@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
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Integration, Archetype } from './types';
|
|
2
|
+
import openai from './integrations/openai';
|
|
3
|
+
import anthropic from './integrations/anthropic';
|
|
2
4
|
import openrouter from './integrations/openrouter';
|
|
3
5
|
import vercelAiSdk from './integrations/vercel-ai-sdk';
|
|
4
6
|
import langgraph from './integrations/langgraph';
|
|
@@ -10,7 +12,22 @@ import pydanticAi from './integrations/pydantic-ai';
|
|
|
10
12
|
import mock from './integrations/mock';
|
|
11
13
|
import { archetypes as _archetypes } from './archetypes';
|
|
12
14
|
|
|
15
|
+
// The surface axis for the scaffolder's gate, derived from the presets above.
|
|
16
|
+
// Re-exported here because `scripts/verify-scaffold-compiles.mjs` bundles this
|
|
17
|
+
// module for its axes and must not reach past the registry for one of them.
|
|
18
|
+
export {
|
|
19
|
+
BASE_COMPONENT,
|
|
20
|
+
listCapabilityGroups,
|
|
21
|
+
listSurfaceProbes,
|
|
22
|
+
type CapabilityGroup,
|
|
23
|
+
type SurfaceProbe,
|
|
24
|
+
} from './archetypes';
|
|
25
|
+
|
|
26
|
+
// Order is the order a scaffolding agent reads them in. `openai` and `anthropic`
|
|
27
|
+
// lead because they are the two keys a developer is most likely to already hold.
|
|
13
28
|
export const integrations: Integration[] = [
|
|
29
|
+
openai,
|
|
30
|
+
anthropic,
|
|
14
31
|
openrouter,
|
|
15
32
|
vercelAiSdk,
|
|
16
33
|
langgraph,
|
|
@@ -3,9 +3,96 @@ import { z } from 'zod';
|
|
|
3
3
|
export const Category = z.enum(['provider', 'gateway', 'framework', 'harness', 'mock']);
|
|
4
4
|
export const Language = z.enum(['ts', 'python']);
|
|
5
5
|
export const StreamFormat = z.enum(['openai-sse', 'ai-sdk', 'native']);
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The scaffold's target.
|
|
8
|
+
*
|
|
9
|
+
* Two of these are NOT web-component consumers, and the difference is load-bearing:
|
|
10
|
+
* - `angular` consumes `kai-*` like vue/svelte/html, but needs
|
|
11
|
+
* `CUSTOM_ELEMENTS_SCHEMA` and binds arrays/objects with `[prop]="…"`.
|
|
12
|
+
* - `solid` consumes the SolidJS components DIRECTLY from the `@kitn.ai/ui`
|
|
13
|
+
* root entry. The kit is authored in Solid, so routing a Solid consumer
|
|
14
|
+
* through the custom-element facade would ship the Solid runtime twice and
|
|
15
|
+
* cross a reactive-context boundary for nothing.
|
|
16
|
+
*/
|
|
17
|
+
export const Framework = z.enum(['html', 'react', 'next', 'vue', 'svelte', 'angular', 'solid', 'fastapi', 'express', 'worker', 'tanstack-start']);
|
|
7
18
|
export const Placement = z.enum(['side', 'full-page', 'docked-widget', 'inline']);
|
|
8
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Whether this integration's SECRET may sit in the browser bundle.
|
|
22
|
+
*
|
|
23
|
+
* Read `'needs-proxy'` as "a server hop is mandatory" and `'frontend-safe'` as
|
|
24
|
+
* "the browser may call the upstream itself". This is the flag `create-kai`
|
|
25
|
+
* consults before it decides where a key goes, so getting it wrong in the
|
|
26
|
+
* permissive direction writes an API key into client code. There is deliberately
|
|
27
|
+
* no default and no boolean: the refinement below REJECTS an integration that
|
|
28
|
+
* declares neither, because "absent" must never read as "safe".
|
|
29
|
+
*
|
|
30
|
+
* `'needs-proxy'` covers two cases, and the second is easy to miss:
|
|
31
|
+
* 1. a secret. The route holds a key, so a static bundle cannot.
|
|
32
|
+
* 2. a server-only CAPABILITY. `pi` spawns a local process; no key is involved
|
|
33
|
+
* and a browser still cannot do it.
|
|
34
|
+
*
|
|
35
|
+
* `'frontend-safe'` is the narrow claim: nothing secret AND no server-only
|
|
36
|
+
* capability. Two integrations qualify, and both were read off their routes —
|
|
37
|
+
* `ollama` fetches `localhost:11434` with no auth header at all, and `mock`
|
|
38
|
+
* ships no route to reach.
|
|
39
|
+
*
|
|
40
|
+
* Do not infer this from the provider's name. A provider with a CORS-friendly
|
|
41
|
+
* public endpoint and one that requires a proxy look identical from outside; only
|
|
42
|
+
* the route says which it is. That is the same lesson `forwardsFromClient` and
|
|
43
|
+
* `clientToolFormat` were each added to record.
|
|
44
|
+
*/
|
|
45
|
+
export const KeyExposure = z.enum(['frontend-safe', 'needs-proxy']);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The packages an app must install BEYOND `@kitn.ai/ui` to run this
|
|
49
|
+
* integration's route.
|
|
50
|
+
*
|
|
51
|
+
* Derived once, here, from the route's own import statements, so the CLI never
|
|
52
|
+
* has to re-parse route source to find them. Today this fact only exists as prose
|
|
53
|
+
* in `runNote`, which no installer can read.
|
|
54
|
+
*
|
|
55
|
+
* The rule, enforced by `registry.test.ts`: `npm` is exactly the set of
|
|
56
|
+
* bare-module specifiers imported by the TS route sources, normalised to package
|
|
57
|
+
* names (`@langchain/core/tools` counts as `@langchain/core`), minus `node:`
|
|
58
|
+
* builtins and minus `@kitn.ai/ui` itself, which every scaffold already depends
|
|
59
|
+
* on. `pip` is a superset of the python route's imports, because a Python app
|
|
60
|
+
* also needs its ASGI server (`uvicorn`), which nothing imports.
|
|
61
|
+
*
|
|
62
|
+
* Type-only packages (`@types/*`) are not listed: nothing imports them, so the
|
|
63
|
+
* rule cannot see them, and the frameworks that need them already carry them.
|
|
64
|
+
*/
|
|
65
|
+
export const DepsSchema = z.object({
|
|
66
|
+
npm: z.array(z.string()).default([]),
|
|
67
|
+
pip: z.array(z.string()).default([]),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* An env var name that holds a secret rather than an address.
|
|
72
|
+
*
|
|
73
|
+
* Anchored at the END, which is the whole precision of it: `CF_API_TOKEN` and
|
|
74
|
+
* `AI_GATEWAY_API_KEY` match, while `CF_ACCOUNT_ID` and `MASTRA_URL` do not.
|
|
75
|
+
* `MASTRA_URL` is the case that stops this being a proxy for "declares any env
|
|
76
|
+
* var at all" — a base URL is not a credential.
|
|
77
|
+
*
|
|
78
|
+
* This is a SAFETY NET over the declaration, never its source. Three integrations
|
|
79
|
+
* (`langgraph`, `vercel-ai-sdk`, `pydantic-ai`) hold a key their route source
|
|
80
|
+
* never names, because the SDK reads the env var itself; their `envVars` is what
|
|
81
|
+
* catches them here, and nothing but the author reading the route would have.
|
|
82
|
+
*
|
|
83
|
+
* Exported because the scaffolder names the secrets back at the developer in its
|
|
84
|
+
* run note ("OPENAI_API_KEY stays on the server"). That sentence and the
|
|
85
|
+
* refinement below have to agree about which env vars are secret, so there is one
|
|
86
|
+
* pattern rather than two free to drift apart.
|
|
87
|
+
*/
|
|
88
|
+
export const SECRET_ENV_VAR = /(?:KEY|TOKEN|SECRET|PASSWORD)$/;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A credential written into a request from route source. The second alternative
|
|
92
|
+
* is Anthropic's spelling, which is not an `Authorization` header at all.
|
|
93
|
+
*/
|
|
94
|
+
const AUTH_HEADER = /Authorization\s*:|['"]x-api-key['"]\s*:/i;
|
|
95
|
+
|
|
9
96
|
export const IntegrationSchema = z.object({
|
|
10
97
|
id: z.string(),
|
|
11
98
|
title: z.string(),
|
|
@@ -14,9 +101,150 @@ export const IntegrationSchema = z.object({
|
|
|
14
101
|
streamFormat: StreamFormat,
|
|
15
102
|
envVars: z.array(z.string()).default([]),
|
|
16
103
|
routeTemplates: z.record(z.string(), z.string()), // keyed by Framework value → code string
|
|
104
|
+
/**
|
|
105
|
+
* The backend as ONE web-standard handler, `(Request) => Response`, written as
|
|
106
|
+
* a complete `async function chatHandler(request: Request)` declaration.
|
|
107
|
+
*
|
|
108
|
+
* WHY THIS EXISTS. `routeTemplates` is keyed by framework, and in practice
|
|
109
|
+
* every TS integration only ever filled in `next`. Everything else fell
|
|
110
|
+
* through to it, so a svelte scaffold emitted a Next.js `export async function
|
|
111
|
+
* POST(req)` — which TYPECHECKS under SvelteKit and then throws
|
|
112
|
+
* `req.json is not a function` on the first submit, because SvelteKit calls
|
|
113
|
+
* `POST(event)`. vue and html got the same snippet with nowhere to put it.
|
|
114
|
+
*
|
|
115
|
+
* The handler BODY is portable; only the few lines that declare the route
|
|
116
|
+
* differ per framework. So integrations write the body once here and the
|
|
117
|
+
* scaffolder wraps it (see `WEB_ROUTE_ADAPTERS` in mcp/tools/scaffold.ts).
|
|
118
|
+
* `routeTemplates` stays for routes that genuinely cannot be expressed this
|
|
119
|
+
* way: a Worker using an `env` binding, an Express `(req, res)` bridge, a
|
|
120
|
+
* FastAPI service.
|
|
121
|
+
*
|
|
122
|
+
* An exact `routeTemplates[framework]` still wins over this.
|
|
123
|
+
*/
|
|
124
|
+
webRoute: z.string().optional(),
|
|
17
125
|
streamMapping: z.string(), // prose: how the stream maps to messages
|
|
18
126
|
runNote: z.string(),
|
|
19
127
|
docsSlug: z.string(),
|
|
128
|
+
/**
|
|
129
|
+
* The request-body fields this integration's ROUTE reads off the client and
|
|
130
|
+
* forwards upstream. Anything not listed is owned by the route or by the agent
|
|
131
|
+
* behind it.
|
|
132
|
+
*
|
|
133
|
+
* The scaffolder emits an editable const for a field only when it appears
|
|
134
|
+
* here, and that is the whole point: `model` used to be emitted whenever a
|
|
135
|
+
* route template contained the substring 'model', which is true of any
|
|
136
|
+
* template that so much as writes `model: 'llama3.2'`, so four integrations
|
|
137
|
+
* shipped an editable const their route threw away. The mirror-image bug is a
|
|
138
|
+
* `tools` array that never gets sent, which leaves kai-tool a panel no code
|
|
139
|
+
* path can populate.
|
|
140
|
+
*
|
|
141
|
+
* Empty by default, so a new integration emits nothing until its route really
|
|
142
|
+
* does forward the field.
|
|
143
|
+
*/
|
|
144
|
+
forwardsFromClient: z.array(z.enum(['model', 'tools'])).default([]),
|
|
145
|
+
/**
|
|
146
|
+
* The tool-definition envelope this integration's ROUTE expects to find in the
|
|
147
|
+
* `tools` array the client POSTs. Required exactly when `forwardsFromClient`
|
|
148
|
+
* includes `'tools'`, and meaningless otherwise.
|
|
149
|
+
*
|
|
150
|
+
* WHY THIS IS DECLARED AND NOT DERIVED. It used to be looked up from
|
|
151
|
+
* `streamFormat`, and that is a category error: `streamFormat` describes the
|
|
152
|
+
* shape of the RESPONSE stream, while the tool envelope is a REQUEST concern.
|
|
153
|
+
* The two only appeared to agree because every integration that forwarded
|
|
154
|
+
* tools happened to be `openai-sse`. `anthropic` is where the conflation
|
|
155
|
+
* becomes visible — it is `streamFormat: 'native'`, which says nothing about
|
|
156
|
+
* request shape, and the old table mapped `native` to null.
|
|
157
|
+
*
|
|
158
|
+
* And keying on the integration's PROVIDER would be wrong too, which is the
|
|
159
|
+
* part worth reading the route before assuming: `anthropic`'s handler converts
|
|
160
|
+
* the array itself (`toAnthropicTools` reads `raw.function.name` /
|
|
161
|
+
* `.function.parameters`), so it wants `'openai'` here. Handing it Anthropic's
|
|
162
|
+
* own `{ name, input_schema }` shape would yield tools with a blank name. Only
|
|
163
|
+
* the route knows what it accepts, so only the integration can state it — the
|
|
164
|
+
* same reason `forwardsFromClient` lives here rather than being sniffed out of
|
|
165
|
+
* the route source.
|
|
166
|
+
*
|
|
167
|
+
* Optional in the type, mandatory in practice: the refinement below rejects an
|
|
168
|
+
* integration that forwards tools without one. There is deliberately no
|
|
169
|
+
* default — a default is how a tools array with no card in it ships silently.
|
|
170
|
+
*/
|
|
171
|
+
clientToolFormat: z.enum(['openai', 'anthropic', 'jsonschema']).optional(),
|
|
172
|
+
/** See {@link DepsSchema}. Empty is a real answer: a fetch-only route needs nothing. */
|
|
173
|
+
deps: DepsSchema.default({ npm: [], pip: [] }),
|
|
174
|
+
/**
|
|
175
|
+
* See {@link KeyExposure}. Optional in the TYPE only so the refinement below
|
|
176
|
+
* owns the error message — Zod skips refinements when the base object already
|
|
177
|
+
* failed, so a plain required field would report "Invalid input" and this is
|
|
178
|
+
* the one field where the reader needs to be told what is at stake.
|
|
179
|
+
*/
|
|
180
|
+
keyExposure: KeyExposure.optional(),
|
|
181
|
+
}).superRefine((integration, ctx) => {
|
|
182
|
+
// Enforced against the real catalog by `registry.test.ts`, which parses every
|
|
183
|
+
// integration through this schema. A new host that forwards tools therefore
|
|
184
|
+
// cannot reach the scaffolder undeclared: it fails at the catalog boundary,
|
|
185
|
+
// before any emit path has to decide what to do about it.
|
|
186
|
+
if (integration.forwardsFromClient.includes('tools') && integration.clientToolFormat === undefined) {
|
|
187
|
+
ctx.addIssue({
|
|
188
|
+
code: z.ZodIssueCode.custom,
|
|
189
|
+
path: ['clientToolFormat'],
|
|
190
|
+
message:
|
|
191
|
+
`integration '${integration.id}' forwards a 'tools' array but declares no clientToolFormat. ` +
|
|
192
|
+
`State the envelope its route expects: 'openai' ({ type: 'function', function: { parameters } }), ` +
|
|
193
|
+
`'anthropic' ({ name, input_schema }), or 'jsonschema' ({ name, description, schema }). ` +
|
|
194
|
+
`Read the route's own handler to decide — a route that CONVERTS the array server-side wants the ` +
|
|
195
|
+
`shape it converts FROM, not its own provider's.`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ---- keyExposure ----
|
|
200
|
+
//
|
|
201
|
+
// Two checks, and the split matters. The first refuses SILENCE. The second
|
|
202
|
+
// refuses a specific LIE, and only ever in the dangerous direction: it can
|
|
203
|
+
// turn a 'frontend-safe' claim into an error, never the reverse. Declaring
|
|
204
|
+
// 'needs-proxy' where a proxy was not strictly required costs a server hop;
|
|
205
|
+
// declaring 'frontend-safe' where it was required costs the key.
|
|
206
|
+
|
|
207
|
+
if (integration.keyExposure === undefined) {
|
|
208
|
+
ctx.addIssue({
|
|
209
|
+
code: z.ZodIssueCode.custom,
|
|
210
|
+
path: ['keyExposure'],
|
|
211
|
+
message:
|
|
212
|
+
`integration '${integration.id}' declares no keyExposure. State whether its SECRET may reach the ` +
|
|
213
|
+
`browser bundle: 'needs-proxy' (a key, or a server-only capability such as spawning a process, so ` +
|
|
214
|
+
`the CLI must keep it behind a server) or 'frontend-safe' (nothing secret and nothing server-only, ` +
|
|
215
|
+
`so the browser may call the upstream directly). Read the route to decide, not the provider's name: ` +
|
|
216
|
+
`a public CORS-friendly endpoint and one that requires a proxy are indistinguishable from outside. ` +
|
|
217
|
+
`There is no default on purpose — a missing flag read as "safe" is how an API key ships in client code.`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (integration.keyExposure === 'frontend-safe') {
|
|
222
|
+
const secrets = integration.envVars.filter((name) => SECRET_ENV_VAR.test(name));
|
|
223
|
+
if (secrets.length > 0) {
|
|
224
|
+
ctx.addIssue({
|
|
225
|
+
code: z.ZodIssueCode.custom,
|
|
226
|
+
path: ['keyExposure'],
|
|
227
|
+
message:
|
|
228
|
+
`integration '${integration.id}' claims keyExposure 'frontend-safe' but declares the secret env ` +
|
|
229
|
+
`var(s) ${secrets.join(', ')}. A frontend bundle is public, so that combination puts a key in ` +
|
|
230
|
+
`client code. Use 'needs-proxy'.`,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const routeSources = [
|
|
235
|
+
...Object.values(integration.routeTemplates),
|
|
236
|
+
...(integration.webRoute ? [integration.webRoute] : []),
|
|
237
|
+
];
|
|
238
|
+
if (routeSources.some((code) => AUTH_HEADER.test(code))) {
|
|
239
|
+
ctx.addIssue({
|
|
240
|
+
code: z.ZodIssueCode.custom,
|
|
241
|
+
path: ['keyExposure'],
|
|
242
|
+
message:
|
|
243
|
+
`integration '${integration.id}' claims keyExposure 'frontend-safe' but its route sends an ` +
|
|
244
|
+
`authorization header, so it holds a credential a browser bundle must not. Use 'needs-proxy'.`,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
20
248
|
});
|
|
21
249
|
export type Integration = z.infer<typeof IntegrationSchema>;
|
|
22
250
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// src/components/artifact-card.tsx
|
|
2
|
+
// The `artifact` built-in card: chrome + sizing around <Artifact>, plus the
|
|
3
|
+
// bridge from its observation callbacks onto the frozen Card Contract.
|
|
4
|
+
import { createUniqueId, untrack, Show, type JSX } from 'solid-js';
|
|
5
|
+
import type { CardHost } from '../primitives/card-contract';
|
|
6
|
+
import { Artifact } from './artifact';
|
|
7
|
+
|
|
8
|
+
// `ArtifactCardData` is AUTHORED IN ../primitives/card-data-types.ts, along with
|
|
9
|
+
// `ArtifactCardFile` — the same declaration `FileTree`/`Artifact` use, which is
|
|
10
|
+
// why nothing here restates the file shape. See the note in confirm-card.tsx, or
|
|
11
|
+
// that file's header, for why the card payload types left a `.tsx` and why they
|
|
12
|
+
// are `type` aliases. Re-exported here unchanged.
|
|
13
|
+
|
|
14
|
+
import type { ArtifactCardData } from '../primitives/card-data-types';
|
|
15
|
+
|
|
16
|
+
export type {
|
|
17
|
+
ArtifactCardData,
|
|
18
|
+
ArtifactCardEnvelope,
|
|
19
|
+
ArtifactCardFile,
|
|
20
|
+
ArtifactCardTab,
|
|
21
|
+
} from '../primitives/card-data-types';
|
|
22
|
+
|
|
23
|
+
/** Height the artifact card falls back to. Tall enough that a framed page is
|
|
24
|
+
* actually legible in a thread, short enough to leave the conversation visible. */
|
|
25
|
+
export const DEFAULT_ARTIFACT_CARD_HEIGHT = '420px';
|
|
26
|
+
|
|
27
|
+
function resolveHeight(height: number | string | undefined): string {
|
|
28
|
+
if (typeof height === 'number') return `${height}px`;
|
|
29
|
+
if (typeof height === 'string' && height.trim() !== '') return height;
|
|
30
|
+
return DEFAULT_ARTIFACT_CARD_HEIGHT;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ArtifactCardProps {
|
|
34
|
+
data: ArtifactCardData;
|
|
35
|
+
cardId: string;
|
|
36
|
+
heading?: string;
|
|
37
|
+
host?: CardHost;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Chrome + sizing around `<Artifact>` for the `artifact` card type.
|
|
41
|
+
*
|
|
42
|
+
* WHY A WRAPPER IS REQUIRED, not cosmetic. `<Artifact>`'s root is
|
|
43
|
+
* `flex h-full w-full flex-col` — it is built to FILL a container that already
|
|
44
|
+
* has a height (a resizable panel, a split view). A message thread gives its
|
|
45
|
+
* parts no height at all, so `h-full` resolves against an auto-height parent,
|
|
46
|
+
* the frame computes to ZERO, and the card renders as an invisible nothing.
|
|
47
|
+
* The explicit `height` here is what makes the card visible; `data.height`
|
|
48
|
+
* overrides it.
|
|
49
|
+
*
|
|
50
|
+
* `part`/`data-card-type` are stable handles. `CardRenderer` renders card
|
|
51
|
+
* components bare, and in the web-component path `cardComponentsFromTags` maps a
|
|
52
|
+
* non-overridden built-in straight to its Solid component — so there is no
|
|
53
|
+
* `<kai-artifact>` tag in the DOM to point at. This wrapper is the only stable
|
|
54
|
+
* thing to select, which is what lets a test count rendered artifacts inside
|
|
55
|
+
* `<kai-thread>`'s shadow root.
|
|
56
|
+
*
|
|
57
|
+
* `part="card"` matches the other chromed cards, which get it from `<Card>`;
|
|
58
|
+
* this one hand-rolls its chrome and so states it directly. The artifact-specific
|
|
59
|
+
* handle is `data-card-type`, NOT a second part token: every `::part` name has to
|
|
60
|
+
* be declared in `elements/slots.ts` (the drift guard in `slots.test.ts` enforces
|
|
61
|
+
* it), so adding an `artifact` part is a deliberate public-API decision to make
|
|
62
|
+
* there, not something to smuggle in from a component.
|
|
63
|
+
*
|
|
64
|
+
* `envelope.title` renders as a HEADING above the frame rather than being folded
|
|
65
|
+
* into `displayUrl`: the address field states where the preview is pointing, and
|
|
66
|
+
* overwriting it with a title would make it lie. A heading is also what the four
|
|
67
|
+
* other chromed cards (form/confirm/tasks/choice) already do with `title`.
|
|
68
|
+
*
|
|
69
|
+
* `tab`/`activeFile` are SEEDS, never re-asserted — see their notes on
|
|
70
|
+
* `ArtifactCardData`. A revised envelope must not undo what the user did.
|
|
71
|
+
*
|
|
72
|
+
* The three observation callbacks emit the contract's EXISTING `state` verb —
|
|
73
|
+
* the contract is frozen, and a new kind would force a CARD_CONTRACT_VERSION
|
|
74
|
+
* bump. Each patch key mirrors a `data` field name, so a host can merge the
|
|
75
|
+
* patch straight back into `envelope.data` and re-send it; `addCard` upserts on
|
|
76
|
+
* `envelope.id`, so that round-trip revises the card instead of duplicating it. */
|
|
77
|
+
export function ArtifactCard(props: ArtifactCardProps): JSX.Element {
|
|
78
|
+
const headingId = createUniqueId();
|
|
79
|
+
// Read ONCE, non-reactively: these seed the view and must not be re-asserted
|
|
80
|
+
// when a revision replaces the envelope. See ArtifactCardData.activeFile.
|
|
81
|
+
const seedTab = untrack(() => props.data.tab);
|
|
82
|
+
const seedActiveFile = untrack(() => props.data.activeFile);
|
|
83
|
+
const patch = (p: Record<string, unknown>) =>
|
|
84
|
+
props.host?.emit({ kind: 'state', cardId: props.cardId, patch: p });
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
part="card"
|
|
89
|
+
data-card-type="artifact"
|
|
90
|
+
data-card-id={props.cardId}
|
|
91
|
+
role="group"
|
|
92
|
+
aria-labelledby={props.heading ? headingId : undefined}
|
|
93
|
+
aria-label={props.heading ? undefined : 'Artifact'}
|
|
94
|
+
style={{ height: resolveHeight(props.data.height) }}
|
|
95
|
+
class="flex w-full flex-col overflow-hidden rounded-xl border border-border bg-card"
|
|
96
|
+
>
|
|
97
|
+
<Show when={props.heading}>
|
|
98
|
+
<h3
|
|
99
|
+
id={headingId}
|
|
100
|
+
class="shrink-0 truncate border-b border-border px-3 py-2 text-sm font-medium text-foreground"
|
|
101
|
+
>
|
|
102
|
+
{props.heading}
|
|
103
|
+
</h3>
|
|
104
|
+
</Show>
|
|
105
|
+
<div class="min-h-0 flex-1">
|
|
106
|
+
<Artifact
|
|
107
|
+
src={props.data.src}
|
|
108
|
+
files={props.data.files}
|
|
109
|
+
defaultTab={seedTab}
|
|
110
|
+
activeFile={seedActiveFile}
|
|
111
|
+
displayUrl={props.data.displayUrl}
|
|
112
|
+
iframeTitle={props.heading ? `${props.heading} preview` : 'Artifact preview'}
|
|
113
|
+
onNavigate={(url) => patch({ src: url })}
|
|
114
|
+
onTabChange={(tab) => patch({ tab })}
|
|
115
|
+
onFileSelect={(path) => patch({ activeFile: path })}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -326,6 +326,15 @@ export function AudioVisualizer(props: AudioVisualizerProps): JSX.Element {
|
|
|
326
326
|
void load()
|
|
327
327
|
.then((m) => { if (!cancelled) setShader(() => m.default); })
|
|
328
328
|
.catch((err) => {
|
|
329
|
+
// Same `cancelled` check as the `.then` above. The two handlers were
|
|
330
|
+
// asymmetric: a rejection arriving after this effect was disposed
|
|
331
|
+
// still warned, even though there is no longer a component to fall
|
|
332
|
+
// back to and nothing the message could usefully tell anyone. Worse,
|
|
333
|
+
// the warning surfaces against whatever is running by the time the
|
|
334
|
+
// rejection lands rather than against the mount that asked for the
|
|
335
|
+
// chunk, so it reads as a fault in unrelated code -- in a test run,
|
|
336
|
+
// in an unrelated test.
|
|
337
|
+
if (cancelled) return;
|
|
329
338
|
console.warn(
|
|
330
339
|
`<kai-audio-visualizer variant="${v}">: failed to load the shader chunk, falling back to bars.`,
|
|
331
340
|
err,
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type { LabLook } from './lab-shaders';
|
|
2
|
+
|
|
3
|
+
/** The agent states the kit's visualizers respond to, plus manual free play. */
|
|
4
|
+
export type LabState = 'manual' | 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking';
|
|
5
|
+
|
|
6
|
+
export const LAB_STATES: LabState[] = ['manual', 'idle', 'connecting', 'listening', 'thinking', 'speaking'];
|
|
7
|
+
|
|
8
|
+
/** Every tunable the lab shaders read. Flat on purpose: story args map 1:1. */
|
|
9
|
+
export interface LabParams {
|
|
10
|
+
baseR: number; ampIdle: number; ampVoice: number; radVoice: number;
|
|
11
|
+
sigma: number; gain: number; f1: number; f2: number; s1: number; s2: number;
|
|
12
|
+
envSpd: number; sepSpd: number; whiteLo: number; whiteHi: number;
|
|
13
|
+
bloomMul: number; bloomGain: number; delta: number; off: number;
|
|
14
|
+
wWidth: number; wMin: number; fillGain: number; edgeGain: number;
|
|
15
|
+
flut: number; twistSpd: number; warpAmp: number; lens: number; spec: number;
|
|
16
|
+
tint: number; vSpeed: number; presence: number; gather: number;
|
|
17
|
+
core: number; neural: number; boltJag: number; boltWidth: number; boltRate: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const SHARED: LabParams = {
|
|
21
|
+
baseR: 0.33, ampIdle: 0.017, ampVoice: 0.043, radVoice: 0.24,
|
|
22
|
+
sigma: 0.022, gain: 0.42, f1: 6, f2: 10, s1: 0.55, s2: 0.85,
|
|
23
|
+
envSpd: 0.21, sepSpd: 0.38, whiteLo: 1.35, whiteHi: 2.3,
|
|
24
|
+
bloomMul: 2.6, bloomGain: 0.18, delta: 0.35, off: 0.024,
|
|
25
|
+
wWidth: 0.045, wMin: 0.006, fillGain: 0.38, edgeGain: 0.7,
|
|
26
|
+
flut: 0.01, twistSpd: 0.55, warpAmp: 0.75, lens: 0.85, spec: 0.35,
|
|
27
|
+
tint: 0.25, vSpeed: 2.2, presence: 1, gather: 0,
|
|
28
|
+
core: 0, neural: 0, boltJag: 0.5, boltWidth: 3, boltRate: 0.25,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Hand-tuned in the aurora playground; per-look starting points. */
|
|
32
|
+
export const LOOK_DEFAULTS: Record<LabLook, LabParams> = {
|
|
33
|
+
braid: { ...SHARED },
|
|
34
|
+
ribbon: {
|
|
35
|
+
...SHARED,
|
|
36
|
+
baseR: 0.315, ampIdle: 0.012, ampVoice: 0.032, radVoice: 0.09,
|
|
37
|
+
sigma: 0.014, gain: 0.6, f1: 3, f2: 9, s1: 1.1, s2: 2.2,
|
|
38
|
+
envSpd: 0.5, whiteLo: 1.0, whiteHi: 2.4, bloomMul: 2.5, bloomGain: 0.15,
|
|
39
|
+
wWidth: 0.085, wMin: 0.009, fillGain: 0.85, edgeGain: 0.35, twistSpd: 1.9,
|
|
40
|
+
},
|
|
41
|
+
planet: {
|
|
42
|
+
...SHARED,
|
|
43
|
+
radVoice: 0, gain: 1.0, fillGain: 0.75, edgeGain: 0.5,
|
|
44
|
+
f2: 12, s1: 1, s2: 1, twistSpd: 1.0, warpAmp: 0.9,
|
|
45
|
+
whiteLo: 1.2, whiteHi: 2.6,
|
|
46
|
+
},
|
|
47
|
+
orb: {
|
|
48
|
+
...SHARED,
|
|
49
|
+
radVoice: 0, gain: 1.1, fillGain: 0.65, edgeGain: 0.45,
|
|
50
|
+
f2: 10, s1: 1, s2: 1, twistSpd: 1.2, warpAmp: 1.0,
|
|
51
|
+
lens: 0.8, spec: 0.3, vSpeed: 3.0,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const ORB_LOOKS: LabLook[] = ['planet', 'orb'];
|
|
56
|
+
|
|
57
|
+
/** Loudness loop standing in for a live voice while `speaking` (dB per third-second). */
|
|
58
|
+
const ENV_DB = [-60.9, -49.0, -46.7, -54.1, -50.0, -47.8, -49.3, -53.3, -53.5, -50.4,
|
|
59
|
+
-46.9, -53.0, -50.2, -52.5, -53.9, -50.6, -50.8, -49.2, -55.1, -48.7,
|
|
60
|
+
-48.4, -47.4, -49.6, -50.7, -49.0, -46.9, -50.8, -52.9, -52.2, -46.6,
|
|
61
|
+
-46.6, -46.2];
|
|
62
|
+
|
|
63
|
+
function envelopeAt(sec: number): number {
|
|
64
|
+
const x = (sec % 10.6) * 3;
|
|
65
|
+
const i = Math.max(0, Math.min(ENV_DB.length - 1, Math.floor(x)));
|
|
66
|
+
const j = Math.min(ENV_DB.length - 1, i + 1);
|
|
67
|
+
const f = x - i;
|
|
68
|
+
const db = ENV_DB[i] * (1 - f) + ENV_DB[j] * f;
|
|
69
|
+
return Math.max(0, Math.min(1, (db + 58) / 14));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface Slow {
|
|
73
|
+
presence: number; gather: number; tintAdd: number; warpMul: number;
|
|
74
|
+
deltaAdd: number; f2Add: number; gainMul: number; neural: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface LabFrame {
|
|
78
|
+
t: number;
|
|
79
|
+
level: number;
|
|
80
|
+
values: LabParams;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The state choreography from the playground, per frame. Slow targets glide
|
|
85
|
+
* over seconds (presence slowest, so smoke visibly forms and dissipates);
|
|
86
|
+
* tempo runs on an accumulated warped clock, so state changes never jump the
|
|
87
|
+
* animation phase; the ember beats and the bolts fire in real time.
|
|
88
|
+
*/
|
|
89
|
+
export function createChoreography(getLook: () => LabLook, getState: () => LabState, getParams: () => LabParams) {
|
|
90
|
+
let tAnim = 0;
|
|
91
|
+
let rateSm = 1;
|
|
92
|
+
let smooth = 0;
|
|
93
|
+
let elapsed = 0;
|
|
94
|
+
const slow: Slow = { presence: 1, gather: 0, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
|
|
95
|
+
|
|
96
|
+
const step = (dt: number): LabFrame => {
|
|
97
|
+
elapsed += dt;
|
|
98
|
+
const P = getParams();
|
|
99
|
+
const state = getState();
|
|
100
|
+
const orb = ORB_LOOKS.includes(getLook());
|
|
101
|
+
const base = orb ? 0.35 : 1.0;
|
|
102
|
+
|
|
103
|
+
const drive = envelopeAt(elapsed);
|
|
104
|
+
const k = drive > smooth ? 0.25 : 0.06;
|
|
105
|
+
smooth += (drive - smooth) * k;
|
|
106
|
+
|
|
107
|
+
const beat = Math.pow(0.5 + 0.5 * Math.sin((elapsed / 1.2) * Math.PI * 2), 3.0);
|
|
108
|
+
const flick = 0.5 + 0.5 * Math.sin((elapsed / 0.35) * Math.PI * 2);
|
|
109
|
+
|
|
110
|
+
let target: Slow;
|
|
111
|
+
let rate: number;
|
|
112
|
+
let level: number;
|
|
113
|
+
let core: number;
|
|
114
|
+
let gpulse = 0;
|
|
115
|
+
switch (state) {
|
|
116
|
+
case 'idle':
|
|
117
|
+
target = orb
|
|
118
|
+
? { presence: 0.12, gather: -0.8, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 }
|
|
119
|
+
: { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.8, neural: 0 };
|
|
120
|
+
rate = base; level = 0; core = orb ? 0.06 : 0;
|
|
121
|
+
break;
|
|
122
|
+
case 'connecting':
|
|
123
|
+
target = orb
|
|
124
|
+
? { presence: 0.22, gather: -0.25, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.9, neural: 0 }
|
|
125
|
+
: { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 };
|
|
126
|
+
rate = base * 1.4; level = 0.04; core = orb ? 0.18 + 0.55 * beat : 0;
|
|
127
|
+
if (!orb) gpulse = 0.2 * beat;
|
|
128
|
+
break;
|
|
129
|
+
case 'listening':
|
|
130
|
+
target = orb
|
|
131
|
+
? { presence: 0.8, gather: 0.5, tintAdd: 0.05, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 }
|
|
132
|
+
: { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
|
|
133
|
+
rate = base * 1.7; level = 0.2; core = orb ? 0.12 : 0;
|
|
134
|
+
break;
|
|
135
|
+
case 'thinking':
|
|
136
|
+
target = orb
|
|
137
|
+
? { presence: 1, gather: 0.6, tintAdd: 0.5, warpMul: 1.3, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 1 }
|
|
138
|
+
: { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0.5, f2Add: 3, gainMul: 1, neural: 0 };
|
|
139
|
+
rate = orb ? 2.2 : 2.5; level = 0.12 + 0.2 * flick; core = orb ? 0.05 : 0;
|
|
140
|
+
if (!orb) gpulse = 0.1 * flick;
|
|
141
|
+
break;
|
|
142
|
+
case 'speaking':
|
|
143
|
+
target = orb
|
|
144
|
+
? { presence: 1, gather: 0, tintAdd: 0, warpMul: 1.25, deltaAdd: 0, f2Add: 0, gainMul: 1.05, neural: 0 }
|
|
145
|
+
: { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
|
|
146
|
+
rate = base * 1.5 + 5.5 * smooth; level = Math.min(1, smooth * 1.35);
|
|
147
|
+
core = orb ? 0.08 + 0.6 * smooth : 0;
|
|
148
|
+
break;
|
|
149
|
+
default:
|
|
150
|
+
target = { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: P.neural };
|
|
151
|
+
rate = base + P.vSpeed * smooth; level = smooth; core = P.core;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const mixTo = (cur: number, tgt: number, tc: number): number =>
|
|
155
|
+
cur + (tgt - cur) * (1 - Math.exp(-dt / tc));
|
|
156
|
+
slow.presence = mixTo(slow.presence, target.presence, 1.4);
|
|
157
|
+
slow.gather = mixTo(slow.gather, target.gather, 1.0);
|
|
158
|
+
slow.tintAdd = mixTo(slow.tintAdd, target.tintAdd, 0.6);
|
|
159
|
+
slow.warpMul = mixTo(slow.warpMul, target.warpMul, 0.6);
|
|
160
|
+
slow.deltaAdd = mixTo(slow.deltaAdd, target.deltaAdd, 0.6);
|
|
161
|
+
slow.f2Add = mixTo(slow.f2Add, target.f2Add, 0.6);
|
|
162
|
+
slow.gainMul = mixTo(slow.gainMul, target.gainMul, 0.6);
|
|
163
|
+
slow.neural = mixTo(slow.neural, target.neural, 0.6);
|
|
164
|
+
|
|
165
|
+
rateSm += (rate - rateSm) * (1 - Math.exp(-dt / 0.4));
|
|
166
|
+
tAnim += dt * rateSm;
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
t: tAnim,
|
|
170
|
+
level,
|
|
171
|
+
values: {
|
|
172
|
+
...P,
|
|
173
|
+
presence: slow.presence,
|
|
174
|
+
gather: slow.gather,
|
|
175
|
+
core,
|
|
176
|
+
neural: slow.neural,
|
|
177
|
+
tint: Math.min(1, P.tint + slow.tintAdd),
|
|
178
|
+
warpAmp: P.warpAmp * slow.warpMul,
|
|
179
|
+
delta: P.delta + slow.deltaAdd,
|
|
180
|
+
f2: P.f2 + slow.f2Add,
|
|
181
|
+
gain: P.gain * slow.gainMul * (1 + gpulse),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
return { step };
|
|
187
|
+
}
|