@kitn.ai/ui 0.20.1 → 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 +5446 -4937
- 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 +61 -8
- 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/README.md
CHANGED
|
@@ -49,9 +49,10 @@ npm run build # emits dist/kai.es.js
|
|
|
49
49
|
|
|
50
50
|
const chat = document.querySelector('kai-chat');
|
|
51
51
|
|
|
52
|
-
// Rich data is set as JS properties (not HTML attributes)
|
|
52
|
+
// Rich data is set as JS properties (not HTML attributes). A message's
|
|
53
|
+
// content is an ordered `parts` array.
|
|
53
54
|
chat.messages = [
|
|
54
|
-
{ id: '1', role: 'assistant',
|
|
55
|
+
{ id: '1', role: 'assistant', parts: [{ type: 'text', text: 'Hello! How can I help?' }] },
|
|
55
56
|
];
|
|
56
57
|
|
|
57
58
|
// Events are non-bubbling kai-* CustomEvents dispatched on the element
|
|
@@ -130,6 +131,8 @@ The components are deliberately **transport-agnostic**: `<kai-chat>` just render
|
|
|
130
131
|
|
|
131
132
|
<script type="module">
|
|
132
133
|
import '@kitn.ai/ui/elements';
|
|
134
|
+
import { createAssistantStream } from '@kitn.ai/ui/state';
|
|
135
|
+
import { readOpenAIStream, toOpenAIMessages } from '@kitn.ai/ui/wire';
|
|
133
136
|
|
|
134
137
|
// Registration is async (SSR-safe) — wait for the element before using it.
|
|
135
138
|
await customElements.whenDefined('kai-chat');
|
|
@@ -142,14 +145,17 @@ The components are deliberately **transport-agnostic**: `<kai-chat>` just render
|
|
|
142
145
|
if (!text) return;
|
|
143
146
|
|
|
144
147
|
// 1. Show the user message immediately
|
|
145
|
-
const history = [...chat.messages,
|
|
148
|
+
const history = [...chat.messages,
|
|
149
|
+
{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text }] }];
|
|
146
150
|
chat.messages = history;
|
|
147
151
|
chat.value = ''; // clear the input
|
|
148
152
|
chat.loading = true;
|
|
149
153
|
|
|
150
|
-
// 2.
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
// 2. Open the assistant message. createAssistantStream appends it and folds
|
|
155
|
+
// each delta onto the right part, reassigning `messages` every time.
|
|
156
|
+
const stream = createAssistantStream((update) => {
|
|
157
|
+
chat.messages = update(chat.messages);
|
|
158
|
+
});
|
|
153
159
|
|
|
154
160
|
try {
|
|
155
161
|
// In production, replace this URL with your own proxy endpoint.
|
|
@@ -162,59 +168,41 @@ The components are deliberately **transport-agnostic**: `<kai-chat>` just render
|
|
|
162
168
|
body: JSON.stringify({
|
|
163
169
|
model: 'anthropic/claude-sonnet-4',
|
|
164
170
|
stream: true,
|
|
165
|
-
|
|
171
|
+
// The encoder turns the thread into the OpenAI `messages` array,
|
|
172
|
+
// keeping tool calls and their results in the order the model needs.
|
|
173
|
+
messages: toOpenAIMessages(history),
|
|
166
174
|
}),
|
|
167
175
|
});
|
|
168
176
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
let answer = '';
|
|
173
|
-
|
|
174
|
-
while (true) {
|
|
175
|
-
const { value, done } = await reader.read();
|
|
176
|
-
if (done) break;
|
|
177
|
-
buffer += decoder.decode(value, { stream: true });
|
|
178
|
-
|
|
179
|
-
// SSE frames are separated by newlines; each data line is JSON
|
|
180
|
-
const lines = buffer.split('\n');
|
|
181
|
-
buffer = lines.pop(); // keep the partial last line
|
|
182
|
-
for (const line of lines) {
|
|
183
|
-
const s = line.trim();
|
|
184
|
-
if (!s.startsWith('data:')) continue; // skip ": keep-alive" comments
|
|
185
|
-
const payload = s.slice(5).trim();
|
|
186
|
-
if (payload === '[DONE]') continue;
|
|
187
|
-
try {
|
|
188
|
-
const delta = JSON.parse(payload).choices?.[0]?.delta?.content;
|
|
189
|
-
if (!delta) continue;
|
|
190
|
-
answer += delta;
|
|
191
|
-
// Replace the assistant message with a NEW object so the row re-renders
|
|
192
|
-
chat.messages = chat.messages.map((m) =>
|
|
193
|
-
m.id === assistantId ? { ...m, content: answer } : m
|
|
194
|
-
);
|
|
195
|
-
} catch { /* ignore non-JSON keep-alive lines */ }
|
|
196
|
-
}
|
|
197
|
-
}
|
|
177
|
+
// Parses the whole stream: keep-alive comments, multi-line frames,
|
|
178
|
+
// codepoints split across a socket boundary, tool calls, reasoning.
|
|
179
|
+
await readOpenAIStream(res, stream);
|
|
198
180
|
} catch (err) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
);
|
|
181
|
+
// A non-ok response throws WireError before a single chunk is read, so put
|
|
182
|
+
// the reason in the bubble rather than leaving an empty one.
|
|
183
|
+
stream.appendText('Request failed: ' + err.message);
|
|
202
184
|
} finally {
|
|
185
|
+
stream.done();
|
|
203
186
|
chat.loading = false;
|
|
204
187
|
}
|
|
205
188
|
});
|
|
206
189
|
</script>
|
|
207
190
|
```
|
|
208
191
|
|
|
209
|
-
Key point:
|
|
192
|
+
Key point: `chat.messages` has to be reassigned with a **new array containing a new object** for the streaming message on each chunk. That's what triggers the re-render. Mutating the existing object in place won't update the view. `createAssistantStream` is what satisfies that rule for you; if you drive `messages` by hand, you own it.
|
|
193
|
+
|
|
194
|
+
`@kitn.ai/ui/wire` also ships `readAnthropicStream`, the helpers for a multi-round tool loop, and a seam for a custom wire format. See the [wire adapter recipe](https://ui.kitn.ai/guides/recipes/wire-adapter/).
|
|
210
195
|
|
|
211
196
|
### Text-to-speech (TTS)
|
|
212
197
|
|
|
213
198
|
#### Option 1 — Browser-native (zero dependencies)
|
|
214
199
|
|
|
215
|
-
The Web Speech API speaks text with no network call.
|
|
200
|
+
The Web Speech API speaks text with no network call. `readOpenAIStream` resolves with the finished turn, so speak `turn.text` in the example above:
|
|
216
201
|
|
|
217
202
|
```js
|
|
203
|
+
const turn = await readOpenAIStream(res, stream);
|
|
204
|
+
speak(turn.text);
|
|
205
|
+
|
|
218
206
|
function speak(text) {
|
|
219
207
|
if (!('speechSynthesis' in window)) return;
|
|
220
208
|
const utter = new SpeechSynthesisUtterance(text);
|
|
@@ -236,7 +224,19 @@ function speakIncremental(fullText) {
|
|
|
236
224
|
spokenUpTo = lastBreak + 1;
|
|
237
225
|
}
|
|
238
226
|
}
|
|
239
|
-
|
|
227
|
+
|
|
228
|
+
// A sink is a plain object, so wrap it to see the text as it arrives. Everything
|
|
229
|
+
// else passes through untouched.
|
|
230
|
+
let sofar = '';
|
|
231
|
+
const speaking = {
|
|
232
|
+
...stream,
|
|
233
|
+
appendText(delta) {
|
|
234
|
+
sofar += delta;
|
|
235
|
+
speakIncremental(sofar);
|
|
236
|
+
return stream.appendText(delta);
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
await readOpenAIStream(res, speaking);
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
#### Option 2 — Cloud TTS (OpenAI, ElevenLabs, …)
|
|
@@ -268,16 +268,15 @@ You can trigger either option from the streaming completion (auto-read replies)
|
|
|
268
268
|
|
|
269
269
|
## State helpers & hooks
|
|
270
270
|
|
|
271
|
-
`@kitn.ai/ui/state` ships immutable helpers (`appendMessage`, `upsertMessage`, `updateMessage`, `removeMessage`, `
|
|
271
|
+
`@kitn.ai/ui/state` ships immutable helpers (`appendMessage`, `upsertMessage`, `updateMessage`, `removeMessage`, `appendText`, `textMessage`), the part-level folds they build on (`appendTextPart`, `appendReasoningPart`, `upsertToolPart`, `upsertCardPart`), and a streaming handle (`createAssistantStream`) so you don't hand-roll array mutations. React apps get `useKaiChat` (from `@kitn.ai/ui/react`); SolidJS apps get `createKaiChat` (from `@kitn.ai/ui`). Both return a `bind` object to spread directly onto the element:
|
|
272
272
|
|
|
273
273
|
```tsx
|
|
274
274
|
import { Chat, useKaiChat } from '@kitn.ai/ui/react';
|
|
275
|
-
import { createAssistantStream } from '@kitn.ai/ui/state';
|
|
276
275
|
|
|
277
276
|
function App() {
|
|
278
277
|
const chat = useKaiChat({
|
|
279
278
|
async onSubmit({ value }) {
|
|
280
|
-
chat.append({ id: crypto.randomUUID(), role: 'user',
|
|
279
|
+
chat.append({ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: value }] });
|
|
281
280
|
const s = chat.streamAssistant();
|
|
282
281
|
for await (const part of backend(value)) s.appendText(part);
|
|
283
282
|
s.done();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
import { CardHost } from '../primitives/card-contract.js';
|
|
3
|
+
import { ArtifactCardData } from '../primitives/card-data-types.js';
|
|
4
|
+
export type { ArtifactCardData, ArtifactCardEnvelope, ArtifactCardFile, ArtifactCardTab, } from '../primitives/card-data-types.js';
|
|
5
|
+
/** Height the artifact card falls back to. Tall enough that a framed page is
|
|
6
|
+
* actually legible in a thread, short enough to leave the conversation visible. */
|
|
7
|
+
export declare const DEFAULT_ARTIFACT_CARD_HEIGHT = "420px";
|
|
8
|
+
export interface ArtifactCardProps {
|
|
9
|
+
data: ArtifactCardData;
|
|
10
|
+
cardId: string;
|
|
11
|
+
heading?: string;
|
|
12
|
+
host?: CardHost;
|
|
13
|
+
}
|
|
14
|
+
/** Chrome + sizing around `<Artifact>` for the `artifact` card type.
|
|
15
|
+
*
|
|
16
|
+
* WHY A WRAPPER IS REQUIRED, not cosmetic. `<Artifact>`'s root is
|
|
17
|
+
* `flex h-full w-full flex-col` — it is built to FILL a container that already
|
|
18
|
+
* has a height (a resizable panel, a split view). A message thread gives its
|
|
19
|
+
* parts no height at all, so `h-full` resolves against an auto-height parent,
|
|
20
|
+
* the frame computes to ZERO, and the card renders as an invisible nothing.
|
|
21
|
+
* The explicit `height` here is what makes the card visible; `data.height`
|
|
22
|
+
* overrides it.
|
|
23
|
+
*
|
|
24
|
+
* `part`/`data-card-type` are stable handles. `CardRenderer` renders card
|
|
25
|
+
* components bare, and in the web-component path `cardComponentsFromTags` maps a
|
|
26
|
+
* non-overridden built-in straight to its Solid component — so there is no
|
|
27
|
+
* `<kai-artifact>` tag in the DOM to point at. This wrapper is the only stable
|
|
28
|
+
* thing to select, which is what lets a test count rendered artifacts inside
|
|
29
|
+
* `<kai-thread>`'s shadow root.
|
|
30
|
+
*
|
|
31
|
+
* `part="card"` matches the other chromed cards, which get it from `<Card>`;
|
|
32
|
+
* this one hand-rolls its chrome and so states it directly. The artifact-specific
|
|
33
|
+
* handle is `data-card-type`, NOT a second part token: every `::part` name has to
|
|
34
|
+
* be declared in `elements/slots.ts` (the drift guard in `slots.test.ts` enforces
|
|
35
|
+
* it), so adding an `artifact` part is a deliberate public-API decision to make
|
|
36
|
+
* there, not something to smuggle in from a component.
|
|
37
|
+
*
|
|
38
|
+
* `envelope.title` renders as a HEADING above the frame rather than being folded
|
|
39
|
+
* into `displayUrl`: the address field states where the preview is pointing, and
|
|
40
|
+
* overwriting it with a title would make it lie. A heading is also what the four
|
|
41
|
+
* other chromed cards (form/confirm/tasks/choice) already do with `title`.
|
|
42
|
+
*
|
|
43
|
+
* `tab`/`activeFile` are SEEDS, never re-asserted — see their notes on
|
|
44
|
+
* `ArtifactCardData`. A revised envelope must not undo what the user did.
|
|
45
|
+
*
|
|
46
|
+
* The three observation callbacks emit the contract's EXISTING `state` verb —
|
|
47
|
+
* the contract is frozen, and a new kind would force a CARD_CONTRACT_VERSION
|
|
48
|
+
* bump. Each patch key mirrors a `data` field name, so a host can merge the
|
|
49
|
+
* patch straight back into `envelope.data` and re-send it; `addCard` upserts on
|
|
50
|
+
* `envelope.id`, so that round-trip revises the card instead of duplicating it. */
|
|
51
|
+
export declare function ArtifactCard(props: ArtifactCardProps): JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { FileTreeFile } from './file-tree';
|
|
2
|
+
import { FileTreeFile } from './file-tree.js';
|
|
3
3
|
export type ArtifactTab = 'preview' | 'code';
|
|
4
4
|
/** A file the artifact can preview + show source for. */
|
|
5
5
|
export type ArtifactFile = FileTreeFile;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types';
|
|
3
|
-
export type { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types';
|
|
2
|
+
import { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types.js';
|
|
3
|
+
export type { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types.js';
|
|
4
4
|
export declare const getMediaCategory: (data: AttachmentData) => AttachmentMediaCategory;
|
|
5
5
|
export declare const getAttachmentLabel: (data: AttachmentData) => string;
|
|
6
6
|
interface AttachmentsContextValue {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Accessor, JSX } from 'solid-js';
|
|
2
|
-
import { VariantProps } from './variant-bar';
|
|
3
|
-
import { VisualizerSize } from './sizes';
|
|
4
|
-
import { UniformType } from './shader-canvas';
|
|
2
|
+
import { VariantProps } from './variant-bar.js';
|
|
3
|
+
import { VisualizerSize } from './sizes.js';
|
|
4
|
+
import { UniformType } from './shader-canvas.js';
|
|
5
5
|
export type VisualizerVariant = 'bar' | 'grid' | 'radial' | 'wave' | 'aurora' | 'custom';
|
|
6
6
|
export declare function normalizeVariant(input: string | undefined): VisualizerVariant;
|
|
7
7
|
/** A consumer-supplied fragment shader, for `variant="custom"`. */
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { LabLook } from './lab-shaders.js';
|
|
2
|
+
/** The agent states the kit's visualizers respond to, plus manual free play. */
|
|
3
|
+
export type LabState = 'manual' | 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking';
|
|
4
|
+
export declare const LAB_STATES: LabState[];
|
|
5
|
+
/** Every tunable the lab shaders read. Flat on purpose: story args map 1:1. */
|
|
6
|
+
export interface LabParams {
|
|
7
|
+
baseR: number;
|
|
8
|
+
ampIdle: number;
|
|
9
|
+
ampVoice: number;
|
|
10
|
+
radVoice: number;
|
|
11
|
+
sigma: number;
|
|
12
|
+
gain: number;
|
|
13
|
+
f1: number;
|
|
14
|
+
f2: number;
|
|
15
|
+
s1: number;
|
|
16
|
+
s2: number;
|
|
17
|
+
envSpd: number;
|
|
18
|
+
sepSpd: number;
|
|
19
|
+
whiteLo: number;
|
|
20
|
+
whiteHi: number;
|
|
21
|
+
bloomMul: number;
|
|
22
|
+
bloomGain: number;
|
|
23
|
+
delta: number;
|
|
24
|
+
off: number;
|
|
25
|
+
wWidth: number;
|
|
26
|
+
wMin: number;
|
|
27
|
+
fillGain: number;
|
|
28
|
+
edgeGain: number;
|
|
29
|
+
flut: number;
|
|
30
|
+
twistSpd: number;
|
|
31
|
+
warpAmp: number;
|
|
32
|
+
lens: number;
|
|
33
|
+
spec: number;
|
|
34
|
+
tint: number;
|
|
35
|
+
vSpeed: number;
|
|
36
|
+
presence: number;
|
|
37
|
+
gather: number;
|
|
38
|
+
core: number;
|
|
39
|
+
neural: number;
|
|
40
|
+
boltJag: number;
|
|
41
|
+
boltWidth: number;
|
|
42
|
+
boltRate: number;
|
|
43
|
+
}
|
|
44
|
+
/** Hand-tuned in the aurora playground; per-look starting points. */
|
|
45
|
+
export declare const LOOK_DEFAULTS: Record<LabLook, LabParams>;
|
|
46
|
+
export interface LabFrame {
|
|
47
|
+
t: number;
|
|
48
|
+
level: number;
|
|
49
|
+
values: LabParams;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The state choreography from the playground, per frame. Slow targets glide
|
|
53
|
+
* over seconds (presence slowest, so smoke visibly forms and dissipates);
|
|
54
|
+
* tempo runs on an accumulated warped clock, so state changes never jump the
|
|
55
|
+
* animation phase; the ember beats and the bolts fire in real time.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createChoreography(getLook: () => LabLook, getState: () => LabState, getParams: () => LabParams): {
|
|
58
|
+
step: (dt: number) => LabFrame;
|
|
59
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The four lab looks, written for `ShaderCanvas` in the same `mainImage`
|
|
3
|
+
* convention the `custom` variant documents. Every uniform is declared by
|
|
4
|
+
* the canvas from the uniform map (`lab-visualizer.tsx`), never in the body.
|
|
5
|
+
*
|
|
6
|
+
* All four are original clean-room work from the aurora prototyping sessions
|
|
7
|
+
* (see `examples/internal/aurora-playground`, the tuning playground these were
|
|
8
|
+
* born in). Braid and ribbon read the accent through the shared ring pipeline;
|
|
9
|
+
* planet and orb are stationary vessels whose CONTENTS react to state and
|
|
10
|
+
* voice: presence materializes the smoke, gather settles or centers it, the
|
|
11
|
+
* ember pulses while connecting, and thinking fires fractal lightning.
|
|
12
|
+
*/
|
|
13
|
+
/** Three woven strands sharing one wave family; pileups soft-compressed. */
|
|
14
|
+
export declare const BRAID_FRAGMENT = "\nfloat labStroke(float d, float sigma) {\n float q = d / sigma;\n float q2 = q * q;\n float core = exp(-q2 * q2);\n float bq = d / (sigma * uBloomMul);\n float bloom = exp(-bq * bq) * uBloomGain;\n return core + bloom;\n}\n\nvec4 labRingColor(float glow, float bfloor, float bscale, float wcap, vec2 fragCoord) {\n float bright = bfloor + bscale * min(glow, 1.2);\n float white = smoothstep(uWhiteLo, uWhiteHi, glow) * wcap;\n vec3 col = mix(uColor * bright, vec3(1.0), white);\n float alpha = clamp(glow, 0.0, 1.0);\n float n = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);\n alpha = clamp(alpha + (n - 0.5) / 255.0, 0.0, 1.0);\n return vec4(col * alpha, alpha);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 hres = iResolution.xy * 0.5;\n vec2 p = (fragCoord - hres) / hres.y;\n float r = length(p);\n float th = atan(p.y, p.x);\n float t = uT;\n\n float amp = uAmpIdle + uAmpVoice * uLvl;\n float baseR = uBaseR + uRadVoice * uLvl;\n float env = 0.62 + 0.38 * sin(th * 2.0 + t * uEnvSpd + 2.0);\n\n float glow = 0.0;\n for (int i = 0; i < 3; i++) {\n float fi = float(i);\n float a = th + fi * uDelta;\n float tt = t + fi * 1.3;\n float wob = sin(a * uF1 + tt * uS1) * 0.55 + sin(a * uF2 - tt * uS2) * 0.45;\n float ampi = amp * (0.65 + 0.35 * fi);\n float sepMod = 0.5 + 0.5 * sin(th + t * uSepSpd + fi * 1.9);\n float ringR = baseR + (fi - 1.0) * uOff * (0.35 + 1.5 * sepMod) + wob * ampi * env;\n glow += uGain * (0.8 + 0.35 * env) * labStroke(abs(r - ringR), uSigma);\n }\n // three overlapping strands can sum past every threshold; compress so\n // crossings brighten without blowing out to a solid white tube\n glow = glow / (1.0 + 0.35 * glow);\n fragColor = labRingColor(glow, 0.55, 0.65, 0.45, fragCoord);\n}\n";
|
|
15
|
+
/** One ribbon whose width pinches to zero at traveling twist points. */
|
|
16
|
+
export declare const RIBBON_FRAGMENT = "\nfloat labStroke(float d, float sigma) {\n float q = d / sigma;\n float q2 = q * q;\n float core = exp(-q2 * q2);\n float bq = d / (sigma * uBloomMul);\n float bloom = exp(-bq * bq) * uBloomGain;\n return core + bloom;\n}\n\nvec4 labRingColor(float glow, float bfloor, float bscale, float wcap, vec2 fragCoord) {\n float bright = bfloor + bscale * min(glow, 1.2);\n float white = smoothstep(uWhiteLo, uWhiteHi, glow) * wcap;\n vec3 col = mix(uColor * bright, vec3(1.0), white);\n float alpha = clamp(glow, 0.0, 1.0);\n float n = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);\n alpha = clamp(alpha + (n - 0.5) / 255.0, 0.0, 1.0);\n return vec4(col * alpha, alpha);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 hres = iResolution.xy * 0.5;\n vec2 p = (fragCoord - hres) / hres.y;\n float r = length(p);\n float th = atan(p.y, p.x);\n float t = uT;\n\n float amp = uAmpIdle + uAmpVoice * uLvl;\n float baseR = uBaseR + uRadVoice * uLvl;\n float env = 0.62 + 0.38 * sin(th * 2.0 + t * uEnvSpd + 2.0);\n\n float wRaw = sin(th * 2.0 + t * uTwistSpd) * 0.6\n + sin(th * 3.0 - t * uTwistSpd * 0.7 + 1.7) * 0.4;\n float w = (abs(wRaw) * uWWidth + uWMin) * (0.55 + 0.45 * env);\n\n float c = baseR\n + (sin(th * uF1 + t * uS1) * 0.6\n + sin(th * (uF1 + 2.0) - t * uS1 * 0.63 + 2.3) * 0.4) * amp;\n\n float fl = uFlut * (0.5 + 0.9 * uLvl);\n float e1 = c - w + sin(th * uF2 + t * uS2) * fl;\n float e2 = c + w + sin(th * uF2 * 1.3 - t * uS2 * 0.8 + 2.0) * fl;\n\n float lo = min(e1, e2), hi = max(e1, e2);\n float ww = max(hi - lo, 0.004);\n float dens = clamp(uWWidth * 1.2 / ww, 0.4, 2.0);\n\n float box = smoothstep(-uSigma, uSigma, r - lo)\n * (1.0 - smoothstep(-uSigma, uSigma, r - hi));\n float u = clamp((r - lo) / ww, 0.0, 1.0);\n float rim = smoothstep(0.5, 1.0, abs(u - 0.5) * 2.0);\n\n float outside = max(max(lo - r, r - hi), 0.0);\n float bs = uSigma * uBloomMul;\n float halo = exp(-(outside * outside) / (2.0 * bs * bs)) * uBloomGain * dens;\n\n float glow = uGain * uFillGain\n * (box * dens * (1.0 + uEdgeGain * rim) + halo * (1.0 - box));\n fragColor = labRingColor(glow, 0.75, 0.45, 0.55, fragCoord);\n}\n";
|
|
17
|
+
/** Dense churning cloud cover on a stationary glass sphere. */
|
|
18
|
+
export declare const PLANET_FRAGMENT = "\nfloat labHash(vec2 q) {\n return fract(sin(dot(q, vec2(127.1, 311.7))) * 43758.5453);\n}\nfloat labNoise(vec2 q) {\n vec2 i = floor(q);\n vec2 f = fract(q);\n vec2 u = f * f * (3.0 - 2.0 * f);\n float a = labHash(i);\n float b = labHash(i + vec2(1.0, 0.0));\n float c = labHash(i + vec2(0.0, 1.0));\n float d = labHash(i + vec2(1.0, 1.0));\n return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);\n}\nfloat labFbm(vec2 q) {\n float sum = 0.0;\n float amp = 0.5;\n for (int i = 0; i < 4; i++) {\n sum += amp * labNoise(q);\n q *= 2.03;\n amp *= 0.5;\n }\n return sum;\n}\n\nfloat labSegDist(vec2 q, vec2 a, vec2 b) {\n vec2 ab = b - a;\n float h = clamp(dot(q - a, ab) / max(dot(ab, ab), 1.0e-6), 0.0, 1.0);\n return length(q - a - ab * h);\n}\nvec2 labSparkPos(float k, float i, float R) {\n float h1 = labHash(vec2(k * 7.31 + 1.13, i * 3.71 + 0.17));\n float h2 = labHash(vec2(i * 9.13 + 2.29, k * 5.77 + 0.53));\n float av = 6.2831853 * h1;\n float rad = R * 0.85 * sqrt(h2);\n return vec2(cos(av), sin(av)) * rad;\n}\nfloat labBolt(vec2 q, vec2 A, vec2 B, float seed, float R, float life) {\n vec2 ab = B - A;\n float len = max(length(ab), 1.0e-4);\n vec2 dir = ab / len;\n vec2 nrm = vec2(-dir.y, dir.x);\n vec2 w = q - A;\n float u = dot(w, dir) / len;\n float v = dot(w, nrm);\n if (u < -0.05 || u > 1.05 || abs(v) > R * 0.30) return 0.0;\n float uu = clamp(u, 0.0, 1.0);\n float taper = sin(uu * 3.14159265);\n float off1 = (labFbm(vec2(uu * 9.0 + seed * 13.1, seed * 7.7)) - 0.5) * 0.55 * uBoltJag;\n float off2 = (labFbm(vec2(uu * 23.0 + seed * 5.3, seed * 3.9 + 4.2)) - 0.5) * 0.22 * uBoltJag;\n float mainArc = abs(v - (off1 + off2) * len * taper);\n float forkArc = abs(v - (off1 * 0.6 - off2 * 1.8) * len * taper);\n float wdt = R * (0.006 + 0.010 * life) * uBoltWidth;\n float bolt = exp(-pow(mainArc / wdt, 2.0))\n + 0.45 * exp(-pow(mainArc / (wdt * 3.0), 2.0))\n + 0.5 * exp(-pow(forkArc / (wdt * 0.8), 2.0))\n + 0.25 * exp(-pow(forkArc / (wdt * 2.5), 2.0));\n return bolt * taper;\n}\nfloat labNeural(vec2 q, float t, float R) {\n if (uNeural < 0.01) return 0.0;\n float acc = 0.0;\n for (int k = 0; k < 5; k++) {\n float fk = float(k);\n float period = (1.1 + 1.3 * labHash(vec2(fk, 3.3))) / max(uBoltRate, 0.05);\n float cyc = t / period + labHash(vec2(fk, 7.7)) * 7.0;\n float i = floor(cyc);\n float life = fract(cyc);\n float env = smoothstep(0.0, 0.04, life) * exp(-5.0 * life);\n if (env >= 0.004) {\n vec2 pos = labSparkPos(fk, i, R);\n vec2 prev = labSparkPos(fk, i - 1.0, R);\n float seed = labHash(vec2(fk * 3.1, i * 1.7));\n float bolt = labBolt(q, prev, pos, seed, R, life) * env;\n vec2 dp = q - pos;\n vec2 dq = q - prev;\n float tips = (exp(-dot(dp, dp) / (2.0 * R * R * 0.0016))\n + 0.6 * exp(-dot(dq, dq) / (2.0 * R * R * 0.0012))) * env;\n acc += bolt * 1.2 + tips * 0.8;\n }\n }\n return acc * uNeural;\n}\n\nvec4 labRingColor(float glow, float bfloor, float bscale, float wcap, vec2 fragCoord) {\n float bright = bfloor + bscale * min(glow, 1.2);\n float white = smoothstep(uWhiteLo, uWhiteHi, glow) * wcap;\n vec3 col = mix(uColor * bright, vec3(1.0), white);\n float alpha = clamp(glow, 0.0, 1.0);\n float n = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);\n alpha = clamp(alpha + (n - 0.5) / 255.0, 0.0, 1.0);\n return vec4(col * alpha, alpha);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 hres = iResolution.xy * 0.5;\n vec2 p = (fragCoord - hres) / hres.y;\n float t = uT;\n float R = uBaseR * 2.0;\n float d = length(p);\n float mask = 1.0 - smoothstep(R - 0.012, R + 0.004, d);\n float zn = sqrt(max(R * R - d * d, 0.0)) / max(R, 1.0e-4);\n vec2 ps = p / (R * mix(1.0, 0.35 + 0.65 * zn, uLens));\n\n float tt = t * uTwistSpd;\n float sc = uF2 * 0.35;\n float turb = uWarpAmp * (0.5 + 0.8 * uLvl);\n\n float dens = 0.0;\n for (int k = 0; k < 3; k++) {\n float fk = float(k);\n vec2 o = vec2(fk * 7.31, fk * 3.77);\n vec2 pk = ps * (1.0 + fk * 0.18 * (1.0 - zn));\n vec2 q = vec2(\n labFbm(pk * sc * 0.6 + o + vec2(tt * uS1 * 0.55, 0.0)),\n labFbm(pk * sc * 0.6 + o + vec2(5.2, 1.3) - vec2(0.0, tt * uS2 * 0.45)));\n float n = labFbm(pk * sc + turb * 2.0 * (q - 0.5) + o + vec2(tt * 0.28, tt * 0.18));\n dens += (0.45 - fk * 0.1) * n;\n }\n dens = smoothstep(0.30 + (1.0 - uPresence) * 0.40, 0.78, dens);\n dens *= 0.12 + 0.88 * uPresence;\n\n vec2 lp = vec2(cos(tt * 0.23), sin(tt * 0.31)) * R * 0.35;\n vec2 dl = p - lp;\n float smoke = dens * (0.5 + 0.9 * exp(-dot(dl, dl) / (2.0 * R * R * 0.16))) * (0.55 + 0.65 * zn)\n + 0.05 * zn;\n\n float rim = pow(smoothstep(R * 0.62, R, d), 3.0);\n vec2 hp = p - vec2(-0.38, 0.42) * R;\n float spec = exp(-dot(hp, hp) / (2.0 * R * R * 0.004)) * uSpec;\n float core = uCore * exp(-(d * d) / (2.0 * R * R * 0.026));\n float nrl = labNeural(p, tt * 0.6, R);\n\n float glow = uGain * mask\n * (uFillGain * 1.6 * smoke + uEdgeGain * 0.8 * rim + spec + core * 1.3 + nrl * 1.2);\n fragColor = labRingColor(glow, 0.75, 0.45, 0.55, fragCoord);\n}\n";
|
|
19
|
+
/** Luminous smoke sealed in a stationary glass sphere, lit from within. */
|
|
20
|
+
export declare const ORB_FRAGMENT = "\nfloat labHash(vec2 q) {\n return fract(sin(dot(q, vec2(127.1, 311.7))) * 43758.5453);\n}\nfloat labNoise(vec2 q) {\n vec2 i = floor(q);\n vec2 f = fract(q);\n vec2 u = f * f * (3.0 - 2.0 * f);\n float a = labHash(i);\n float b = labHash(i + vec2(1.0, 0.0));\n float c = labHash(i + vec2(0.0, 1.0));\n float d = labHash(i + vec2(1.0, 1.0));\n return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);\n}\nfloat labFbm(vec2 q) {\n float sum = 0.0;\n float amp = 0.5;\n for (int i = 0; i < 4; i++) {\n sum += amp * labNoise(q);\n q *= 2.03;\n amp *= 0.5;\n }\n return sum;\n}\n\nfloat labSegDist(vec2 q, vec2 a, vec2 b) {\n vec2 ab = b - a;\n float h = clamp(dot(q - a, ab) / max(dot(ab, ab), 1.0e-6), 0.0, 1.0);\n return length(q - a - ab * h);\n}\nvec2 labSparkPos(float k, float i, float R) {\n float h1 = labHash(vec2(k * 7.31 + 1.13, i * 3.71 + 0.17));\n float h2 = labHash(vec2(i * 9.13 + 2.29, k * 5.77 + 0.53));\n float av = 6.2831853 * h1;\n float rad = R * 0.85 * sqrt(h2);\n return vec2(cos(av), sin(av)) * rad;\n}\nfloat labBolt(vec2 q, vec2 A, vec2 B, float seed, float R, float life) {\n vec2 ab = B - A;\n float len = max(length(ab), 1.0e-4);\n vec2 dir = ab / len;\n vec2 nrm = vec2(-dir.y, dir.x);\n vec2 w = q - A;\n float u = dot(w, dir) / len;\n float v = dot(w, nrm);\n if (u < -0.05 || u > 1.05 || abs(v) > R * 0.30) return 0.0;\n float uu = clamp(u, 0.0, 1.0);\n float taper = sin(uu * 3.14159265);\n float off1 = (labFbm(vec2(uu * 9.0 + seed * 13.1, seed * 7.7)) - 0.5) * 0.55 * uBoltJag;\n float off2 = (labFbm(vec2(uu * 23.0 + seed * 5.3, seed * 3.9 + 4.2)) - 0.5) * 0.22 * uBoltJag;\n float mainArc = abs(v - (off1 + off2) * len * taper);\n float forkArc = abs(v - (off1 * 0.6 - off2 * 1.8) * len * taper);\n float wdt = R * (0.006 + 0.010 * life) * uBoltWidth;\n float bolt = exp(-pow(mainArc / wdt, 2.0))\n + 0.45 * exp(-pow(mainArc / (wdt * 3.0), 2.0))\n + 0.5 * exp(-pow(forkArc / (wdt * 0.8), 2.0))\n + 0.25 * exp(-pow(forkArc / (wdt * 2.5), 2.0));\n return bolt * taper;\n}\nfloat labNeural(vec2 q, float t, float R) {\n if (uNeural < 0.01) return 0.0;\n float acc = 0.0;\n for (int k = 0; k < 5; k++) {\n float fk = float(k);\n float period = (1.1 + 1.3 * labHash(vec2(fk, 3.3))) / max(uBoltRate, 0.05);\n float cyc = t / period + labHash(vec2(fk, 7.7)) * 7.0;\n float i = floor(cyc);\n float life = fract(cyc);\n float env = smoothstep(0.0, 0.04, life) * exp(-5.0 * life);\n if (env >= 0.004) {\n vec2 pos = labSparkPos(fk, i, R);\n vec2 prev = labSparkPos(fk, i - 1.0, R);\n float seed = labHash(vec2(fk * 3.1, i * 1.7));\n float bolt = labBolt(q, prev, pos, seed, R, life) * env;\n vec2 dp = q - pos;\n vec2 dq = q - prev;\n float tips = (exp(-dot(dp, dp) / (2.0 * R * R * 0.0016))\n + 0.6 * exp(-dot(dq, dq) / (2.0 * R * R * 0.0012))) * env;\n acc += bolt * 1.2 + tips * 0.8;\n }\n }\n return acc * uNeural;\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 hres = iResolution.xy * 0.5;\n vec2 p = (fragCoord - hres) / hres.y;\n float t = uT;\n float R = uBaseR * 2.0;\n float d = length(p);\n float mask = 1.0 - smoothstep(R - 0.010, R + 0.004, d);\n float zn = sqrt(max(R * R - d * d, 0.0)) / max(R, 1.0e-4);\n float inner = 1.0 - clamp(d / max(R, 1.0e-4), 0.0, 1.0);\n vec2 ps = p / (R * mix(1.0, 0.35 + 0.65 * zn, uLens));\n\n float tt = t * uTwistSpd;\n // rigid drift plus a BOUNDED oscillating stir: shear that accumulates\n // forever winds any pattern into a spiral\n float ang = tt * 0.04\n + (sin(tt * 0.11) * 0.55 + sin(tt * 0.047 + 1.7) * 0.35) * inner;\n float ca = cos(ang), sa = sin(ang);\n ps = mat2(ca, -sa, sa, ca) * ps;\n\n float sc = uF2 * 0.18;\n float tau0 = 0.50 + 0.06 * uLvl;\n float bw = mix(0.16, 0.12, uLvl);\n\n vec2 lp = vec2(cos(tt * 0.21), sin(tt * 0.27)) * R * 0.42;\n vec2 L = normalize(lp - p + vec2(1.0e-4, 0.0));\n\n float dens = 0.0;\n float lit = 0.0;\n for (int k = 0; k < 2; k++) {\n float fk = float(k);\n vec2 o = vec2(fk * 9.17, fk * 5.13);\n float scale = sc * (1.0 + 0.7 * fk);\n vec2 pk = ps * (1.0 + fk * 0.24 * (1.0 - zn)) + o;\n\n // bounded orbit, never a straight scroll: the coverage pattern wanders\n // around home instead of migrating off one side of the vessel\n float cn = labFbm(pk * 0.9 + vec2(sin(tt * 0.041), -cos(tt * 0.033)) * 0.8);\n float covLo = 0.62 - 0.30 * uFillGain + 0.03 * uLvl\n + (1.0 - uPresence) * 0.45;\n float bottomness = clamp(-p.y / max(R, 1.0e-4) * 1.3 - 0.1, 0.0, 1.0);\n float gBias = 0.16 * inner * uPresence\n + max(uGather, 0.0) * 0.30 * inner\n + max(-uGather, 0.0) * 0.38 * bottomness;\n float cov = smoothstep(covLo, covLo + 0.28, cn + gBias);\n\n vec2 flow = vec2(-pk.y, pk.x) * 0.5 + vec2(0.0, 0.4);\n float cyc = tt * 0.10 * uS1 * (1.0 + 0.6 * fk);\n float ph0 = fract(cyc + 0.35 * cn);\n float ph1 = fract(cyc + 0.35 * cn + 0.5);\n float w0 = 1.0 - abs(1.0 - 2.0 * ph0);\n\n vec2 w2 = vec2(labFbm(pk * scale * 0.5 + vec2(sin(tt * 0.09 * uS2), cos(tt * 0.075 * uS2)) * 0.9),\n labFbm(pk * scale * 0.5 + vec2(3.7, 8.1) + vec2(cos(tt * 0.065 * uS2), sin(tt * 0.083 * uS2)) * 0.9));\n vec2 qw = pk * scale + uWarpAmp * 3.0 * (w2 - 0.5);\n\n float n = mix(labFbm(qw - flow * 1.2 * ph1), labFbm(qw - flow * 1.2 * ph0), w0);\n float sgn = 2.0 * n - 1.0;\n float ridge = 1.0 - abs(sgn);\n ridge *= ridge;\n float band = smoothstep(tau0 - bw, tau0, n) * (1.0 - smoothstep(tau0, tau0 + bw, n));\n float dk = cov * (band * (0.6 + 0.5 * ridge) + 0.12 * n * cov);\n dens += (0.60 - 0.22 * fk) * dk;\n\n float nL = labFbm(qw + L * 0.5);\n lit += clamp((nL - n) * 3.0, 0.0, 1.0) * dk;\n }\n dens *= 1.0 - smoothstep(0.72, 0.97, d / max(R, 1.0e-4));\n dens *= (0.45 + 1.25 * uFillGain) * (1.0 + 0.25 * uLvl);\n dens *= 0.08 + 0.92 * uPresence;\n float dEff = clamp(dens, 0.0, 1.5) * (0.5 + 0.5 * zn);\n float aSmoke = 1.0 - exp(-2.6 * dEff);\n\n float rL = length(p - lp) / R;\n float G = 1.0 / (1.0 + 2.0 * rL + 8.0 * rL * rL);\n float act = 0.7 + 0.8 * uLvl;\n\n vec3 albedo = mix(vec3(0.84, 0.87, 0.92), uColor, uTint);\n vec3 body = albedo * (0.30 + 0.55 * exp(-1.4 * dEff))\n + uColor * (lit * 0.5 + dEff * G * 1.1) * act;\n vec3 bgIn = uColor * 0.05 * zn;\n vec3 col = mix(bgIn, body, aSmoke)\n + uColor * G * act * 0.18 * zn;\n\n float rim = pow(smoothstep(R * 0.66, R, d), 3.0);\n vec2 hp = p - vec2(-0.38, 0.42) * R;\n float spec = exp(-dot(hp, hp) / (2.0 * R * R * 0.004)) * uSpec;\n float core = uCore * exp(-(d * d) / (2.0 * R * R * 0.022));\n float nrl = labNeural(p, tt * 0.6, R);\n col += uColor * rim * uEdgeGain * 0.7 + vec3(spec) + uColor * core * 1.5\n + uColor * nrl * (0.7 + 0.6 * aSmoke);\n\n col *= uGain * mask;\n float alpha = clamp((aSmoke * 0.9 + G * act * 0.15 * zn + core + nrl * 0.55\n + rim * uEdgeGain * 0.5 + spec + 0.03 * zn) * uGain, 0.0, 1.0) * mask;\n float nz = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);\n alpha = clamp(alpha + (nz - 0.5) / 255.0, 0.0, 1.0);\n fragColor = vec4(col, alpha);\n}\n";
|
|
21
|
+
export type LabLook = 'braid' | 'ribbon' | 'planet' | 'orb';
|
|
22
|
+
export declare const LAB_FRAGMENTS: Record<LabLook, string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
import { LabLook } from './lab-shaders.js';
|
|
3
|
+
import { LabParams, LabState } from './lab-choreography.js';
|
|
4
|
+
export interface LabVisualizerProps {
|
|
5
|
+
look: LabLook;
|
|
6
|
+
state?: LabState;
|
|
7
|
+
color?: string;
|
|
8
|
+
/** Square canvas edge in px. */
|
|
9
|
+
size?: number;
|
|
10
|
+
/** Overrides on the look's tuned defaults. */
|
|
11
|
+
params?: Partial<LabParams>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs one lab look through the same `ShaderCanvas` the shipped variants use,
|
|
15
|
+
* with the playground's state choreography driving the uniforms per frame.
|
|
16
|
+
* While `speaking`, a baked loudness loop stands in for a live voice.
|
|
17
|
+
*/
|
|
18
|
+
export declare function LabVisualizer(props: LabVisualizerProps): JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { VisualizerState } from '../../primitives/visualizer-sequences';
|
|
3
|
-
import { ShaderVariantProps } from './index';
|
|
2
|
+
import { VisualizerState } from '../../primitives/visualizer-sequences.js';
|
|
3
|
+
import { ShaderVariantProps } from './index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Per-state uniform targets, straight from fact sheet section 5's measured
|
|
6
6
|
* table (`.superpowers/sdd/2026-08-07-audio-visualizers/reference/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { VisualizerState } from '../../primitives/visualizer-sequences';
|
|
3
|
-
import { VisualizerSize } from './sizes';
|
|
2
|
+
import { VisualizerState } from '../../primitives/visualizer-sequences.js';
|
|
3
|
+
import { VisualizerSize } from './sizes.js';
|
|
4
4
|
/** Props every DOM variant takes. The dispatcher supplies all of them. */
|
|
5
5
|
export interface VariantProps {
|
|
6
6
|
state: VisualizerState;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { UniformSpec } from './shader-canvas';
|
|
3
|
-
import { ShaderVariantProps } from './index';
|
|
2
|
+
import { UniformSpec } from './shader-canvas.js';
|
|
3
|
+
import { ShaderVariantProps } from './index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Uniforms every custom shader receives without asking: the standard set
|
|
6
6
|
* (`uColor`, `uIntensity`, `uSpeed`, `uComplexity`) plus the audio pair that
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
2
|
export interface CardFallbackProps {
|
|
3
|
-
/** The
|
|
3
|
+
/** The envelope type, shown to aid debugging. */
|
|
4
4
|
type: string;
|
|
5
5
|
/** The envelope id (for parity with cards; not displayed). */
|
|
6
6
|
cardId?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Why this card could not render, when the type WAS known but the data was not
|
|
9
|
+
* usable. Carries the failing field paths verbatim, e.g.
|
|
10
|
+
* `(root).actions: fewer than minItems 1`.
|
|
11
|
+
*
|
|
12
|
+
* Absent means the older case: an unrecognized type. The two are told apart by
|
|
13
|
+
* this prop rather than by a mode flag so a caller cannot ask for the diagnostic
|
|
14
|
+
* and forget to supply the diagnosis.
|
|
15
|
+
*/
|
|
16
|
+
reason?: string;
|
|
7
17
|
}
|
|
8
|
-
/** Inert, themed fallback for
|
|
18
|
+
/** Inert, themed fallback for a card that cannot render. Emits nothing itself:
|
|
9
19
|
* the dispatcher emits the contract `error` event alongside rendering this. */
|
|
10
20
|
export declare function CardFallback(props: CardFallbackProps): JSX.Element;
|
|
@@ -1,13 +1,74 @@
|
|
|
1
1
|
import { JSX } from 'solid-js';
|
|
2
|
-
import { CardEnvelope } from '../primitives/card-contract';
|
|
3
|
-
import { CardComponentMap } from '../primitives/card-registry';
|
|
2
|
+
import { CardEnvelope } from '../primitives/card-contract.js';
|
|
3
|
+
import { CardComponentMap } from '../primitives/card-registry.js';
|
|
4
|
+
/**
|
|
5
|
+
* Consumer card schemas by envelope type: `{ 'pricing-table': pricingSchema }`.
|
|
6
|
+
*
|
|
7
|
+
* `object`, NOT `JsonSchema`, and that is measured rather than lazy. A real schema
|
|
8
|
+
* is either imported from a `.json` file — where TypeScript widens `"type": "object"`
|
|
9
|
+
* to `string`, which `JsonSchema`'s literal union rejects — or written out with the
|
|
10
|
+
* `$schema` / `title` / `description` / `additionalProperties` keywords that
|
|
11
|
+
* `JsonSchema` does not describe at all, which excess-property checking rejects.
|
|
12
|
+
* Both are the ordinary case, so the tighter type would make the normal way of
|
|
13
|
+
* supplying a schema a compile error. `src/schemas/index.ts` widens `CardSchema`
|
|
14
|
+
* for exactly this reason and says so at length (lines 92-110 there).
|
|
15
|
+
*
|
|
16
|
+
* The value is handed straight to `validateCardData`, which reads only the keywords
|
|
17
|
+
* `validateAgainstSchema` implements and ignores the rest.
|
|
18
|
+
*/
|
|
19
|
+
export type CardSchemaMap = Record<string, object>;
|
|
4
20
|
export interface CardRendererProps {
|
|
5
21
|
envelope: CardEnvelope;
|
|
6
22
|
/** Add/override type→component entries (merged over the built-ins). */
|
|
7
23
|
types?: CardComponentMap;
|
|
24
|
+
/**
|
|
25
|
+
* JSON Schemas for the card types this app renders, keyed by `envelope.type`.
|
|
26
|
+
* `createCardRegistry(...).validationSchemas` is exactly this shape.
|
|
27
|
+
*
|
|
28
|
+
* The companion of `types`, and the half that was missing: `types` says WHAT
|
|
29
|
+
* draws a `pricing-table`, `schemas` says what a VALID one looks like. Without it
|
|
30
|
+
* the kit checks its own seven built-ins and leaves the developer's own card —
|
|
31
|
+
* the one the app actually cares about — as the only unvalidated thing on screen.
|
|
32
|
+
*
|
|
33
|
+
* A schema given here WINS over a built-in of the same name, matching
|
|
34
|
+
* `mergeCardComponents`, where the consumer's entry is spread over ours.
|
|
35
|
+
*/
|
|
36
|
+
schemas?: CardSchemaMap;
|
|
37
|
+
/**
|
|
38
|
+
* Validate `envelope.data` against the built-in schema for `envelope.type` before
|
|
39
|
+
* rendering. Default `true`.
|
|
40
|
+
*
|
|
41
|
+
* ON IN PRODUCTION TOO, DELIBERATELY. The obvious alternative, stripping the check
|
|
42
|
+
* from production builds, inverts the point: a model emitting a bad shape is a
|
|
43
|
+
* production failure mode, so stripping it means the developer's USERS get the
|
|
44
|
+
* broken card while the developer's laptop looks fine. The cost is the projected
|
|
45
|
+
* schema data for all seven card types, measured by building this package twice
|
|
46
|
+
* (once with the projection stubbed to `{}`) rather than estimated: +834 B gzip on
|
|
47
|
+
* `dist/index.js` and +775 B gzip on the elements register bundle. That is below
|
|
48
|
+
* the noise floor of a package that already ships a Solid runtime and `marked`.
|
|
49
|
+
*
|
|
50
|
+
* Set `false` to opt out. A type with no schema at all — no built-in, and none
|
|
51
|
+
* supplied through `schemas` — is never validated either way.
|
|
52
|
+
*/
|
|
53
|
+
validateCards?: boolean;
|
|
8
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* True when the consumer registered a schema for this type.
|
|
57
|
+
*
|
|
58
|
+
* Spelled out rather than left to `validateCardData` because it is a GATE, not a
|
|
59
|
+
* lookup: a consumer schema is the one thing that authorises validating a renderer
|
|
60
|
+
* that is not ours. `hasOwnProperty` (not `in`) so a type named `toString` cannot
|
|
61
|
+
* pick up `Object.prototype`, and the `typeof` check so a `{ 'x': null }` entry
|
|
62
|
+
* reads as "not registered" instead of matching and then validating against
|
|
63
|
+
* nothing. The same predicate lives in elements/cards.tsx for `<kai-cards>`; the
|
|
64
|
+
* two dispatchers already duplicate this rule (they compare component identity vs
|
|
65
|
+
* tag identity), so keep them in step.
|
|
66
|
+
*/
|
|
67
|
+
export declare function hasConsumerSchema(schemas: CardSchemaMap | undefined, type: string): boolean;
|
|
9
68
|
export declare function CardRenderer(props: CardRendererProps): JSX.Element;
|
|
10
69
|
/** Function sugar: renderCard(env) ≡ <CardRenderer envelope={env} />. */
|
|
11
70
|
export declare function renderCard(envelope: CardEnvelope, opts?: {
|
|
12
71
|
types?: CardComponentMap;
|
|
72
|
+
schemas?: CardSchemaMap;
|
|
73
|
+
validateCards?: boolean;
|
|
13
74
|
}): JSX.Element;
|
|
@@ -16,4 +16,7 @@ export interface ChatContainerScrollAnchorProps extends JSX.HTMLAttributes<HTMLD
|
|
|
16
16
|
ref?: HTMLDivElement | ((el: HTMLDivElement) => void);
|
|
17
17
|
}
|
|
18
18
|
declare function ChatContainerScrollAnchor(props: ChatContainerScrollAnchorProps): JSX.Element;
|
|
19
|
+
/** `ChatContainer` is the exported alias of `ChatContainerRoot`; its props type
|
|
20
|
+
* is aliased too, so the name a consumer imports always has a matching Props. */
|
|
21
|
+
export type ChatContainerProps = ChatContainerRootProps;
|
|
19
22
|
export { ChatContainerRoot as ChatContainer, ChatContainerRoot, ChatContainerContent, ChatContainerScrollAnchor, };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DropdownController } from '../ui/dropdown';
|
|
2
|
-
import { SearchFilters } from '../types';
|
|
1
|
+
import { DropdownController } from '../ui/dropdown.js';
|
|
2
|
+
import { SearchFilters } from '../types.js';
|
|
3
3
|
export interface ChatScopePickerProps {
|
|
4
4
|
currentLabel: string;
|
|
5
5
|
onScopeChange: (filters: SearchFilters | undefined) => void;
|