@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
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
// createCardRegistry: the one place an app writes down which cards it renders.
|
|
2
|
+
//
|
|
3
|
+
// WHY THIS EXISTS, AND WHY IT IS NOT "A WAY TO REGISTER CUSTOM CARDS"
|
|
4
|
+
// ------------------------------------------------------------------
|
|
5
|
+
// Registering a custom card already worked: `chat.cardTypes = { 'pricing-table':
|
|
6
|
+
// 'my-pricing-table' }` goes through `mergeCardTags` and has since the card contract
|
|
7
|
+
// landed, and `cardTools({ 'pricing-table': schema }, { provider })` already emitted
|
|
8
|
+
// `kai_pricing-table` before this file existed. Measured on 4b33cd8, both halves of
|
|
9
|
+
// the custom round trip passed already. Nothing here unlocks them.
|
|
10
|
+
//
|
|
11
|
+
// Two things did not work, and they are what this file is for.
|
|
12
|
+
//
|
|
13
|
+
// 1. NOTHING TIED THE TWO ENDS TOGETHER. `cardTypes` is a per-element PROP, so there
|
|
14
|
+
// is no ambient registry a backend route could consult. The developer wrote their
|
|
15
|
+
// card types on the client, wrote them again in the tool definitions, and nothing
|
|
16
|
+
// made the two agree. This is the fifth-copy problem the emit contract exists to
|
|
17
|
+
// kill, one layer up from the schema itself.
|
|
18
|
+
//
|
|
19
|
+
// 2. THE MODEL WAS TOLD ABOUT ALL SEVEN BUILT-INS REGARDLESS. `cardTools({ provider })`
|
|
20
|
+
// has no way to say "this app renders confirm and choice, do not offer the model an
|
|
21
|
+
// artifact card". Every request paid for seven tool definitions, five of which the
|
|
22
|
+
// app had no intention of using, and the model could pick one of them.
|
|
23
|
+
//
|
|
24
|
+
// So the goal is not the seam, which existed. It is to make the NORMAL path go through
|
|
25
|
+
// the seam, so it cannot rot the way it did once already: the only end-to-end user of
|
|
26
|
+
// `cardTypes` was a workaround in the conformance spike that registered `spike-artifact`
|
|
27
|
+
// because the kit had no artifact card, and when the kit grew one the workaround was
|
|
28
|
+
// correctly deleted and the coverage went with it. Coverage that exists only because
|
|
29
|
+
// something is missing is coverage on a timer.
|
|
30
|
+
//
|
|
31
|
+
// WHAT `use` DOES AND DOES NOT NARROW
|
|
32
|
+
// -----------------------------------
|
|
33
|
+
// `use` narrows what the MODEL IS TOLD ABOUT. It does not narrow what renders, and it
|
|
34
|
+
// must not be read as if it did. `mergeCardTags`/`mergeCardComponents` union the seven
|
|
35
|
+
// built-ins in unconditionally (consumer overrides win), so an app declaring
|
|
36
|
+
// `use: ['confirm']` still renders a `choice` envelope if one arrives. That is the
|
|
37
|
+
// right behaviour: an envelope that turns up from somewhere else should draw, not
|
|
38
|
+
// degrade to a fallback because it was left off a tool list. Narrowing rendering would
|
|
39
|
+
// be a `primitives/card-registry.tsx` change, and a worse product.
|
|
40
|
+
//
|
|
41
|
+
// Likewise `registry.validate()` covers all seven built-ins regardless of `use`.
|
|
42
|
+
// Validation is about what ARRIVED, not about what was offered.
|
|
43
|
+
//
|
|
44
|
+
// NO `toolPrefix`, DELIBERATELY
|
|
45
|
+
// -----------------------------
|
|
46
|
+
// The plan reserves `createCardRegistry({ toolPrefix })` and this file does not ship
|
|
47
|
+
// it, for the reason tool-defs.ts already gives: the inverse (`cardTypeFromToolName`)
|
|
48
|
+
// hard-codes `kai_`, so a prefix honoured on the emit side alone would generate tools
|
|
49
|
+
// the loop's parser cannot recognise, and the card would vanish into `runTool` with no
|
|
50
|
+
// error anywhere. Worse than not having the option. It lands in both directions in one
|
|
51
|
+
// change, or not at all.
|
|
52
|
+
//
|
|
53
|
+
// SERVER-SAFE
|
|
54
|
+
// -----------
|
|
55
|
+
// This module is imported by a backend route (it is half the point) so it stays free
|
|
56
|
+
// of DOM and of the Solid runtime. `CardComponentMap`/`CardTagMap` are TYPE imports
|
|
57
|
+
// and erase completely; the values in `components` are passed through untouched and
|
|
58
|
+
// never called here. `verify:ssr` imports the built entry under the `node` condition
|
|
59
|
+
// and proves the runtime half.
|
|
60
|
+
//
|
|
61
|
+
// It does NOT prove the compile-time half, and the two imports below are deliberately
|
|
62
|
+
// aimed at `.ts` modules rather than at primitives/card-registry.tsx for a reason no
|
|
63
|
+
// runtime guard can see. A type import still has to RESOLVE, and a Node/no-DOM project
|
|
64
|
+
// (tsconfig.mcp.json: `lib: ["ESNext"]`, no `jsx`) cannot resolve a `.tsx` at all:
|
|
65
|
+
// pointing either of these back at card-registry.tsx puts TS6142 on this exact line on
|
|
66
|
+
// any unbuilt tree. Both types are re-exported from card-registry.tsx, so importing
|
|
67
|
+
// them from there LOOKS equivalent and compiles everywhere else. It is not. The check
|
|
68
|
+
// that tells the difference is `tsc --noEmit -p tsconfig.mcp.json` with no dist/
|
|
69
|
+
// present; see the header of primitives/card-component-types.ts.
|
|
70
|
+
|
|
71
|
+
import type { CardComponentMap } from '../primitives/card-component-types';
|
|
72
|
+
import type { CardTagMap } from '../primitives/card-tags';
|
|
73
|
+
import type { JsonSchema } from '../primitives/card-validate';
|
|
74
|
+
import {
|
|
75
|
+
validateCardData,
|
|
76
|
+
type CardValidationReport,
|
|
77
|
+
} from '../primitives/card-validate-cards';
|
|
78
|
+
import { cardSchemas, isCardSchemaName, type CardSchema, type CardSchemaName } from './index';
|
|
79
|
+
import type { CardToolSource } from './tool-defs';
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* One custom card type: what the model should be told, and what draws it.
|
|
83
|
+
*
|
|
84
|
+
* Every member is optional because the useful combinations genuinely differ. A
|
|
85
|
+
* web-component consumer supplies `tag`; a Solid consumer supplies `component`; a
|
|
86
|
+
* backend-only registry (a route that builds tool definitions and never renders)
|
|
87
|
+
* supplies neither. Only `schema` carries a warning when absent, and the reason is on
|
|
88
|
+
* {@link CardRegistrySpec.onIncomplete}.
|
|
89
|
+
*/
|
|
90
|
+
export interface CustomCardSpec {
|
|
91
|
+
/**
|
|
92
|
+
* The JSON Schema for this card type's `data` payload.
|
|
93
|
+
*
|
|
94
|
+
* Used for BOTH ends: `cardTools()` projects it into a tool definition, and
|
|
95
|
+
* `registry.validate()` checks arriving data against it. Authored form is fine, with
|
|
96
|
+
* the descriptions left in: the projection strips what a provider cannot take, and
|
|
97
|
+
* the validator ignores keywords it does not implement.
|
|
98
|
+
*
|
|
99
|
+
* That last clause is a real limit, not a formality, and it is the same one the
|
|
100
|
+
* built-ins carry. `validateAgainstSchema` has no applicators, so `allOf`, `anyOf`,
|
|
101
|
+
* `oneOf`, `if`/`then`, `$ref` and `additionalProperties` in a custom schema are
|
|
102
|
+
* carried faithfully to the model and NOT enforced on the way back. See the
|
|
103
|
+
* NOT_ENFORCED table at the top of primitives/card-validate-schemas.ts.
|
|
104
|
+
*/
|
|
105
|
+
readonly schema?: CardSchema | JsonSchema;
|
|
106
|
+
/** The custom element that renders it, e.g. `'my-pricing-table'`. Feeds `mergeCardTags`. */
|
|
107
|
+
readonly tag?: string;
|
|
108
|
+
/** The Solid component that renders it. Feeds `mergeCardComponents`. */
|
|
109
|
+
readonly component?: CardComponentMap[string];
|
|
110
|
+
/**
|
|
111
|
+
* One sentence of PURPOSE, addressed to the model: when should it reach for this
|
|
112
|
+
* card? Not a restatement of the shape, which the schema already carries.
|
|
113
|
+
*
|
|
114
|
+
* Falls back to the schema's own `description`, then to a generated stub. See
|
|
115
|
+
* `describe()` in tool-defs.ts.
|
|
116
|
+
*/
|
|
117
|
+
readonly description?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** What to do about a custom card type registered with no schema. */
|
|
121
|
+
export type IncompletePolicy = 'warn' | 'throw' | 'silent';
|
|
122
|
+
|
|
123
|
+
export interface CardRegistrySpec {
|
|
124
|
+
/**
|
|
125
|
+
* Which BUILT-IN card types this app renders, and therefore which ones the model is
|
|
126
|
+
* offered.
|
|
127
|
+
*
|
|
128
|
+
* Omitted means all seven, which is what `cardTools({ provider })` already does and
|
|
129
|
+
* what `<kai-chat>` actually renders, so the default describes reality rather than
|
|
130
|
+
* quietly shrinking it. `use: []` means none of ours: an app whose generative UI is
|
|
131
|
+
* entirely its own.
|
|
132
|
+
*/
|
|
133
|
+
readonly use?: readonly CardSchemaName[];
|
|
134
|
+
/** This app's own card types, keyed by `CardEnvelope.type`. */
|
|
135
|
+
readonly custom?: Readonly<Record<string, CustomCardSpec>>;
|
|
136
|
+
/**
|
|
137
|
+
* How a schema-less custom type is reported. Default `'warn'`.
|
|
138
|
+
*
|
|
139
|
+
* `'throw'` for a build or a CI check that wants the hole to be fatal; `'silent'` for
|
|
140
|
+
* a card type your own code populates and a model never emits, where the warning is
|
|
141
|
+
* noise. `'silent'` is deliberately a word you have to type, so the acknowledgement is
|
|
142
|
+
* greppable instead of implied.
|
|
143
|
+
*/
|
|
144
|
+
readonly onIncomplete?: IncompletePolicy;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* An app's card types, in the one shape both ends take.
|
|
149
|
+
*
|
|
150
|
+
* ```ts
|
|
151
|
+
* // cards.ts, imported by the client AND the route
|
|
152
|
+
* export const cards = createCardRegistry({
|
|
153
|
+
* use: ['confirm', 'choice'],
|
|
154
|
+
* custom: { 'pricing-table': { schema: pricingSchema, tag: 'my-pricing-table' } },
|
|
155
|
+
* });
|
|
156
|
+
*
|
|
157
|
+
* // client
|
|
158
|
+
* chat.cardTypes = cards.tags;
|
|
159
|
+
* // server
|
|
160
|
+
* const tools = cardTools(cards, { provider: 'anthropic' });
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* Extends {@link CardToolSource}, so `cardTools(registry, opts)` takes it with no
|
|
164
|
+
* signature change on that side. That interface was left open for exactly this.
|
|
165
|
+
*/
|
|
166
|
+
export interface CardRegistry extends CardToolSource {
|
|
167
|
+
/**
|
|
168
|
+
* The card types the model is offered, keyed by type. `use`d built-ins plus every
|
|
169
|
+
* custom type that HAS a schema. What `cardTools()` reads.
|
|
170
|
+
*/
|
|
171
|
+
readonly schemas: Readonly<Record<string, CardSchema>>;
|
|
172
|
+
/** Purpose sentences for custom types (and for any built-in a custom entry overrode). */
|
|
173
|
+
readonly descriptions: Readonly<Record<string, string>>;
|
|
174
|
+
/**
|
|
175
|
+
* Custom `type -> tag`, for `chat.cardTypes` / `mergeCardTags`.
|
|
176
|
+
*
|
|
177
|
+
* Custom entries ONLY. The built-in tags are not restated here because
|
|
178
|
+
* `mergeCardTags` adds all seven itself; listing the `use`d ones would read as if the
|
|
179
|
+
* others had been excluded, which is not what happens.
|
|
180
|
+
*/
|
|
181
|
+
readonly tags: CardTagMap;
|
|
182
|
+
/** Custom `type -> Solid component`, for `<CardRenderer types>` / `mergeCardComponents`. */
|
|
183
|
+
readonly components: CardComponentMap;
|
|
184
|
+
/** Every type this registry declares, schema-less ones included. Built-ins first. */
|
|
185
|
+
readonly types: readonly string[];
|
|
186
|
+
/** The built-in types in `use`, in `cardSchemas` order. */
|
|
187
|
+
readonly builtIn: readonly CardSchemaName[];
|
|
188
|
+
/** The custom types, in declaration order, schema-less ones included. */
|
|
189
|
+
readonly custom: readonly string[];
|
|
190
|
+
/** Custom types with no schema: registered, renderable, invisible to the model. */
|
|
191
|
+
readonly incomplete: readonly string[];
|
|
192
|
+
/**
|
|
193
|
+
* Custom schemas in the shape `validateCardData`'s third argument takes, so a caller
|
|
194
|
+
* that already has a `validateCardData` call can widen it without going through
|
|
195
|
+
* {@link CardRegistry.validate}.
|
|
196
|
+
*/
|
|
197
|
+
readonly validationSchemas: Readonly<Record<string, JsonSchema>>;
|
|
198
|
+
/**
|
|
199
|
+
* Validate an envelope's `data` against this registry's schema for `type`.
|
|
200
|
+
*
|
|
201
|
+
* Custom schemas win over a built-in of the same name, matching `mergeCardTags`'s
|
|
202
|
+
* consumer-wins rule. `null` means there was nothing to check (a type with no
|
|
203
|
+
* schema anywhere), which is kept distinguishable from a clean pass so a caller
|
|
204
|
+
* cannot report the second as the first.
|
|
205
|
+
*
|
|
206
|
+
* Covers all seven built-ins regardless of `use`: see the module header.
|
|
207
|
+
*/
|
|
208
|
+
validate(type: string, data: unknown): CardValidationReport | null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const isRecord = (v: unknown): v is Record<string, unknown> =>
|
|
212
|
+
typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
213
|
+
|
|
214
|
+
function warnIncomplete(incomplete: readonly string[]): string {
|
|
215
|
+
const names = incomplete.map((t) => `"${t}"`).join(', ');
|
|
216
|
+
const plural = incomplete.length === 1 ? 'type' : 'types';
|
|
217
|
+
return [
|
|
218
|
+
`createCardRegistry: ${incomplete.length} custom card ${plural} registered with no \`schema\`: ${names}.`,
|
|
219
|
+
' They will still RENDER (their tag/component is registered), but:',
|
|
220
|
+
' - cardTools() skips them, so the model is never told the type exists and will never emit one;',
|
|
221
|
+
' - registry.validate() returns null for them, so nothing checks what does arrive.',
|
|
222
|
+
' A card type the model is never told about and that nothing validates is a silent hole.',
|
|
223
|
+
' Fix: give each one a `schema`. If the type is populated by your own code and never by a',
|
|
224
|
+
" model, say so with `onIncomplete: 'silent'`; use `onIncomplete: 'throw'` to make it fatal.",
|
|
225
|
+
].join('\n');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Declare the card types this app renders, once, for both ends.
|
|
230
|
+
*
|
|
231
|
+
* @throws {TypeError} if `use` names something that is not a built-in card type (a
|
|
232
|
+
* typo, or a custom type that belongs in `custom`), if a custom key is empty, or if
|
|
233
|
+
* `onIncomplete: 'throw'` and a custom type has no schema.
|
|
234
|
+
*/
|
|
235
|
+
export function createCardRegistry(spec: CardRegistrySpec = {}): CardRegistry {
|
|
236
|
+
// A plain typeof check rather than the `isRecord` predicate used everywhere else in
|
|
237
|
+
// this file. `isRecord` narrows to `Record<string, unknown>`, and intersecting that
|
|
238
|
+
// with `CardRegistrySpec` makes the INDEX SIGNATURE win over the declared members:
|
|
239
|
+
// `spec.use` becomes `unknown`, `spec.use ?? […]` becomes `{}`, and the rest of the
|
|
240
|
+
// function loses its types while still compiling in places. Measured, not guessed —
|
|
241
|
+
// it produced seven `tsc` errors on the first pass of this file.
|
|
242
|
+
if (typeof spec !== 'object' || spec === null || Array.isArray(spec)) {
|
|
243
|
+
throw new TypeError('createCardRegistry: expected a spec object, e.g. createCardRegistry({ use: ["confirm"] })');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// `cardSchemas` is read HERE, inside the function, for the reason `builtInSchemas()`
|
|
247
|
+
// in tool-defs.ts spells out: ./index re-exports this module and this module imports
|
|
248
|
+
// back out of it, a real ESM cycle that is safe only while the read happens after
|
|
249
|
+
// both module bodies have evaluated. Do not hoist it to a module-scope const.
|
|
250
|
+
const builtInSource = cardSchemas;
|
|
251
|
+
|
|
252
|
+
const useList = spec.use ?? (Object.keys(builtInSource) as CardSchemaName[]);
|
|
253
|
+
const unknownUse = useList.filter((t) => !isCardSchemaName(t));
|
|
254
|
+
if (unknownUse.length > 0) {
|
|
255
|
+
throw new TypeError(
|
|
256
|
+
`createCardRegistry: \`use\` names ${unknownUse.length} type(s) that are not built in: ` +
|
|
257
|
+
`${unknownUse.map((t) => `"${t}"`).join(', ')}. ` +
|
|
258
|
+
`The built-in types are ${Object.keys(builtInSource).join(', ')}. ` +
|
|
259
|
+
'A card type of your own goes in `custom`, with its schema, not in `use`.',
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Deduped and put back into cardSchemas order, so two registries listing the same
|
|
264
|
+
// types in a different order produce byte-identical tool arrays.
|
|
265
|
+
const used = new Set(useList);
|
|
266
|
+
const builtIn = (Object.keys(builtInSource) as CardSchemaName[]).filter((t) => used.has(t));
|
|
267
|
+
|
|
268
|
+
const customSpecs = spec.custom ?? {};
|
|
269
|
+
const customNames = Object.keys(customSpecs);
|
|
270
|
+
const emptyKey = customNames.find((n) => n.trim().length === 0);
|
|
271
|
+
if (emptyKey !== undefined) {
|
|
272
|
+
throw new TypeError('createCardRegistry: a custom card type name must be a non-empty string; it becomes `CardEnvelope.type` and the `kai_<type>` tool name.');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const schemas: Record<string, CardSchema> = {};
|
|
276
|
+
for (const type of builtIn) schemas[type] = builtInSource[type];
|
|
277
|
+
|
|
278
|
+
const descriptions: Record<string, string> = {};
|
|
279
|
+
const tags: CardTagMap = {};
|
|
280
|
+
const components: CardComponentMap = {};
|
|
281
|
+
const validationSchemas: Record<string, JsonSchema> = {};
|
|
282
|
+
const incomplete: string[] = [];
|
|
283
|
+
|
|
284
|
+
for (const type of customNames) {
|
|
285
|
+
const entry: CustomCardSpec = customSpecs[type];
|
|
286
|
+
// Same reason as the `spec` check above: narrowing with `isRecord` here would swap
|
|
287
|
+
// `CustomCardSpec`'s members for an index signature and lose `component`'s type.
|
|
288
|
+
if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {
|
|
289
|
+
throw new TypeError(`createCardRegistry: custom card type "${type}" must be an object, e.g. { schema, tag }.`);
|
|
290
|
+
}
|
|
291
|
+
// A custom entry OVERRIDES a built-in of the same name rather than colliding with
|
|
292
|
+
// it, matching mergeCardTags/mergeCardComponents where the consumer wins. That is
|
|
293
|
+
// how you replace our confirm card with yours and still get one tool definition.
|
|
294
|
+
if (isRecord(entry.schema)) {
|
|
295
|
+
schemas[type] = entry.schema as CardSchema;
|
|
296
|
+
validationSchemas[type] = entry.schema as JsonSchema;
|
|
297
|
+
} else {
|
|
298
|
+
// No schema: keep it out of `schemas` so `cardTools` skips it with no special
|
|
299
|
+
// case over there, and record it so the policy below can speak up.
|
|
300
|
+
//
|
|
301
|
+
// The `delete` is not dead code. It fires when a custom entry SHADOWS a `use`d
|
|
302
|
+
// built-in without supplying a schema (`use: ['confirm']` plus
|
|
303
|
+
// `custom: { confirm: { tag: 'my-confirm' } }`). Keeping our confirm schema there
|
|
304
|
+
// would hand the model a shape describing OUR card while the developer's card
|
|
305
|
+
// renders it, which is the drift this whole contract exists to prevent. Dropping
|
|
306
|
+
// it instead puts the type in `incomplete`, where it gets said out loud.
|
|
307
|
+
delete schemas[type];
|
|
308
|
+
incomplete.push(type);
|
|
309
|
+
}
|
|
310
|
+
if (typeof entry.tag === 'string' && entry.tag.length > 0) tags[type] = entry.tag;
|
|
311
|
+
if (typeof entry.component === 'function') components[type] = entry.component;
|
|
312
|
+
if (typeof entry.description === 'string' && entry.description.length > 0) {
|
|
313
|
+
descriptions[type] = entry.description;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (incomplete.length > 0) {
|
|
318
|
+
const policy: IncompletePolicy = spec.onIncomplete ?? 'warn';
|
|
319
|
+
const message = warnIncomplete(incomplete);
|
|
320
|
+
if (policy === 'throw') throw new TypeError(message);
|
|
321
|
+
// WHY THIS WARNS UNCONDITIONALLY RATHER THAN ONLY IN DEV.
|
|
322
|
+
// ------------------------------------------------------
|
|
323
|
+
// There is no `process.env.NODE_ENV` / `import.meta.env` convention anywhere in
|
|
324
|
+
// this package's src/, and the emit-contract plan rejected introducing one for
|
|
325
|
+
// exactly this shape of thing: a stripping contract has to hold across seven
|
|
326
|
+
// consumer bundlers on a PRE-BUILT dist, where substitution into node_modules is
|
|
327
|
+
// not guaranteed, and getting it wrong means the developer's laptop looks fine
|
|
328
|
+
// while production is silently the broken one. The same argument applies here,
|
|
329
|
+
// and the cost side is far smaller than it was there: a registry is built ONCE at
|
|
330
|
+
// module load, not per render, so this is one line per process and not a hot path.
|
|
331
|
+
// `onIncomplete: 'silent'` is the escape hatch, and it is a word you have to type.
|
|
332
|
+
//
|
|
333
|
+
// `!== 'silent'` rather than `=== 'warn'`, so an unrecognised policy is LOUD.
|
|
334
|
+
// TypeScript rejects one, but this is shipped JS a consumer can call untyped, and
|
|
335
|
+
// `onIncomplete: 'quiet'` reaching the silent branch would be a typo that disables
|
|
336
|
+
// the warning about a silent hole. Defaulting the unknown case to noise is the only
|
|
337
|
+
// direction that fails safe.
|
|
338
|
+
if (policy !== 'silent') console.warn(message);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const frozenValidationSchemas = Object.freeze({ ...validationSchemas });
|
|
342
|
+
|
|
343
|
+
return Object.freeze({
|
|
344
|
+
schemas: Object.freeze(schemas),
|
|
345
|
+
descriptions: Object.freeze(descriptions),
|
|
346
|
+
tags: Object.freeze(tags),
|
|
347
|
+
components: Object.freeze(components),
|
|
348
|
+
types: Object.freeze([...builtIn, ...customNames]),
|
|
349
|
+
builtIn: Object.freeze(builtIn),
|
|
350
|
+
custom: Object.freeze([...customNames]),
|
|
351
|
+
incomplete: Object.freeze([...incomplete]),
|
|
352
|
+
validationSchemas: frozenValidationSchemas,
|
|
353
|
+
validate: (type: string, data: unknown) => validateCardData(type, data, frozenValidationSchemas),
|
|
354
|
+
});
|
|
355
|
+
}
|