@kitn.ai/ui 0.28.0 → 0.30.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 +11 -7
- package/dist/{Icon-DObhsRtm.js → Icon-BzBET3E-.js} +1 -1
- package/dist/{action-icons-CcgNN2oT.js → action-icons-DaW2pU6m.js} +1 -1
- package/dist/agent-tooling/construct/public.d.ts +15 -0
- package/dist/agent-tooling/construct/schema.d.ts +111 -0
- package/dist/arrow-down-D783iMJj.js +1 -0
- package/dist/arrow-left-0VLM5kyg.js +1 -0
- package/dist/artifact-DGjzHYUT.js +1 -0
- package/dist/{attachments-Qr4kg-2b.js → attachments-YvXHlg88.js} +1 -1
- package/dist/{audio-visualizer-DToYdfSc.js → audio-visualizer-9lz5IHsL.js} +1 -1
- package/dist/{badge-CdEu_jn2.js → badge-Dh_vp8A5.js} +1 -1
- package/dist/{bell-DQAAOpDz.js → bell-CT7_WUwS.js} +1 -1
- package/dist/{button-DkuOnGLy.js → button-C_3te6fm.js} +1 -1
- package/dist/{card-renderer-Jx70m6_l.js → card-renderer-DZVaGH2e.js} +1 -1
- package/dist/check-CiEOVnEN.js +1 -0
- package/dist/{checkbox-D7iRB3nL.js → checkbox-Bu2T2e0U.js} +1 -1
- package/dist/{checkbox-group-B2_rpoPM.js → checkbox-group-BiryEXPQ.js} +1 -1
- package/dist/chevron-down-CSobuZRG.js +1 -0
- package/dist/chevron-right-DR9ZAP-2.js +1 -0
- package/dist/{choice-card-m0BYqqOK.js → choice-card-CM6IjkmL.js} +1 -1
- package/dist/circle-BC66EYF7.js +1 -0
- package/dist/circle-check-BqmahW0O.js +1 -0
- package/dist/{circle-x-BPG0iPst.js → circle-x-Bk-dA5Wf.js} +1 -1
- package/dist/{code-block-ClMLKb7C.js → code-block-B26t-Q7q.js} +1 -1
- package/dist/{collapsible-B4DlWicL.js → collapsible-Bhc636Cf.js} +1 -1
- package/dist/components/builder-composer-triggers.d.ts +62 -0
- package/dist/components/builder-layout.d.ts +54 -0
- package/dist/components/builder-message-actions.d.ts +72 -0
- package/dist/components/builder-panel.d.ts +189 -0
- package/dist/components/builder-preview.d.ts +11 -0
- package/dist/components/builder-shell-controls.d.ts +69 -0
- package/dist/components/builder-skeleton.d.ts +58 -0
- package/dist/components/builder-start.d.ts +75 -0
- package/dist/components/builder-workspace-variants.d.ts +23 -0
- package/dist/components/captions.d.ts +66 -0
- package/dist/{composer-sQ0HcvyG.js → composer-DMI85B6j.js} +1 -1
- package/dist/{confirm-card-rQWDQsnC.js → confirm-card-B0YIAwXp.js} +1 -1
- package/dist/construct-cli.es.js +3 -3
- package/dist/construct.d.ts +5 -0
- package/dist/construct.js +327 -0
- package/dist/{context-0kg4ZX1J.js → context-DWgfhqWp.js} +1 -1
- package/dist/controllable-BagRpyHv.js +1 -0
- package/dist/{conversation-item-BxwQLaFJ.js → conversation-item-BsOsVGmT.js} +1 -1
- package/dist/{conversation-list-BCfGN1JU.js → conversation-list-aX3Vtc7L.js} +1 -1
- package/dist/{copy-n9u9rqpi.js → copy-BmEwsNhJ.js} +1 -1
- package/dist/core-C8fzo39E.js +1 -12
- package/dist/{create-tween-uPkArjIG.js → create-tween-CNOAU3Fx.js} +1 -1
- package/dist/{create-tween-C-q-JCM-.js → create-tween-WfqiENls.js} +1 -1
- package/dist/{create-tween-CRrJXxBd.js → create-tween-wlFtW9Kh.js} +1 -1
- package/dist/{create-tween-DZ3RRDHD.js → create-tween-zt79ba32.js} +1 -1
- package/dist/{default-input-CaMrJkgH.js → default-input-DMV5Eaze.js} +1 -1
- package/dist/define-CI0y3eE4.js +1 -0
- package/dist/define.js +40 -40
- package/dist/define.server.js +45 -45
- package/dist/{disclosure-WUImBbDv.js → disclosure-NnACBxsC.js} +1 -1
- package/dist/{dropdown-wZVeJOMd.js → dropdown-DT7G0RGR.js} +1 -1
- 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-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkbox-group.js +1 -1
- package/dist/elements/checkbox.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-item.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.js +1 -1
- package/dist/elements/dropdown.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- 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-grid.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/radio-group.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +1 -1
- 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/select.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/slider.js +1 -1
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/{ellipsis-CbOpJnU3.js → ellipsis-6pJ7SxYT.js} +1 -1
- package/dist/{embed-CrfjkbUG.js → embed-BMje-nxj.js} +1 -1
- package/dist/engine-javascript-C1x7zo1_.js +1 -141
- package/dist/{external-link-ByXAwBBQ.js → external-link-Beh9DKeR.js} +1 -1
- package/dist/{file-text-DMib2qwt.js → file-text-D1GPfZ8Q.js} +1 -1
- package/dist/{file-tree-CJqM2aP7.js → file-tree-Dwj2lqg-.js} +1 -1
- package/dist/{folder-_BAb929C.js → folder-b6D8x1DY.js} +1 -1
- package/dist/{form-DSZgZQZk.js → form-DWgdxDXu.js} +1 -1
- package/dist/{hover-card-BQbul9eq.js → hover-card-CWRkqm40.js} +1 -1
- package/dist/{icon-CdcfRhYI.js → icon-CL0jdhsf.js} +1 -1
- package/dist/index.js +1741 -1725
- package/dist/index.server.js +1582 -1566
- package/dist/{info-DsFjGuI_.js → info-0cOUherQ.js} +1 -1
- package/dist/{input-DKbmkMos.js → input-BH6Ru91Q.js} +1 -1
- package/dist/kai.es.js +1 -1
- package/dist/{kbd-PvdGhX4s.js → kbd-DRAnVtNX.js} +1 -1
- package/dist/{link-zF8PzWfF.js → link-Dlr0vssB.js} +1 -1
- package/dist/{link-preview-DbM1866N.js → link-preview-DODgRyV9.js} +1 -1
- package/dist/loader-KvJB6NrT.js +1 -0
- package/dist/{markdown-LMvmAyBk.js → markdown-DX9tuJVj.js} +1 -1
- package/dist/mcp.es.js +9 -5
- package/dist/{message-BYZECyek.js → message-BqQ7Ot5q.js} +1 -1
- package/dist/{message-BSsgvHvf.js → message-DkaGfBd8.js} +1 -1
- package/dist/message-circle-BPpp5QKv.js +1 -0
- package/dist/message-square-BLbsd9BJ.js +1 -0
- package/dist/{minimize-2-BQRoBV1V.js → minimize-2-CyOHJwcN.js} +1 -1
- package/dist/{model-switcher-CMpCOYcB.js → model-switcher-0hrKDiK2.js} +1 -1
- package/dist/{overlay-Cb-MkyDa.js → overlay-DBMFXie6.js} +1 -1
- package/dist/{panel-right-i8warFxT.js → panel-right-t8SWJL6e.js} +1 -1
- package/dist/{paperclip-ByY3UVO6.js → paperclip-CdzuOjbU.js} +1 -1
- package/dist/play-BXy1u7rW.js +1 -0
- package/dist/primitives/use-auto-resize.d.ts +11 -0
- package/dist/{progress-bar-jVAHvMUf.js → progress-bar-CiBtxMWT.js} +1 -1
- package/dist/{prompt-suggestion-CD-qtNgC.js → prompt-suggestion-I_DHP21i.js} +1 -1
- package/dist/{radio-BsoBMhkF.js → radio-C_p3n39l.js} +1 -1
- package/dist/{reasoning-4kBPtlTx.js → reasoning-BDwy_tIe.js} +1 -1
- package/dist/register-impl-DvEnhIxx.js +424 -0
- package/dist/{resizable-uPmY9VY-.js → resizable-SYC-fStM.js} +1 -1
- package/dist/{rotate-ccw-B2xn93py.js → rotate-ccw-B1nwmwuY.js} +1 -1
- package/dist/{rotate-cw-CMVLoCyH.js → rotate-cw-CLAnBcm1.js} +1 -1
- package/dist/{scroll-area-BqLUo8ZZ.js → scroll-area-zRyXoLhI.js} +1 -1
- package/dist/{scroll-button-DslXiJyL.js → scroll-button-jzrbYCG9.js} +1 -1
- package/dist/{select-2cLRtPGT.js → select-DM-0nEe0.js} +1 -1
- package/dist/{separator-BWQtNJcM.js → separator-BToOOoOt.js} +1 -1
- package/dist/{settings-BBR63jLg.js → settings-PaGo_S4U.js} +1 -1
- package/dist/{settings-group-B2ciy-Iw.js → settings-group-BFXGIfXq.js} +1 -1
- package/dist/{skeleton-CkHI-HgC.js → skeleton-DYpmFnnm.js} +1 -1
- package/dist/{slider-DDR9U-i0.js → slider-ebutAmkQ.js} +1 -1
- package/dist/{solid-DruVOXnf.js → solid-15v_3WVL.js} +3563 -3412
- package/dist/{solid-BzCFdL25.js → solid-5P-otgdi.js} +4502 -4296
- package/dist/solid.d.ts +6 -0
- package/dist/solid.js +259 -254
- package/dist/solid.server.js +259 -254
- package/dist/{source-GEnFF528.js → source-c1gpRl9h.js} +1 -1
- package/dist/{star-CilHq8GP.js → star-pcV_3LqF.js} +1 -1
- package/dist/{store-Ciyk6eZG.js → store-CSgbFFCg.js} +1 -1
- package/dist/{switch-KkeQIbuH.js → switch-Bh2OdLV2.js} +1 -1
- package/dist/{tasks-card-BrN4bggJ.js → tasks-card-CbqQAn2S.js} +1 -1
- package/dist/text-shimmer-BSzgEnDH.js +1 -0
- package/dist/textarea-DrYNt_0z.js +1 -0
- package/dist/theme.tokens.css +22 -21
- package/dist/{thumbs-up-CsT9Wzb9.js → thumbs-up-BL3-NenK.js} +1 -1
- package/dist/{toast-store-tgK6MuMv.js → toast-store-DkOlYczt.js} +1 -1
- package/dist/{tool-DzUjIBT8.js → tool-CeIWUVUe.js} +1 -1
- package/dist/{tooltip-Bkkg_4t0.js → tooltip-GA-nmg06.js} +1 -1
- package/dist/{trash-2-jBKxjGGQ.js → trash-2-CT66QWlm.js} +1 -1
- package/dist/{triangle-alert-DlQ68ppf.js → triangle-alert-CeHLWxhD.js} +1 -1
- package/dist/ui/color-field.d.ts +48 -0
- package/dist/ui/textarea.d.ts +4 -0
- package/dist/ui/toggle-chip.d.ts +40 -0
- package/dist/{upload-TcAHXv9W.js → upload-9Csb0F0J.js} +1 -1
- package/dist/{use-card-resolution-DaZqAdWf.js → use-card-resolution-Zg0a08Z-.js} +1 -1
- package/dist/{variant-aurora-DbW_OWL2.js → variant-aurora-4VBQHIKV.js} +1 -1
- package/dist/{variant-aurora-CNmfHhcx.js → variant-aurora-DBeCAQNk.js} +2 -2
- package/dist/{variant-aurora-D6GsdTPA.js → variant-aurora-FzHVXHby.js} +2 -2
- package/dist/{variant-aurora-BhLuYxJR.js → variant-aurora-LE3fqxgw.js} +1 -1
- package/dist/{variant-custom-BvYHR62b.js → variant-custom-AFRGcOBS.js} +1 -1
- package/dist/{variant-custom-DV2x254s.js → variant-custom-BQkNuPpE.js} +2 -2
- package/dist/{variant-custom-BRvaNHSi.js → variant-custom-DI5R0rln.js} +1 -1
- package/dist/{variant-custom-DMTrEO5w.js → variant-custom-WWnrrRHS.js} +2 -2
- package/dist/{variant-wave-CyBueXj9.js → variant-wave-DUCbH5oI.js} +2 -2
- package/dist/{variant-wave-BNMGrDfj.js → variant-wave-DuQV7DhQ.js} +2 -2
- package/dist/{variant-wave-BpDd8t3Z.js → variant-wave-nSI2sfII.js} +1 -1
- package/dist/{variant-wave-sp-qwsdI.js → variant-wave-wTP5v_jU.js} +1 -1
- package/dist/x-eiO9V6J6.js +1 -0
- package/{src/elements/styles.css → kit-base.css} +27 -44
- package/package.json +32 -17
- package/solid.css +33 -0
- package/theme.css +39 -23
- package/bin/route.test.js +0 -58
- package/dist/arrow-down-CjRU3JgV.js +0 -1
- package/dist/arrow-left-Bnpb1UEW.js +0 -1
- package/dist/artifact-Bwt7OgcR.js +0 -1
- package/dist/check-njkVdZu2.js +0 -1
- package/dist/chevron-down-B72s6PXR.js +0 -1
- package/dist/chevron-right-BatuHzUm.js +0 -1
- package/dist/circle-check-B62pODB3.js +0 -1
- package/dist/circle-zx0ByzY9.js +0 -1
- package/dist/controllable-CnGpMF6r.js +0 -1
- package/dist/define-By-uL588.js +0 -1
- package/dist/loader-BM4CEz4G.js +0 -1
- package/dist/message-circle-DruwObfX.js +0 -1
- package/dist/message-square-BG6q6mlm.js +0 -1
- package/dist/play-BvKKq3fX.js +0 -1
- package/dist/register-impl-B1hLkrI8.js +0 -424
- package/dist/text-shimmer-Dcj1MHuq.js +0 -1
- package/dist/textarea-Dpvbngbg.js +0 -1
- package/dist/x-Z5UntkIJ.js +0 -1
- package/src/agent-tooling/README.md +0 -192
- package/src/agent-tooling/archetypes.ts +0 -205
- package/src/agent-tooling/catalog/README.md +0 -676
- package/src/agent-tooling/catalog/catalog-types.ts +0 -231
- package/src/agent-tooling/catalog/fabrications.ts +0 -96
- package/src/agent-tooling/catalog/invariants.ts +0 -284
- package/src/agent-tooling/catalog/labs-titles.ts +0 -114
- package/src/agent-tooling/catalog/scenarios.ts +0 -87
- package/src/agent-tooling/catalog/surfaces.ts +0 -347
- package/src/agent-tooling/construct/cli-entry.ts +0 -8
- package/src/agent-tooling/construct/cli.ts +0 -147
- package/src/agent-tooling/construct/codegen.ts +0 -1635
- package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
- package/src/agent-tooling/construct/dev.ts +0 -148
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
- package/src/agent-tooling/construct/schema.ts +0 -452
- package/src/agent-tooling/integrations/anthropic.ts +0 -442
- package/src/agent-tooling/integrations/cloudflare.ts +0 -218
- package/src/agent-tooling/integrations/langgraph.ts +0 -133
- package/src/agent-tooling/integrations/mastra.ts +0 -182
- package/src/agent-tooling/integrations/mock.ts +0 -148
- package/src/agent-tooling/integrations/ollama.ts +0 -97
- package/src/agent-tooling/integrations/openai.ts +0 -95
- package/src/agent-tooling/integrations/openrouter.ts +0 -82
- package/src/agent-tooling/integrations/pi.ts +0 -176
- package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
- package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
- package/src/agent-tooling/mcp/manifest.ts +0 -422
- package/src/agent-tooling/mcp/server.ts +0 -116
- package/src/agent-tooling/mcp/stdio.ts +0 -18
- package/src/agent-tooling/mcp/tools/construct.ts +0 -130
- package/src/agent-tooling/mcp/tools/debug.ts +0 -621
- package/src/agent-tooling/mcp/tools/reference.ts +0 -980
- package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
- package/src/agent-tooling/mcp/tools/theme.ts +0 -456
- package/src/agent-tooling/mcp/tools/types.ts +0 -14
- package/src/agent-tooling/mcp/validate-args.ts +0 -141
- package/src/agent-tooling/recipes/composed-thread.ts +0 -714
- package/src/agent-tooling/recipes/index.ts +0 -22
- package/src/agent-tooling/recipes/types.ts +0 -32
- package/src/agent-tooling/registry.ts +0 -132
- package/src/agent-tooling/route-emit.ts +0 -305
- package/src/agent-tooling/types.ts +0 -390
- package/src/components/artifact-card.tsx +0 -120
- package/src/components/artifact.tsx +0 -914
- package/src/components/attachment-types.ts +0 -66
- package/src/components/attachments.tsx +0 -536
- package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
- package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
- package/src/components/audio-visualizer/fit-scale.ts +0 -112
- package/src/components/audio-visualizer/index.tsx +0 -528
- package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
- package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
- package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
- package/src/components/audio-visualizer/sizes.ts +0 -54
- package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
- package/src/components/audio-visualizer/variant-bar.tsx +0 -175
- package/src/components/audio-visualizer/variant-custom.tsx +0 -344
- package/src/components/audio-visualizer/variant-grid.tsx +0 -175
- package/src/components/audio-visualizer/variant-radial.tsx +0 -163
- package/src/components/audio-visualizer/variant-wave.tsx +0 -130
- package/src/components/audio-visualizer/wave.glsl.ts +0 -130
- package/src/components/card-fallback.tsx +0 -60
- package/src/components/card-renderer.tsx +0 -220
- package/src/components/card.tsx +0 -212
- package/src/components/chain-of-thought.tsx +0 -348
- package/src/components/chat-container.tsx +0 -89
- package/src/components/chat-scope-picker.tsx +0 -57
- package/src/components/chat-thread.tsx +0 -1014
- package/src/components/checkpoint.tsx +0 -88
- package/src/components/choice-card.tsx +0 -743
- package/src/components/coachmark.tsx +0 -249
- package/src/components/code-block.tsx +0 -181
- package/src/components/composer-dom.ts +0 -159
- package/src/components/composer-highlight.ts +0 -242
- package/src/components/composer-history.ts +0 -82
- package/src/components/composer.tsx +0 -1075
- package/src/components/confirm-card.tsx +0 -402
- package/src/components/context.tsx +0 -377
- package/src/components/conversation-item.tsx +0 -241
- package/src/components/conversation-list.tsx +0 -429
- package/src/components/conversation-panel.tsx +0 -118
- package/src/components/dismissed-stub.tsx +0 -80
- package/src/components/embed.tsx +0 -200
- package/src/components/empty.tsx +0 -177
- package/src/components/feedback-bar.tsx +0 -166
- package/src/components/file-tree.tsx +0 -530
- package/src/components/file-upload.tsx +0 -167
- package/src/components/form-widgets.tsx +0 -525
- package/src/components/form.tsx +0 -1296
- package/src/components/home-panel.tsx +0 -159
- package/src/components/image.tsx +0 -65
- package/src/components/link-preview.tsx +0 -195
- package/src/components/loader.tsx +0 -367
- package/src/components/markdown.tsx +0 -162
- package/src/components/message-skills.tsx +0 -40
- package/src/components/message.tsx +0 -765
- package/src/components/model-switcher.tsx +0 -132
- package/src/components/prompt-input.tsx +0 -188
- package/src/components/prompt-suggestion.tsx +0 -150
- package/src/components/reasoning.tsx +0 -293
- package/src/components/response-compare-types.ts +0 -152
- package/src/components/response-compare.tsx +0 -455
- package/src/components/response-stream.tsx +0 -109
- package/src/components/screen.tsx +0 -181
- package/src/components/scroll-button.tsx +0 -93
- package/src/components/source.tsx +0 -192
- package/src/components/tasks-card.tsx +0 -801
- package/src/components/text-shimmer.tsx +0 -37
- package/src/components/thinking-bar.tsx +0 -50
- package/src/components/thread.tsx +0 -228
- package/src/components/toast.tsx +0 -503
- package/src/components/tool-classify.ts +0 -26
- package/src/components/tool-types.ts +0 -49
- package/src/components/tool.tsx +0 -190
- package/src/components/use-card-resolution.ts +0 -44
- package/src/components/voice-input.tsx +0 -222
- package/src/components/voice-output.tsx +0 -242
- package/src/components/widget-tab-bar.tsx +0 -73
- package/src/components/workspace-shell.tsx +0 -285
- package/src/diagnostics/hook.ts +0 -352
- package/src/diagnostics/index.ts +0 -82
- package/src/diagnostics/report-request.ts +0 -296
- package/src/elements/agent-card.tsx +0 -67
- package/src/elements/artifact.tsx +0 -194
- package/src/elements/attachments.tsx +0 -140
- package/src/elements/audio-visualizer.tsx +0 -227
- package/src/elements/autoloader.ts +0 -89
- package/src/elements/avatar.tsx +0 -33
- package/src/elements/badge.tsx +0 -32
- package/src/elements/button.tsx +0 -149
- package/src/elements/card.tsx +0 -133
- package/src/elements/cards.tsx +0 -266
- package/src/elements/chain-of-thought.tsx +0 -141
- package/src/elements/chat-scope-picker.tsx +0 -65
- package/src/elements/chat-types.ts +0 -102
- package/src/elements/chat-workspace.tsx +0 -188
- package/src/elements/chat.tsx +0 -304
- package/src/elements/checkbox-group.tsx +0 -164
- package/src/elements/checkbox.tsx +0 -134
- package/src/elements/checkpoint.tsx +0 -47
- package/src/elements/choice.tsx +0 -100
- package/src/elements/coachmark.tsx +0 -90
- package/src/elements/code-block.tsx +0 -60
- package/src/elements/command.tsx +0 -197
- package/src/elements/compare.tsx +0 -111
- package/src/elements/compiled.css +0 -2
- package/src/elements/composer.tsx +0 -162
- package/src/elements/confirm-card.tsx +0 -76
- package/src/elements/context-meter.tsx +0 -107
- package/src/elements/conversation-item.tsx +0 -120
- package/src/elements/conversation-list.tsx +0 -203
- package/src/elements/css.ts +0 -5
- package/src/elements/default-input.tsx +0 -392
- package/src/elements/define-entry.ts +0 -12
- package/src/elements/define.tsx +0 -563
- package/src/elements/diagnostic-events.ts +0 -114
- package/src/elements/dialog.tsx +0 -145
- package/src/elements/disclosure.ts +0 -95
- package/src/elements/dock.tsx +0 -215
- package/src/elements/dropdown.tsx +0 -123
- package/src/elements/editable-label.tsx +0 -140
- package/src/elements/element-data-types.ts +0 -152
- package/src/elements/element-diagnostics.ts +0 -392
- package/src/elements/element-manifest.json +0 -354
- package/src/elements/element-nonscalar.json +0 -187
- package/src/elements/element-types.d.ts +0 -4353
- package/src/elements/embed.tsx +0 -35
- package/src/elements/empty.tsx +0 -29
- package/src/elements/feedback-bar.tsx +0 -66
- package/src/elements/file-tree.tsx +0 -62
- package/src/elements/file-upload.tsx +0 -44
- package/src/elements/form.tsx +0 -94
- package/src/elements/hover-card.tsx +0 -80
- package/src/elements/icon.tsx +0 -41
- package/src/elements/image.tsx +0 -32
- package/src/elements/input.tsx +0 -492
- package/src/elements/kbd.tsx +0 -45
- package/src/elements/link-preview.tsx +0 -34
- package/src/elements/loader.tsx +0 -25
- package/src/elements/markdown.tsx +0 -38
- package/src/elements/menu.tsx +0 -241
- package/src/elements/message-skills.tsx +0 -83
- package/src/elements/message.tsx +0 -361
- package/src/elements/model-switcher.tsx +0 -121
- package/src/elements/nav.tsx +0 -87
- package/src/elements/notice.tsx +0 -53
- package/src/elements/pane-grid.tsx +0 -111
- package/src/elements/pane-group.tsx +0 -119
- package/src/elements/pane.tsx +0 -129
- package/src/elements/popover.tsx +0 -81
- package/src/elements/progress-bar.tsx +0 -39
- package/src/elements/prompt-dock.tsx +0 -82
- package/src/elements/prompt-input.tsx +0 -240
- package/src/elements/prompt-suggestions.tsx +0 -113
- package/src/elements/radio-group.tsx +0 -129
- package/src/elements/reasoning.tsx +0 -71
- package/src/elements/register-impl.ts +0 -148
- package/src/elements/register.ts +0 -76
- package/src/elements/remote.tsx +0 -225
- package/src/elements/resizable.globals.d.ts +0 -36
- package/src/elements/resizable.tsx +0 -704
- package/src/elements/response-stream.tsx +0 -40
- package/src/elements/screen.tsx +0 -90
- package/src/elements/scroll-area.tsx +0 -33
- package/src/elements/scroll-button.tsx +0 -179
- package/src/elements/search.tsx +0 -185
- package/src/elements/segmented.tsx +0 -129
- package/src/elements/select.tsx +0 -165
- package/src/elements/separator.tsx +0 -36
- package/src/elements/setting-item.tsx +0 -50
- package/src/elements/settings-group.tsx +0 -37
- package/src/elements/skeleton.tsx +0 -45
- package/src/elements/slider.tsx +0 -171
- package/src/elements/slot-text.ts +0 -73
- package/src/elements/slots.ts +0 -787
- package/src/elements/source.tsx +0 -126
- package/src/elements/status.tsx +0 -42
- package/src/elements/switch.tsx +0 -118
- package/src/elements/tabs.tsx +0 -95
- package/src/elements/tasks.tsx +0 -103
- package/src/elements/text-shimmer.tsx +0 -28
- package/src/elements/thinking-bar.tsx +0 -43
- package/src/elements/thread.tsx +0 -139
- package/src/elements/toast.tsx +0 -106
- package/src/elements/tool.tsx +0 -78
- package/src/elements/tooltip.tsx +0 -85
- package/src/elements/validate-messages.ts +0 -76
- package/src/elements/voice-input.tsx +0 -100
- package/src/elements/voice-output.tsx +0 -82
- package/src/index.ts +0 -430
- package/src/primitives/audio-bands.ts +0 -174
- package/src/primitives/card-component-types.ts +0 -63
- package/src/primitives/card-contract.ts +0 -80
- package/src/primitives/card-data-types.ts +0 -361
- package/src/primitives/card-host.tsx +0 -37
- package/src/primitives/card-recovery.ts +0 -160
- package/src/primitives/card-registry.tsx +0 -78
- package/src/primitives/card-resolution.ts +0 -36
- package/src/primitives/card-routing.ts +0 -85
- package/src/primitives/card-schemas/artifact.schema.json +0 -92
- package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
- package/src/primitives/card-schemas/card-event.schema.json +0 -12
- package/src/primitives/card-schemas/choice.schema.json +0 -75
- package/src/primitives/card-schemas/confirm.schema.json +0 -65
- package/src/primitives/card-schemas/embed.schema.json +0 -63
- package/src/primitives/card-schemas/form.result.schema.json +0 -7
- package/src/primitives/card-schemas/form.schema.json +0 -53
- package/src/primitives/card-schemas/link.schema.json +0 -54
- package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
- package/src/primitives/card-schemas/tasks.schema.json +0 -83
- package/src/primitives/card-tags.ts +0 -61
- package/src/primitives/card-validate-cards.ts +0 -255
- package/src/primitives/card-validate-schemas.ts +0 -58
- package/src/primitives/card-validate.ts +0 -131
- package/src/primitives/chat-config.tsx +0 -103
- package/src/primitives/composer-model.ts +0 -49
- package/src/primitives/composer-triggers.ts +0 -35
- package/src/primitives/controllable.ts +0 -21
- package/src/primitives/conversation-store.ts +0 -248
- package/src/primitives/create-kai-chat.ts +0 -66
- package/src/primitives/create-tween.ts +0 -266
- package/src/primitives/embed-providers.ts +0 -254
- package/src/primitives/field-mask.ts +0 -256
- package/src/primitives/field-semantics.ts +0 -115
- package/src/primitives/highlighter.ts +0 -157
- package/src/primitives/input-mask.ts +0 -853
- package/src/primitives/link-preview.ts +0 -87
- package/src/primitives/message-feedback.ts +0 -124
- package/src/primitives/pdf-preview.ts +0 -121
- package/src/primitives/toast-store.ts +0 -338
- package/src/primitives/url-scheme-policy.ts +0 -70
- package/src/primitives/use-audio-analysis.ts +0 -340
- package/src/primitives/use-auto-resize.ts +0 -31
- package/src/primitives/use-resize-observer.ts +0 -45
- package/src/primitives/use-sequencer.ts +0 -72
- package/src/primitives/use-speech-recognition.ts +0 -146
- package/src/primitives/use-stick-to-bottom.ts +0 -75
- package/src/primitives/use-text-stream.ts +0 -143
- package/src/primitives/use-voice-recorder.ts +0 -62
- package/src/primitives/visualizer-sequences.ts +0 -350
- package/src/remote/host-embed.ts +0 -345
- package/src/remote/index.ts +0 -2
- package/src/remote/origin.ts +0 -30
- package/src/remote/provider-runtime.ts +0 -262
- package/src/remote/provider.ts +0 -2
- package/src/remote/validate.ts +0 -22
- package/src/remote/version.ts +0 -12
- package/src/remote/wire.ts +0 -48
- package/src/schemas/from-tool-call.ts +0 -151
- package/src/schemas/index.ts +0 -341
- package/src/schemas/provider-subsets.ts +0 -538
- package/src/schemas/registry.ts +0 -355
- package/src/schemas/tool-defs.ts +0 -793
- package/src/solid.ts +0 -173
- package/src/state/index.ts +0 -44
- package/src/state/messages.ts +0 -53
- package/src/state/mock.ts +0 -297
- package/src/state/parts.ts +0 -295
- package/src/state/persistence.ts +0 -180
- package/src/state/stream.ts +0 -246
- package/src/state/suggestions.ts +0 -9
- package/src/state/threads.ts +0 -142
- package/src/test-utils/fake-clock.ts +0 -88
- package/src/types.ts +0 -95
- package/src/ui/action-icons.ts +0 -53
- package/src/ui/agent-card.tsx +0 -218
- package/src/ui/avatar.tsx +0 -23
- package/src/ui/badge.tsx +0 -21
- package/src/ui/button.tsx +0 -49
- package/src/ui/card.tsx +0 -245
- package/src/ui/checkbox-group.tsx +0 -153
- package/src/ui/checkbox.tsx +0 -63
- package/src/ui/collapsible.tsx +0 -163
- package/src/ui/command.tsx +0 -103
- package/src/ui/dialog.tsx +0 -223
- package/src/ui/dock.tsx +0 -630
- package/src/ui/dropdown.tsx +0 -636
- package/src/ui/editable-label.tsx +0 -112
- package/src/ui/hover-card.tsx +0 -345
- package/src/ui/icon.tsx +0 -167
- package/src/ui/input.tsx +0 -391
- package/src/ui/kbd.tsx +0 -118
- package/src/ui/nav.tsx +0 -282
- package/src/ui/notice.tsx +0 -84
- package/src/ui/overlay.tsx +0 -277
- package/src/ui/pane-grid.tsx +0 -117
- package/src/ui/pane-group.tsx +0 -291
- package/src/ui/pane.tsx +0 -193
- package/src/ui/popover.tsx +0 -106
- package/src/ui/progress-bar.tsx +0 -83
- package/src/ui/prompt-dock.tsx +0 -145
- package/src/ui/radio.tsx +0 -150
- package/src/ui/resizable.tsx +0 -693
- package/src/ui/scroll-area.tsx +0 -26
- package/src/ui/segmented.tsx +0 -109
- package/src/ui/select.tsx +0 -168
- package/src/ui/separator.tsx +0 -10
- package/src/ui/settings-group.tsx +0 -67
- package/src/ui/skeleton.tsx +0 -73
- package/src/ui/slider.tsx +0 -178
- package/src/ui/status.tsx +0 -48
- package/src/ui/switch.tsx +0 -119
- package/src/ui/tabs.tsx +0 -168
- package/src/ui/textarea.tsx +0 -21
- package/src/ui/tooltip.tsx +0 -118
- package/src/utils/cn.ts +0 -30
- package/src/wire/chunk.ts +0 -248
- package/src/wire/consume.ts +0 -599
- package/src/wire/diagnostics.ts +0 -727
- package/src/wire/encode-probe.ts +0 -214
- package/src/wire/encode.ts +0 -947
- package/src/wire/files.ts +0 -342
- package/src/wire/formats/anthropic.ts +0 -274
- package/src/wire/formats/openai.ts +0 -228
- package/src/wire/index.ts +0 -95
- package/src/wire/media-types.ts +0 -344
- package/src/wire/read.ts +0 -396
- package/src/wire/sink-helpers.ts +0 -50
- package/src/wire/sse.ts +0 -153
|
@@ -1,980 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
KAI_TOOL_PREFIX,
|
|
4
|
-
cardSchemaNames,
|
|
5
|
-
cardSchemas,
|
|
6
|
-
cardTools,
|
|
7
|
-
isCardSchemaName,
|
|
8
|
-
toolNameForCardType,
|
|
9
|
-
} from '@kitn.ai/ui/schemas';
|
|
10
|
-
import type { CardSchemaName, ToolProvider } from '@kitn.ai/ui/schemas';
|
|
11
|
-
import type { Tool } from './types';
|
|
12
|
-
import {
|
|
13
|
-
cardHostTags,
|
|
14
|
-
cardTagForType,
|
|
15
|
-
cardTypeForTag,
|
|
16
|
-
entryForTag,
|
|
17
|
-
getElement,
|
|
18
|
-
listElements,
|
|
19
|
-
optInEntryForTag,
|
|
20
|
-
} from '../manifest';
|
|
21
|
-
import type { CemMember } from '../manifest';
|
|
22
|
-
// The RAW literals, not listInvariants() / listSurfaceRecipes(). Those re-run a
|
|
23
|
-
// zod parse over the whole catalog, and this is a per-lookup serving path called
|
|
24
|
-
// once for every element a harness asks about. The parse is not skipped, only
|
|
25
|
-
// moved: invariants.test.ts and surfaces.test.ts run it over these same literals
|
|
26
|
-
// in CI, so a malformed record fails a test rather than a request.
|
|
27
|
-
import { invariants } from '../../catalog/invariants';
|
|
28
|
-
import { surfaceRecipes } from '../../catalog/surfaces';
|
|
29
|
-
import type { TInvariant, TInvariantExample, TSurfaceRecipe } from '../../catalog/catalog-types';
|
|
30
|
-
import { listCodeRecipes, getCodeRecipe } from '../../recipes';
|
|
31
|
-
import type { CodeRecipe } from '../../recipes';
|
|
32
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
33
|
-
import { dirname, join } from 'node:path';
|
|
34
|
-
import { resolveManifestPath } from '../manifest';
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* component_reference — look up AI/UI (kai-*) web components, their props,
|
|
38
|
-
* events, attributes, and CSS custom properties from the live Custom Elements
|
|
39
|
-
* Manifest (dist/custom-elements.json).
|
|
40
|
-
*
|
|
41
|
-
* Backed by manifest.ts which resolves the CEM in both the bundled bin
|
|
42
|
-
* (dist/mcp.es.js sibling) and the Vitest source context (walks up to find
|
|
43
|
-
* dist/custom-elements.json in the repo root).
|
|
44
|
-
*
|
|
45
|
-
* For a card-backed element it also serves the card's JSON Schema and a tool
|
|
46
|
-
* definition GENERATED by `cardTools()`. See `renderCardContract` for why not one
|
|
47
|
-
* byte of that is written here as a literal.
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
/** Types that warrant the JS-property contract note. */
|
|
51
|
-
const JS_ONLY_TYPE_PATTERNS = /\[\]|\{|Record</;
|
|
52
|
-
|
|
53
|
-
function isJsOnlyType(typeText: string | undefined): boolean {
|
|
54
|
-
return typeText ? JS_ONLY_TYPE_PATTERNS.test(typeText) : false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
58
|
-
// The imperative half of the interaction surface
|
|
59
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* A CEM member of `kind: 'method'`.
|
|
63
|
-
*
|
|
64
|
-
* `CemMember` in manifest.ts types what EVERY member carries. `parameters` and
|
|
65
|
-
* `return` exist only on methods, and gen-element-api.mjs writes the AUTHORED
|
|
66
|
-
* parameter list into a single `parameters[0].name` rather than splitting it, so
|
|
67
|
-
* the signature is rebuilt from those two fields rather than read off one.
|
|
68
|
-
*/
|
|
69
|
-
interface CemMethodMember extends CemMember {
|
|
70
|
-
kind: 'method';
|
|
71
|
-
parameters?: { name: string }[];
|
|
72
|
-
return?: { type?: { text?: string } };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function isPublicMethod(member: CemMember): member is CemMethodMember {
|
|
76
|
-
return member.kind === 'method' && member.privacy === 'public';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** `maximize(index: number): void` — the call as a consumer types it. */
|
|
80
|
-
function methodSignature(method: CemMethodMember): string {
|
|
81
|
-
return `${method.name}(${method.parameters?.[0]?.name ?? ''}): ${method.return?.type?.text ?? 'void'}`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
85
|
-
// The card contract
|
|
86
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
87
|
-
|
|
88
|
-
const PROVIDERS = ['openai', 'anthropic', 'jsonschema'] as const;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* What a caller gets when they do not name a provider.
|
|
92
|
-
*
|
|
93
|
-
* NOT a coin-flip between the two wire formats, and deliberately not "serve all
|
|
94
|
-
* three". The three envelopes are not interchangeable in a way a reader can patch
|
|
95
|
-
* up: OpenAI nests the schema at `function.parameters`, Anthropic puts it flat at
|
|
96
|
-
* `input_schema`. Handing over one of those unasked means a harness on the other
|
|
97
|
-
* provider pastes it in and gets a 400 it will blame on the kit.
|
|
98
|
-
*
|
|
99
|
-
* `jsonschema` is the only one of the three that is not a wire envelope at all —
|
|
100
|
-
* `{ name, description, schema }` cannot be mistaken for either provider's shape, so
|
|
101
|
-
* a caller who reads it as one is corrected by the field names before they ship it.
|
|
102
|
-
* It is also directly usable, not a booby prize: `tool({ inputSchema: jsonSchema(
|
|
103
|
-
* def.schema) })` is exactly what the Vercel AI SDK wants, and of the nine
|
|
104
|
-
* integrations this MCP scaffolds, exactly one (openrouter) posts a raw OpenAI-wire
|
|
105
|
-
* tools array; the rest go through an SDK or an agent framework that takes the bare
|
|
106
|
-
* schema.
|
|
107
|
-
*
|
|
108
|
-
* Serving all three was the other candidate and it loses on cost for no gain in
|
|
109
|
-
* safety: measured on this tree, one card's pretty-printed definition runs
|
|
110
|
-
* 1.7-5.3 KB, so three of them plus the schema turns a single `kai-artifact` lookup
|
|
111
|
-
* into roughly 20 KB of context. The response names all three modes and the exact
|
|
112
|
-
* call that produces each, so a caller who does know their provider is one re-ask
|
|
113
|
-
* away and still never invents an envelope.
|
|
114
|
-
*/
|
|
115
|
-
const DEFAULT_PROVIDER: ToolProvider = 'jsonschema';
|
|
116
|
-
|
|
117
|
-
function isProvider(value: string): value is ToolProvider {
|
|
118
|
-
return (PROVIDERS as readonly string[]).includes(value);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Stable fence info strings, so a reader (and reference.test.ts) can lift the blocks back out exactly. */
|
|
122
|
-
const TOOL_FENCE = 'kai-tool-definition';
|
|
123
|
-
const SCHEMA_FENCE = 'kai-card-schema';
|
|
124
|
-
|
|
125
|
-
function fence(info: string, value: unknown): string[] {
|
|
126
|
-
return ['```json ' + info, JSON.stringify(value, null, 2), '```'];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Render a card type as it would be written in JS source.
|
|
131
|
-
*
|
|
132
|
-
* The seven built-ins are all bare identifiers, but a card type is whatever string a
|
|
133
|
-
* developer put in `CardEnvelope.type` — `pricing-table` is legal and reaches this
|
|
134
|
-
* code the day an eighth built-in is hyphenated. Emitting `{ pricing-table: … }` as a
|
|
135
|
-
* copy-paste sample would be a syntax error, so the quoting is decided, not assumed.
|
|
136
|
-
*/
|
|
137
|
-
const BARE_IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
|
|
138
|
-
|
|
139
|
-
function asKey(cardType: string): string {
|
|
140
|
-
return BARE_IDENTIFIER.test(cardType) ? cardType : JSON.stringify(cardType);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function asMember(cardType: string): string {
|
|
144
|
-
return BARE_IDENTIFIER.test(cardType) ? `.${cardType}` : `[${JSON.stringify(cardType)}]`;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* The loop, in the four facts a harness cannot infer from a prop table.
|
|
149
|
-
*
|
|
150
|
-
* Shared by the card-backed and the card-host sections because they are the same
|
|
151
|
-
* contract seen from the two ends, and a second copy would be the drift this whole
|
|
152
|
-
* task exists to remove, one level up from the tool definition.
|
|
153
|
-
*
|
|
154
|
-
* `example` is the card the caller actually asked about, so the illustration is about
|
|
155
|
-
* their card rather than a fixed one they then have to translate.
|
|
156
|
-
*/
|
|
157
|
-
function loopWiring(example: string): string[] {
|
|
158
|
-
return [
|
|
159
|
-
'',
|
|
160
|
-
'#### Wiring the loop',
|
|
161
|
-
`- **Tool names are \`${KAI_TOOL_PREFIX}<card type>\`.** \`${toolNameForCardType(example)}\` produces \`{ type: "${example}" }\`. ` +
|
|
162
|
-
'Use `isCardTool(name)` to split card calls from your own tools; never match the prefix by hand.',
|
|
163
|
-
'- **`tool_call_id` becomes `CardEnvelope.id`, unchanged.** That is what makes a revision UPSERT: ' +
|
|
164
|
-
'a model that re-sends the same tool call id replaces the card in place instead of rendering a second copy of it. ' +
|
|
165
|
-
'Generating your own id breaks that silently.',
|
|
166
|
-
'- **`cardFromToolCall(name, input, { id: call.id })`** turns the call into a renderable envelope, ' +
|
|
167
|
-
'or returns `null` when it is one of your own tools so the loop falls through to it. It never throws.',
|
|
168
|
-
'- **Everything above is one import:** `import { cardTools, cardFromToolCall, isCardTool } from \'@kitn.ai/ui/schemas\'`. ' +
|
|
169
|
-
`The raw documents also ship as JSON (\`@kitn.ai/ui/schemas/${example}.schema.json\`) for a Python or Go backend.`,
|
|
170
|
-
];
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** The card-backed section: schema + a GENERATED tool definition. */
|
|
174
|
-
function renderCardContract(tag: string, cardType: CardSchemaName, provider: ToolProvider): string[] {
|
|
175
|
-
const schema = cardSchemas[cardType];
|
|
176
|
-
|
|
177
|
-
// GENERATED, NEVER RESTATED.
|
|
178
|
-
//
|
|
179
|
-
// This calls the same `cardTools` a consumer's route calls, on the same schema, so
|
|
180
|
-
// the definition served here cannot diverge from the one they ship — not when a
|
|
181
|
-
// schema gains a field, not when the projection changes what it strips. A literal
|
|
182
|
-
// typed into this file would read identically today and rot on the first schema
|
|
183
|
-
// change, which is exactly the hand-copy drift this tool exists to remove.
|
|
184
|
-
// reference.test.ts asserts byte-equality against BOTH `cardTools({ [type]: schema },
|
|
185
|
-
// …)` and the matching entry of the whole-registry `cardTools({ provider })`, so a
|
|
186
|
-
// hand-edit here fails a test rather than shipping.
|
|
187
|
-
const [def] = cardTools({ [cardType]: schema }, { provider });
|
|
188
|
-
|
|
189
|
-
const lines: string[] = [
|
|
190
|
-
'',
|
|
191
|
-
'### Card contract',
|
|
192
|
-
`\`<${tag}>\` renders \`CardEnvelope.type: "${cardType}"\`. A model does not emit an envelope; ` +
|
|
193
|
-
`it calls the tool \`${toolNameForCardType(cardType)}\`, and the kit turns that call back into one.`,
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
lines.push(
|
|
197
|
-
'',
|
|
198
|
-
`#### Tool definition — provider \`${provider}\``,
|
|
199
|
-
`Generated by \`cardTools({ ${asKey(cardType)}: cardSchemas${asMember(cardType)} }, { provider: '${provider}' })\`. ` +
|
|
200
|
-
'Copy it; do not retype it, and do not hand-maintain a second copy — regenerate instead.',
|
|
201
|
-
`Ask again with \`provider\` set to \`openai\`, \`anthropic\` or \`jsonschema\` for the other envelopes. ` +
|
|
202
|
-
'They are NOT interchangeable: OpenAI nests the schema at `function.parameters`, Anthropic puts it flat at `input_schema`.',
|
|
203
|
-
...fence(TOOL_FENCE, def),
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
lines.push(
|
|
207
|
-
'',
|
|
208
|
-
'#### Card data JSON Schema',
|
|
209
|
-
`\`import { cardSchemas } from '@kitn.ai/ui/schemas'\` → \`cardSchemas${asMember(cardType)}\`. ` +
|
|
210
|
-
`Raw document: \`@kitn.ai/ui/schemas/${cardType}.schema.json\`.`,
|
|
211
|
-
'This is the authored contract, and it is what `registry.validate()` checks arriving data against. ' +
|
|
212
|
-
'The tool definition above carries the same document with `$schema`, `$id` and `x-kai-*` stripped — ' +
|
|
213
|
-
'that projection is `cardTools`\' job, so do not put a raw schema on the wire yourself.',
|
|
214
|
-
...fence(SCHEMA_FENCE, schema),
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
lines.push(...loopWiring(cardType));
|
|
218
|
-
return lines;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/** The card-host section: no schema of its own, but this is where the props live. */
|
|
222
|
-
function renderCardHost(tag: string): string[] {
|
|
223
|
-
const rows = cardSchemaNames.map((type) => {
|
|
224
|
-
const cardTag = cardTagForType(type);
|
|
225
|
-
return `- \`${type}\` → \`<${cardTag ?? '(no element)'}>\`, tool \`${toolNameForCardType(type)}\``;
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
return [
|
|
229
|
-
'',
|
|
230
|
-
'### Card contract',
|
|
231
|
-
`\`<${tag}>\` renders generative-UI cards inside the thread. It is a HOST: it draws whatever ` +
|
|
232
|
-
'envelopes arrive, and carries the two props that say what a card may be.',
|
|
233
|
-
'',
|
|
234
|
-
'- **`cardTypes`** — `Record<envelope type, custom element tag>`. What DRAWS a card. ' +
|
|
235
|
-
`Merged over the built-ins, so your entry overrides ours and the other ${cardSchemaNames.length - 1} still render.`,
|
|
236
|
-
'- **`cardSchemas`** — `Record<envelope type, JSON Schema>`. What a VALID card looks like. ' +
|
|
237
|
-
`This is the prop that carries YOUR OWN card schemas into the browser validator; the ${cardSchemaNames.length} built-ins are already known. ` +
|
|
238
|
-
'Both are objects, so both are JS properties (`el.cardSchemas = …`), never HTML attributes.',
|
|
239
|
-
'',
|
|
240
|
-
'Write both once with `createCardRegistry({ use, custom })` from `@kitn.ai/ui/schemas` and thread it to both ends: ' +
|
|
241
|
-
'`el.cardTypes = cards.tags` / `el.cardSchemas = cards.validationSchemas` on the client, `cardTools(cards, { provider })` on the route.',
|
|
242
|
-
'',
|
|
243
|
-
'Built-in card types (ask `component_reference` for one of these tags to get its schema and tool definition):',
|
|
244
|
-
...rows,
|
|
245
|
-
...loopWiring(cardSchemaNames[0]),
|
|
246
|
-
];
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
250
|
-
// The composition catalog: invariants, and recipe membership
|
|
251
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* An invariant applies to a tag if it is unscoped by tag, or names it.
|
|
255
|
-
*
|
|
256
|
-
* `appliesTo.targets` deliberately does NOT filter here: `upgrade-race` is
|
|
257
|
-
* scoped to script-tag DELIVERY, which is a fact about how the page loads and
|
|
258
|
-
* not about which element is on it — every element can be dropped onto a CDN
|
|
259
|
-
* page. So it is served everywhere and the scope is RENDERED (see `scopeOf`),
|
|
260
|
-
* which is the difference between a conditional rule a reader can apply and an
|
|
261
|
-
* unqualified one they will either over-apply or stop trusting.
|
|
262
|
-
*/
|
|
263
|
-
function invariantsFor(tag: string): TInvariant[] {
|
|
264
|
-
return invariants.filter((i) => !i.appliesTo.tags || i.appliesTo.tags.includes(tag));
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* The recipe's nesting, as markup a reader can paste.
|
|
269
|
-
*
|
|
270
|
-
* `noteSep` is how much of the record to print: the appendix passes ' — ' and
|
|
271
|
-
* gets the WHY, an element lookup passes '' and gets only the shape, on the same
|
|
272
|
-
* split the wiring rows already use. A recipe with no `composition` prints
|
|
273
|
-
* nothing at all rather than "flat" — the field being absent means nobody
|
|
274
|
-
* decided, and a rendered "(none)" would turn a gap into a claim.
|
|
275
|
-
*/
|
|
276
|
-
function compositionLines(r: TSurfaceRecipe, noteSep: string): string[] {
|
|
277
|
-
if (!r.composition) return [];
|
|
278
|
-
return [
|
|
279
|
-
'- **Composition** — where the parts go (a slotted child, not a sibling):',
|
|
280
|
-
...r.composition.map(
|
|
281
|
-
(c) =>
|
|
282
|
-
` - \`<${c.child} slot="${c.slot}">\` goes INSIDE \`<${c.parent}>\`` +
|
|
283
|
-
(noteSep && c.note ? `${noteSep}${c.note}` : ''),
|
|
284
|
-
),
|
|
285
|
-
];
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function recipesFor(tag: string): TSurfaceRecipe[] {
|
|
289
|
-
return surfaceRecipes.filter((r) => r.ingredients.includes(tag));
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* How the coverage of one invariant reads — never a bare status word, and never
|
|
294
|
-
* silence.
|
|
295
|
-
*
|
|
296
|
-
* Three of the catalog's records are enforced by NOTHING and two more by half of
|
|
297
|
-
* what they say. A section that printed every rule as an equal-looking bullet
|
|
298
|
-
* would put back exactly the overstatement those records were rewritten to
|
|
299
|
-
* remove, one layer further out where it is harder to see. The wording also says
|
|
300
|
-
* whose code the guard reads: every path here is inside the KIT's own repo, and
|
|
301
|
-
* none of them checks the consumer's.
|
|
302
|
-
*/
|
|
303
|
-
function coverageOf(inv: TInvariant): string {
|
|
304
|
-
const by = inv.enforcedBy;
|
|
305
|
-
// `guard` is '' only for kind:'none', and that combination reaches neither the
|
|
306
|
-
// 'enforced' nor the 'partial' branch below: invariants.test.ts ("open ⟺
|
|
307
|
-
// enforcedBy.kind none") asserts the equivalence in BOTH directions, so a
|
|
308
|
-
// kind:'none' record is always status:'open'. Named here because a reader of
|
|
309
|
-
// this file alone cannot see what makes `enforced by ` with nothing after it
|
|
310
|
-
// unreachable.
|
|
311
|
-
const guard =
|
|
312
|
-
by.kind === 'test'
|
|
313
|
-
? `the kit's own tests (${by.paths.join(', ')})`
|
|
314
|
-
: by.kind === 'lint'
|
|
315
|
-
? `the kit's \`${by.script}\` script, in required CI`
|
|
316
|
-
: by.kind === 'structural'
|
|
317
|
-
? `a structural guarantee in ${by.path}`
|
|
318
|
-
: '';
|
|
319
|
-
|
|
320
|
-
switch (inv.status) {
|
|
321
|
-
case 'enforced':
|
|
322
|
-
return `enforced by ${guard}`;
|
|
323
|
-
case 'partial':
|
|
324
|
-
return `PARTIALLY ENFORCED: one half is covered, by ${guard}; the statement says which half is not`;
|
|
325
|
-
case 'open':
|
|
326
|
-
return (
|
|
327
|
-
'NOT ENFORCED: nothing in the kit checks this' +
|
|
328
|
-
(by.kind === 'none' && by.until ? `, until ${by.until}` : '') +
|
|
329
|
-
'. A rule you apply, not a guarantee you will be warned about'
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/** What narrows an invariant, when something does. `targets` is not `tags`. */
|
|
335
|
-
function scopeOf(inv: TInvariant): string {
|
|
336
|
-
const { tags, targets, parts } = inv.appliesTo;
|
|
337
|
-
const bits: string[] = [];
|
|
338
|
-
if (tags) bits.push(`only ${tags.join(', ')}`);
|
|
339
|
-
if (targets) bits.push(`${targets.join(' / ')} delivery only`);
|
|
340
|
-
if (parts) bits.push(`parts ${parts.join(', ')}`);
|
|
341
|
-
return bits.join('; ');
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* The wrong/right pairs, as one fenced block per invariant.
|
|
346
|
-
*
|
|
347
|
-
* A fence rather than inline code because a `right` form is allowed to span
|
|
348
|
-
* lines (the URL guards do), and because the pairs are meant to be
|
|
349
|
-
* pattern-matched and grepped verbatim — the self-audit checklist greps emitted
|
|
350
|
-
* code for the `wrong` form and expects zero hits, which only works if what is
|
|
351
|
-
* served here is the literal and not a paraphrase of it.
|
|
352
|
-
*/
|
|
353
|
-
function exampleLines(examples: TInvariantExample[]): string[] {
|
|
354
|
-
if (examples.length === 0) return [];
|
|
355
|
-
const out: string[] = ['', '```js'];
|
|
356
|
-
examples.forEach((ex, i) => {
|
|
357
|
-
if (i > 0) out.push('');
|
|
358
|
-
out.push('// WRONG', ex.wrong, '// RIGHT', ex.right);
|
|
359
|
-
if (ex.note) out.push(...ex.note.split('\n').map((l) => `// ${l}`));
|
|
360
|
-
});
|
|
361
|
-
out.push('```');
|
|
362
|
-
return out;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* The one sentence saying how much of this section is actually guarded.
|
|
367
|
-
*
|
|
368
|
-
* BOTH numerators are derived and both are needed. `open` alone was the first
|
|
369
|
-
* form of this line, and it is the more quotable half: "3 of the 7 below are
|
|
370
|
-
* enforced by NOTHING" compresses, in any reader summarising it, into "3
|
|
371
|
-
* unenforced, 4 enforced" — and two of that four are `partial`, covered on one
|
|
372
|
-
* half only. That is this repo's own compression-drops-the-qualifier failure,
|
|
373
|
-
* sitting in the sentence written to prevent it. Naming both counts leaves the
|
|
374
|
-
* compression nothing to invent.
|
|
375
|
-
*
|
|
376
|
-
* Returns '' when every applicable record is fully enforced, so the line can
|
|
377
|
-
* never outlive the gap it describes and become a comfortable falsehood.
|
|
378
|
-
*
|
|
379
|
-
* Exported for reference.test.ts, which drives all four count combinations over
|
|
380
|
-
* synthetic records — the real catalog can only instance one of them at a time.
|
|
381
|
-
*/
|
|
382
|
-
export function coverageSummary(applicable: TInvariant[]): string {
|
|
383
|
-
const open = applicable.filter((i) => i.status === 'open').length;
|
|
384
|
-
const partial = applicable.filter((i) => i.status === 'partial').length;
|
|
385
|
-
if (open === 0 && partial === 0) return '';
|
|
386
|
-
|
|
387
|
-
const total = applicable.length;
|
|
388
|
-
const half = (n: number) => `only half of what ${n === 1 ? 'it says' : 'they say'}`;
|
|
389
|
-
const clauses: string[] = [];
|
|
390
|
-
|
|
391
|
-
if (open > 0) {
|
|
392
|
-
clauses.push(`${open} of the ${total} below ${open === 1 ? 'is' : 'are'} enforced by NOTHING at all`);
|
|
393
|
-
}
|
|
394
|
-
if (partial > 0) {
|
|
395
|
-
clauses.push(
|
|
396
|
-
open > 0
|
|
397
|
-
? `${partial} more by ${half(partial)}`
|
|
398
|
-
: `${partial} of the ${total} below ${partial === 1 ? 'is' : 'are'} enforced by ${half(partial)}`,
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
return ` ${clauses.join(', and ')}.`;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* `###` to match every other section heading in this file (see '### Props'),
|
|
406
|
-
* `####` for the per-record blocks, matching the card contract's sub-headings.
|
|
407
|
-
*
|
|
408
|
-
* Each invariant gets its heading (id, scope, coverage) and its one-line
|
|
409
|
-
* `statement` — enough to apply the rule and to know how much to trust it —
|
|
410
|
-
* but NOT the diagnosis and wrong/right examples. Those are the bulk: measured
|
|
411
|
-
* on this tree, the full body of the 7 catalog records runs ~13 KB, and every
|
|
412
|
-
* unscoped record (5 of 7) applies to all 80 elements, so printing the full
|
|
413
|
-
* body here paid that in full on every lookup. `renderInvariantAppendix`
|
|
414
|
-
* carries the long form exactly once; this function points to it instead of
|
|
415
|
-
* repeating it.
|
|
416
|
-
*/
|
|
417
|
-
function catalogSectionLines(tag: string): string[] {
|
|
418
|
-
const applicable = invariantsFor(tag);
|
|
419
|
-
const lines: string[] = [];
|
|
420
|
-
|
|
421
|
-
if (applicable.length > 0) {
|
|
422
|
-
lines.push(
|
|
423
|
-
'',
|
|
424
|
-
'### Invariants',
|
|
425
|
-
'Rules that have already broken real consumers of this kit. Each block says what enforces ' +
|
|
426
|
-
'it — read that line rather than assuming CI catches a violation, because nothing here ' +
|
|
427
|
-
'reads YOUR code.' + coverageSummary(applicable) + ' Diagnosis and wrong/right examples for ' +
|
|
428
|
-
'every invariant are served once, not repeated per element — call component_reference with ' +
|
|
429
|
-
'{ name: "invariants" }.',
|
|
430
|
-
);
|
|
431
|
-
|
|
432
|
-
for (const inv of applicable) {
|
|
433
|
-
const scope = scopeOf(inv);
|
|
434
|
-
lines.push('', `#### ${inv.id}${scope ? ` (${scope})` : ''} — ${coverageOf(inv)}`, inv.statement);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// No recipe, no section. An element that is in none gets its universal
|
|
439
|
-
// invariants and nothing else — a "part of: (none)" row would be a fabricated
|
|
440
|
-
// membership claim dressed as an empty one.
|
|
441
|
-
const recipes = recipesFor(tag);
|
|
442
|
-
if (recipes.length > 0) {
|
|
443
|
-
lines.push(
|
|
444
|
-
'',
|
|
445
|
-
'### Appears in surface recipes',
|
|
446
|
-
'Compositions this element is part of, each with the whole ingredient list and the host ' +
|
|
447
|
-
'wiring — nothing coordinates one element with another except your own code ' +
|
|
448
|
-
'(host-coordinates). The WHY behind each wiring edge, and the caveats on the nesting ' +
|
|
449
|
-
'below, are served once rather than repeated per ingredient — call component_reference ' +
|
|
450
|
-
'with { name: "recipes" }.',
|
|
451
|
-
);
|
|
452
|
-
for (const r of recipes) {
|
|
453
|
-
lines.push(
|
|
454
|
-
'',
|
|
455
|
-
`#### ${r.id} — ${r.intent}`,
|
|
456
|
-
`- **Ingredients:** ${r.ingredients.map((t) => `\`<${t}>\``).join(', ')}`,
|
|
457
|
-
`- **Delivery:** ${r.targets.join(', ')} · archetype: ${r.archetypes.join(', ')}`,
|
|
458
|
-
`- **Backend:** your own endpoint, read with \`${r.backend.reader}\` from \`@kitn.ai/ui/wire\``,
|
|
459
|
-
// WHERE the parts go. Printed per element and not only in the appendix,
|
|
460
|
-
// because this is the one fact a builder cannot infer from anything else
|
|
461
|
-
// on the page: the wiring rows say which event drives which property and
|
|
462
|
-
// are silent about nesting, so an element lookup that omitted this left
|
|
463
|
-
// the reader to guess between a child and a sibling. Short enough to
|
|
464
|
-
// repeat; the `note` (the WHY) stays in the appendix with the wiring notes.
|
|
465
|
-
...compositionLines(r, ''),
|
|
466
|
-
// Bare ids, deliberately. This row is a DEPENDENCY list, not a coverage
|
|
467
|
-
// claim, and it can only ever be read a few lines below the full
|
|
468
|
-
// `### Invariants` section in the same response, where each of these ids
|
|
469
|
-
// already carries its own coverage line. Repeating the status here would
|
|
470
|
-
// print it a second (and, with two recipes, a third) time per element for
|
|
471
|
-
// no fact a reader does not already have on the page.
|
|
472
|
-
`- **Invariants it leans on:** ${r.invariants.join(', ')}`,
|
|
473
|
-
// Compact: the edge (event out of A, property into B) with no `note`.
|
|
474
|
-
// The note is the WHY — often a full sentence, sometimes several — and
|
|
475
|
-
// repeating it is the same shape of duplication task 4 removed from
|
|
476
|
-
// invariants: this recipe's ingredients (kai-chat, kai-conversations,
|
|
477
|
-
// kai-resizable, kai-artifact) all print this identical wiring list.
|
|
478
|
-
// `renderRecipeAppendix` carries the notes exactly once.
|
|
479
|
-
'- **Wiring** — event out of A, property into B, wired by the host:',
|
|
480
|
-
);
|
|
481
|
-
for (const w of r.wiring) {
|
|
482
|
-
lines.push(` - \`<${w.from}>\` fires \`${w.event}\` → host sets \`${w.to}.${w.property}\``);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
return lines;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* The long-form recipe reference, served exactly once rather than repeated on
|
|
492
|
-
* every ingredient. `catalogSectionLines` prints the ingredients, delivery,
|
|
493
|
-
* backend and a compact wiring list (edge only, no `note`) per element and
|
|
494
|
-
* points here for the rest — the WHY behind each wiring edge, which is the
|
|
495
|
-
* bulk: `workspace-chat` alone has 4 ingredients, and every one of them
|
|
496
|
-
* printed every wiring note in full before this moved. Reached via
|
|
497
|
-
* `component_reference({ name: "recipes" })`.
|
|
498
|
-
*/
|
|
499
|
-
function renderRecipeAppendix(): string[] {
|
|
500
|
-
const lines: string[] = [
|
|
501
|
-
`## Surface recipe catalog (${surfaceRecipes.length} total) — wiring notes`,
|
|
502
|
-
'',
|
|
503
|
-
'Every element lookup that appears in a recipe lists its ingredients, delivery, backend and ' +
|
|
504
|
-
'a compact wiring list (event out of A, property into B). This is the long form: the WHY ' +
|
|
505
|
-
'behind each wiring edge, written once here rather than repeated on every ingredient.',
|
|
506
|
-
];
|
|
507
|
-
|
|
508
|
-
for (const r of surfaceRecipes) {
|
|
509
|
-
lines.push(
|
|
510
|
-
'',
|
|
511
|
-
`#### ${r.id} — ${r.intent}`,
|
|
512
|
-
`- **Ingredients:** ${r.ingredients.map((t) => `\`<${t}>\``).join(', ')}`,
|
|
513
|
-
`- **Delivery:** ${r.targets.join(', ')} · archetype: ${r.archetypes.join(', ')}`,
|
|
514
|
-
`- **Backend:** your own endpoint, read with \`${r.backend.reader}\` from \`@kitn.ai/ui/wire\``,
|
|
515
|
-
`- **Invariants it leans on:** ${r.invariants.join(', ')}`,
|
|
516
|
-
...compositionLines(r, ' — '),
|
|
517
|
-
'- **Wiring** — event out of A, property into B, wired by the host:',
|
|
518
|
-
);
|
|
519
|
-
for (const w of r.wiring) {
|
|
520
|
-
lines.push(
|
|
521
|
-
` - \`<${w.from}>\` fires \`${w.event}\` → host sets \`${w.to}.${w.property}\`` +
|
|
522
|
-
(w.note ? ` — ${w.note}` : ''),
|
|
523
|
-
);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return lines;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* The long-form invariant reference, served exactly once rather than repeated
|
|
532
|
-
* on every element it applies to. `catalogSectionLines` prints only the id,
|
|
533
|
-
* scope and one-line statement per element and points here for the rest —
|
|
534
|
-
* this is that "rest": every record's full statement again for context, its
|
|
535
|
-
* diagnosis rows, and its wrong/right examples, each written once for the
|
|
536
|
-
* whole catalog regardless of how many of the 80 elements the record applies
|
|
537
|
-
* to. Reached via `component_reference({ name: "invariants" })`.
|
|
538
|
-
*/
|
|
539
|
-
function renderInvariantAppendix(): string[] {
|
|
540
|
-
const lines: string[] = [
|
|
541
|
-
`## Invariant catalog (${invariants.length} total) — diagnosis and examples`,
|
|
542
|
-
'',
|
|
543
|
-
'Every element lookup lists the invariants that apply to it by id and one-line statement. ' +
|
|
544
|
-
'This is the long form: full statement, diagnosis and wrong/right examples for each record, ' +
|
|
545
|
-
'written once here rather than repeated on every element it applies to.',
|
|
546
|
-
];
|
|
547
|
-
|
|
548
|
-
for (const inv of invariants) {
|
|
549
|
-
const scope = scopeOf(inv);
|
|
550
|
-
lines.push('', `#### ${inv.id}${scope ? ` (${scope})` : ''} — ${coverageOf(inv)}`, inv.statement);
|
|
551
|
-
if (inv.diagnosis.length > 0) {
|
|
552
|
-
lines.push('', 'If you are debugging:');
|
|
553
|
-
for (const d of inv.diagnosis) lines.push(`- ${d.symptom} → ${d.cause}`);
|
|
554
|
-
}
|
|
555
|
-
lines.push(...exampleLines(inv.examples));
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
return lines;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
562
|
-
// The programmatic layer and the code recipes
|
|
563
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
564
|
-
|
|
565
|
-
/** The topic names that all resolve to the programmatic-layer appendix. */
|
|
566
|
-
const PROGRAMMATIC_ALIASES = ['programmatic', 'state', 'wire', 'state-wire'] as const;
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* The `/state` + `/wire` appendix (rung-6 F-46): a marker-fenced section of the
|
|
570
|
-
* package-root `llms-full.txt`, which `build:api` DERIVES from the shipped
|
|
571
|
-
* `dist/state/*.d.ts` + `dist/wire/*.d.ts` (scripts/gen-llms-programmatic.mjs).
|
|
572
|
-
* Read, never restated: this tool restating one signature by hand is exactly
|
|
573
|
-
* the drift the generator exists to remove. The root copy is the CANONICAL and
|
|
574
|
-
* ONLY shipped copy (owner-ruled 2026-08-25): a second copy under `dist/llms/`
|
|
575
|
-
* used to ship too, ~293 KB of duplicate tarball weight — and it once went
|
|
576
|
-
* stale against the root while both claimed to be the artifact. It resolves
|
|
577
|
-
* relative to the manifest (`dist/custom-elements.json`), whose parent's
|
|
578
|
-
* parent is the package root in both contexts — bundled bin and source/vitest.
|
|
579
|
-
*/
|
|
580
|
-
/**
|
|
581
|
-
* The fence gen-llms-programmatic.mjs writes around the section inside
|
|
582
|
-
* llms-full.txt. REGISTERED COPY of `PROGRAMMATIC_MARKERS` in that script —
|
|
583
|
-
* this TS module cannot import the generator .mjs. If either side moves, the
|
|
584
|
-
* slice below misses and the reference tests fail on the "Missing build
|
|
585
|
-
* artifact" branch, so the drift is loud.
|
|
586
|
-
*/
|
|
587
|
-
const PROGRAMMATIC_START = '<!-- kai:programmatic:start -->';
|
|
588
|
-
const PROGRAMMATIC_END = '<!-- kai:programmatic:end -->';
|
|
589
|
-
|
|
590
|
-
function renderProgrammaticAppendix(): string {
|
|
591
|
-
// Sliced out of the SHIPPED llms-full.txt rather than served from a file of
|
|
592
|
-
// its own: a standalone copy was ~50 KB of duplicate tarball weight
|
|
593
|
-
// (verify:pack priced it), and slicing keeps one derivation with zero extra
|
|
594
|
-
// shipped bytes.
|
|
595
|
-
const path = join(dirname(resolveManifestPath()), '..', 'llms-full.txt');
|
|
596
|
-
const missing = (what: string) =>
|
|
597
|
-
`Missing build artifact: ${what}\n\n` +
|
|
598
|
-
'The programmatic-layer reference is generated from the shipped dist/*.d.ts by the ' +
|
|
599
|
-
'build (a marker-fenced section of the package-root llms-full.txt). Run `nx build ui` ' +
|
|
600
|
-
'(or `npm run build:api` in packages/ui) and ask again. It is deliberately not restated ' +
|
|
601
|
-
'here: a hand-typed copy would drift from the declarations your editor shows.';
|
|
602
|
-
if (!existsSync(path)) return missing(path);
|
|
603
|
-
const full = readFileSync(path, 'utf-8');
|
|
604
|
-
const start = full.indexOf(PROGRAMMATIC_START);
|
|
605
|
-
const end = full.indexOf(PROGRAMMATIC_END);
|
|
606
|
-
if (start === -1 || end === -1 || end <= start) {
|
|
607
|
-
return missing(`the ${PROGRAMMATIC_START} section inside ${path}`);
|
|
608
|
-
}
|
|
609
|
-
return full.slice(start + PROGRAMMATIC_START.length, end).trim();
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* One code recipe as files a builder pastes. The catalog half (ingredients,
|
|
614
|
-
* wiring edges, invariants — each executed by surfaces.test.ts) is the surface
|
|
615
|
-
* recipe of the same id; this is the body a data record cannot carry, and
|
|
616
|
-
* `verify:scaffold` compiles every `lang: 'ts'` file of it.
|
|
617
|
-
*/
|
|
618
|
-
function renderCodeRecipe(r: CodeRecipe): string {
|
|
619
|
-
const lines: string[] = [
|
|
620
|
-
`## Recipe: ${r.title} (\`${r.id}\`)`,
|
|
621
|
-
'',
|
|
622
|
-
r.intent,
|
|
623
|
-
'',
|
|
624
|
-
`**Elements composed:** ${r.ingredients.map((t) => `\`<${t}>\``).join(', ')}`,
|
|
625
|
-
'',
|
|
626
|
-
'**Read these before pasting:**',
|
|
627
|
-
...r.notes.map((n) => `- ${n}`),
|
|
628
|
-
];
|
|
629
|
-
for (const f of r.files) {
|
|
630
|
-
lines.push('', `### \`${f.path}\``, '', '```' + f.lang, f.code.trimEnd(), '```');
|
|
631
|
-
}
|
|
632
|
-
lines.push(
|
|
633
|
-
'',
|
|
634
|
-
'The wiring topology, invariants and composition claims behind this recipe are the ' +
|
|
635
|
-
`surface recipe of the same id — call component_reference with { name: "recipes" }.`,
|
|
636
|
-
);
|
|
637
|
-
return lines.join('\n');
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* The payload out of `CustomEvent<T>`, or `undefined` when there is no payload.
|
|
642
|
-
*
|
|
643
|
-
* The manifest types every event, but as the wrapper — printing that raw teaches
|
|
644
|
-
* a reader to write `CustomEvent<...>` where a payload belongs. Anything that is
|
|
645
|
-
* not of the form `CustomEvent<…>` has NO payload to print, and this returns
|
|
646
|
-
* `undefined` so the caller omits the `detail` clause entirely.
|
|
647
|
-
*
|
|
648
|
-
* That is read off the generator rather than guessed at. gen-element-api.mjs
|
|
649
|
-
* writes the CEM type as ``CustomEvent<${e.detail}>`` when the element declares a
|
|
650
|
-
* detail and the bare string `CustomEvent` when it does not — exactly two shapes,
|
|
651
|
-
* and the bare one means the detail is `void` (e.g. `'kai-click': void` in
|
|
652
|
-
* button.tsx). Passing an unrecognised type through unchanged looked like a safe
|
|
653
|
-
* fallback for an already-unwrapped payload; what it actually caught was the void
|
|
654
|
-
* events, which then rendered ``Carries no detail. `detail`: `CustomEvent` `` — a
|
|
655
|
-
* line contradicting itself, on 13 events across 10 elements. The whole-manifest
|
|
656
|
-
* probe in reference.test.ts holds both directions of the rule.
|
|
657
|
-
*/
|
|
658
|
-
function eventDetail(typeText: string | undefined): string | undefined {
|
|
659
|
-
const m = /^CustomEvent<([\s\S]*)>$/.exec(typeText?.trim() ?? '');
|
|
660
|
-
return m ? m[1].trim() || undefined : undefined;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
function formatReference(tag: string, provider: ToolProvider): string {
|
|
664
|
-
const el = getElement(tag);
|
|
665
|
-
|
|
666
|
-
if (!el) {
|
|
667
|
-
const all = listElements();
|
|
668
|
-
const sample = all.slice(0, 5).join(', ');
|
|
669
|
-
return (
|
|
670
|
-
`Unknown element: ${tag}\n\n` +
|
|
671
|
-
`Valid tags include: ${sample} (and ${Math.max(0, all.length - 5)} more).\n` +
|
|
672
|
-
`Call component_reference with no name (or name: "list") to list all ${all.length} elements.`
|
|
673
|
-
);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
const lines: string[] = [];
|
|
677
|
-
|
|
678
|
-
// ── Header ─────────────────────────────────────────────────────────────────
|
|
679
|
-
lines.push(`## <${tag}>`);
|
|
680
|
-
if (el.description) {
|
|
681
|
-
lines.push('', el.description.trim());
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// ── Getting the element ────────────────────────────────────────────────────
|
|
685
|
-
// FIRST, above every other section. An element that never upgrades renders
|
|
686
|
-
// nothing and logs NOTHING: the property assigns and reads back fine, and
|
|
687
|
-
// whenDefined() never settles, so the listener is never attached. That symptom
|
|
688
|
-
// is also what props-not-attributes blames on a different cause, so a reader
|
|
689
|
-
// who has the invariants and not this line is steered to the wrong diagnosis.
|
|
690
|
-
const entry = entryForTag(tag);
|
|
691
|
-
const iface = el.name;
|
|
692
|
-
const neverUpgrades =
|
|
693
|
-
'If you skip registering it the element never upgrades: nothing renders, ' +
|
|
694
|
-
'**no error and no warning is logged**, a property you set assigns and reads ' +
|
|
695
|
-
`back correctly, and \`customElements.whenDefined('${tag}')\` never resolves.`;
|
|
696
|
-
lines.push('', '### Getting the element');
|
|
697
|
-
if (entry) {
|
|
698
|
-
lines.push(
|
|
699
|
-
`Register it before you use it. ${neverUpgrades}`,
|
|
700
|
-
'',
|
|
701
|
-
'```ts',
|
|
702
|
-
"import '@kitn.ai/ui/elements';",
|
|
703
|
-
`import '@kitn.ai/ui/elements/${entry}'; // or just this one`,
|
|
704
|
-
'```',
|
|
705
|
-
);
|
|
706
|
-
} else {
|
|
707
|
-
// entryForTag is undefined exactly when register-impl.ts does not import this
|
|
708
|
-
// element's source file — i.e. it is NOT in the register-all bundle. The only
|
|
709
|
-
// current instance is kai-remote, a deliberate exception (opt-in cross-origin
|
|
710
|
-
// iframe card) documented at src/elements/element-diagnostics.ts:347-363 and
|
|
711
|
-
// vite.config.elements.ts:44-50. `import '@kitn.ai/ui/elements'` would NOT
|
|
712
|
-
// register a tag in this state, so asserting it here is exactly the false
|
|
713
|
-
// claim this section exists to prevent.
|
|
714
|
-
//
|
|
715
|
-
// The specifier is still NOT guessed — stripping `kai-` is wrong for ten of
|
|
716
|
-
// the eighty elements. `optInEntryForTag` reads it off the module the
|
|
717
|
-
// per-element build actually emitted, matched to this tag by the tag literal
|
|
718
|
-
// it registers; see the note there. Telling the reader to go look it up was
|
|
719
|
-
// the last place in this reference where "how to make the element exist" did
|
|
720
|
-
// not answer itself, and the answer was in the build config all along.
|
|
721
|
-
const optIn = optInEntryForTag(tag);
|
|
722
|
-
lines.push(
|
|
723
|
-
`**\`${tag}\` is opt-in — it is not part of \`import '@kitn.ai/ui/elements'\` ` +
|
|
724
|
-
'(register-all), and that import alone will NOT register it.** ' +
|
|
725
|
-
(optIn
|
|
726
|
-
? `Import its own entry point instead. ${neverUpgrades}`
|
|
727
|
-
: // No built module claims this tag, so there is no specifier to name.
|
|
728
|
-
// Stay honest rather than inventing one.
|
|
729
|
-
'Find its specific `@kitn.ai/ui/elements/<name>` entry point in the ' +
|
|
730
|
-
`package's published exports before using it. ${neverUpgrades}`),
|
|
731
|
-
);
|
|
732
|
-
if (optIn) {
|
|
733
|
-
lines.push('', '```ts', `import '@kitn.ai/ui/elements/${optIn}';`, '```');
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
if (iface) {
|
|
737
|
-
lines.push(
|
|
738
|
-
'',
|
|
739
|
-
`TypeScript: \`import type { ${iface} } from '@kitn.ai/ui/elements';\` — ` +
|
|
740
|
-
'the element interface ships with the package; do not hand-roll a structural type.',
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
// ── Contract note ──────────────────────────────────────────────────────────
|
|
745
|
-
lines.push(
|
|
746
|
-
'',
|
|
747
|
-
'### AI/UI contract',
|
|
748
|
-
'`kai-*` elements accept **array and object data as JavaScript properties** ' +
|
|
749
|
-
'(set in JavaScript via `el.property = value`, not as HTML attributes). ' +
|
|
750
|
-
'Events are native CustomEvents — listen with `el.addEventListener("event-name", handler)` ' +
|
|
751
|
-
'and read `event.detail` for the payload.',
|
|
752
|
-
);
|
|
753
|
-
|
|
754
|
-
// ── Card contract ─────────────────────────────────────────────────────────
|
|
755
|
-
// Attached to the two populations manifest.ts derives, and to nothing else. A
|
|
756
|
-
// reference that hangs card material off all 80 elements is worse than one that
|
|
757
|
-
// hangs it off none: it teaches a harness that every element takes a tool call.
|
|
758
|
-
const cardType = cardTypeForTag(tag);
|
|
759
|
-
if (cardType !== undefined && isCardSchemaName(cardType)) {
|
|
760
|
-
lines.push(...renderCardContract(tag, cardType, provider));
|
|
761
|
-
} else if (cardHostTags().includes(tag)) {
|
|
762
|
-
lines.push(...renderCardHost(tag));
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// ── Public JS properties ───────────────────────────────────────────────────
|
|
766
|
-
const publicFields = (el.members ?? []).filter(
|
|
767
|
-
(m) => m.kind === 'field' && m.privacy === 'public',
|
|
768
|
-
);
|
|
769
|
-
|
|
770
|
-
if (publicFields.length > 0) {
|
|
771
|
-
lines.push('', '### Props (JavaScript properties)');
|
|
772
|
-
for (const field of publicFields) {
|
|
773
|
-
const type = field.type?.text ?? 'unknown';
|
|
774
|
-
const jsOnly = isJsOnlyType(type);
|
|
775
|
-
const desc = field.description?.trim() ?? '';
|
|
776
|
-
const note = jsOnly ? ' ⚑ set as a JS property, not an HTML attribute' : '';
|
|
777
|
-
lines.push(`- **${field.name}** \`${type}\`${note}`);
|
|
778
|
-
if (desc) {
|
|
779
|
-
lines.push(` ${desc}`);
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// ── HTML attributes ────────────────────────────────────────────────────────
|
|
785
|
-
const attrs = el.attributes ?? [];
|
|
786
|
-
if (attrs.length > 0) {
|
|
787
|
-
lines.push('', '### Attributes (HTML-safe)');
|
|
788
|
-
for (const attr of attrs) {
|
|
789
|
-
const type = attr.type?.text ?? 'unknown';
|
|
790
|
-
const desc = attr.description?.trim() ?? '';
|
|
791
|
-
lines.push(`- **${attr.name}** \`${type}\``);
|
|
792
|
-
if (desc) {
|
|
793
|
-
lines.push(` ${desc}`);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
// ── Events ────────────────────────────────────────────────────────────────
|
|
799
|
-
const events = el.events ?? [];
|
|
800
|
-
if (events.length > 0) {
|
|
801
|
-
lines.push('', '### Events (CustomEvent, listen via addEventListener)');
|
|
802
|
-
for (const ev of events) {
|
|
803
|
-
const desc = ev.description?.trim() ?? '';
|
|
804
|
-
const detail = eventDetail(ev.type?.text);
|
|
805
|
-
lines.push(
|
|
806
|
-
detail
|
|
807
|
-
? `- **${ev.name}** — ${desc} \`detail\`: \`${detail}\``
|
|
808
|
-
: `- **${ev.name}** — ${desc}`,
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// ── Methods ───────────────────────────────────────────────────────────────
|
|
814
|
-
// The input half of the interaction surface. These were in the manifest and in
|
|
815
|
-
// the shipped types and rendered in NO reference, so the only way to find one
|
|
816
|
-
// was to read the kit's source.
|
|
817
|
-
const methods = (el.members ?? []).filter(isPublicMethod);
|
|
818
|
-
if (methods.length > 0) {
|
|
819
|
-
lines.push(
|
|
820
|
-
'',
|
|
821
|
-
'### Methods (call these on the element instance)',
|
|
822
|
-
`Get the element (\`const el = document.querySelector('${tag}')\`), then call it. ` +
|
|
823
|
-
'Methods drive the element from your code; the events above report back what the ' +
|
|
824
|
-
'user did. Both are public API.',
|
|
825
|
-
);
|
|
826
|
-
for (const method of methods) {
|
|
827
|
-
const desc = method.description?.trim() ?? '';
|
|
828
|
-
lines.push(`- **${methodSignature(method)}**${desc ? ` — ${desc}` : ''}`);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
// ── CSS custom properties ─────────────────────────────────────────────────
|
|
833
|
-
const cssProps = el.cssProperties ?? [];
|
|
834
|
-
if (cssProps.length > 0) {
|
|
835
|
-
lines.push('', '### CSS custom properties');
|
|
836
|
-
for (const prop of cssProps) {
|
|
837
|
-
const desc = prop.description?.trim() ?? '';
|
|
838
|
-
const def = prop.default ? ` (default: ${prop.default})` : '';
|
|
839
|
-
lines.push(`- **${prop.name}**${def}${desc ? ` — ${desc}` : ''}`);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// ── Composition slots ──────────────────────────────────────────────────────
|
|
844
|
-
const slots = el.slots ?? [];
|
|
845
|
-
if (slots.length > 0) {
|
|
846
|
-
lines.push(
|
|
847
|
-
'',
|
|
848
|
-
'### Composition slots',
|
|
849
|
-
'Project your own markup into these named regions — add a light-DOM child ' +
|
|
850
|
-
'with a `slot="…"` attribute (e.g. `<div slot="sidebar">…</div>`).',
|
|
851
|
-
);
|
|
852
|
-
for (const slot of slots) {
|
|
853
|
-
const desc = slot.description?.trim() ?? '';
|
|
854
|
-
lines.push(`- **${slot.name}**${desc ? ` — ${desc}` : ''}`);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
// ── Styleable parts (::part) ───────────────────────────────────────────────
|
|
859
|
-
const parts = el.cssParts ?? [];
|
|
860
|
-
if (parts.length > 0) {
|
|
861
|
-
lines.push(
|
|
862
|
-
'',
|
|
863
|
-
'### Styleable parts (`::part`)',
|
|
864
|
-
'Restyle these from outside the Shadow DOM via `' + tag + '::part(name) { … }`.',
|
|
865
|
-
);
|
|
866
|
-
for (const part of parts) {
|
|
867
|
-
const desc = part.description?.trim() ?? '';
|
|
868
|
-
lines.push(`- **${part.name}**${desc ? ` — ${desc}` : ''}`);
|
|
869
|
-
if (part.recipe) {
|
|
870
|
-
lines.push(' ```css', ` ${part.recipe}`, ' ```');
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
// ── The composition catalog ────────────────────────────────────────────────
|
|
876
|
-
lines.push(...catalogSectionLines(tag));
|
|
877
|
-
|
|
878
|
-
return lines.join('\n');
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
export const reference: Tool = {
|
|
882
|
-
name: 'component_reference',
|
|
883
|
-
description:
|
|
884
|
-
'Look up AI/UI (kai-*) web components: their tags, props, events, imperative methods, and usage examples. ' +
|
|
885
|
-
'For a card-backed element it also returns the card\'s JSON Schema and a ready-to-send ' +
|
|
886
|
-
'tool definition generated from it — pass `provider` to get that provider\'s envelope. ' +
|
|
887
|
-
'Also serves the programmatic layer (name: "programmatic" — the @kitn.ai/ui/state + ' +
|
|
888
|
-
'@kitn.ai/ui/wire streaming/mock/encode API) and complete code recipes ' +
|
|
889
|
-
'(e.g. name: "composed-thread" — a hand-composed thread with no <kai-chat>).',
|
|
890
|
-
inputSchema: z.object({
|
|
891
|
-
name: z
|
|
892
|
-
.string()
|
|
893
|
-
.optional()
|
|
894
|
-
.describe(
|
|
895
|
-
'The element tag, e.g. "kai-chat". Omit it (or pass "list") to get the ' +
|
|
896
|
-
'index of every element with a one-line summary, then ask again for the one you want. ' +
|
|
897
|
-
'Pass "invariants" for the full diagnosis and wrong/right examples behind every ' +
|
|
898
|
-
'invariant id an element lookup shows. Pass "recipes" for the full wiring notes ' +
|
|
899
|
-
'behind every surface recipe an element lookup names. Pass "programmatic" (or ' +
|
|
900
|
-
'"state" / "wire") for the @kitn.ai/ui/state + @kitn.ai/ui/wire API — streaming ' +
|
|
901
|
-
'folds, the mock responder, the SSE readers/encoders. Pass a code-recipe id ' +
|
|
902
|
-
'(e.g. "composed-thread") for a complete pasteable composition.',
|
|
903
|
-
),
|
|
904
|
-
provider: z
|
|
905
|
-
.enum(PROVIDERS)
|
|
906
|
-
.optional()
|
|
907
|
-
.describe(
|
|
908
|
-
'Which tool-definition envelope to project for a card-backed element. ' +
|
|
909
|
-
`Defaults to "${DEFAULT_PROVIDER}", the provider-neutral { name, description, schema } form.`,
|
|
910
|
-
),
|
|
911
|
-
}),
|
|
912
|
-
handler: async (args: Record<string, unknown>) => {
|
|
913
|
-
const name = typeof args.name === 'string' ? args.name.trim() : undefined;
|
|
914
|
-
|
|
915
|
-
// Validated HERE, not left to the zod schema above. server.ts advertises
|
|
916
|
-
// `inputSchema` over the protocol but hands `request.params.arguments` straight
|
|
917
|
-
// to this handler without parsing it, so an unrecognised provider would reach
|
|
918
|
-
// `cardTools`, which treats anything that is not "openai"/"anthropic" as the
|
|
919
|
-
// jsonschema branch. A caller asking for "gemini" would then get a definition in
|
|
920
|
-
// a shape they did not ask for, with nothing saying so. Refusing is the only
|
|
921
|
-
// answer that cannot be mistaken for an answer.
|
|
922
|
-
const rawProvider = args.provider;
|
|
923
|
-
if (rawProvider !== undefined && (typeof rawProvider !== 'string' || !isProvider(rawProvider))) {
|
|
924
|
-
return {
|
|
925
|
-
content: [
|
|
926
|
-
{
|
|
927
|
-
type: 'text' as const,
|
|
928
|
-
text:
|
|
929
|
-
`Unknown provider: ${JSON.stringify(rawProvider)}\n\n` +
|
|
930
|
-
`Valid providers are ${PROVIDERS.map((p) => `"${p}"`).join(', ')}. ` +
|
|
931
|
-
`Omit it to get "${DEFAULT_PROVIDER}", the provider-neutral { name, description, schema } form ` +
|
|
932
|
-
'that the Vercel AI SDK and most agent frameworks take directly.\n' +
|
|
933
|
-
'No tool definition was returned, because guessing which envelope you meant would hand you ' +
|
|
934
|
-
'a shape your provider rejects with nothing saying why.',
|
|
935
|
-
},
|
|
936
|
-
],
|
|
937
|
-
};
|
|
938
|
-
}
|
|
939
|
-
const provider: ToolProvider = rawProvider ?? DEFAULT_PROVIDER;
|
|
940
|
-
|
|
941
|
-
let text: string;
|
|
942
|
-
|
|
943
|
-
if (!name || name === 'list') {
|
|
944
|
-
const tags = listElements();
|
|
945
|
-
const cardRows = cardSchemaNames
|
|
946
|
-
.map((t) => cardTagForType(t))
|
|
947
|
-
.filter((t): t is string => t !== undefined);
|
|
948
|
-
text =
|
|
949
|
-
`AI/UI elements (${tags.length} total):\n\n` +
|
|
950
|
-
tags.map((t) => ` ${t}`).join('\n') +
|
|
951
|
-
'\n\nCall component_reference with a specific name (e.g. { name: "kai-chat" }) for full API details.' +
|
|
952
|
-
`\n\nCard-backed elements — ask for one of these to get its JSON Schema and a generated ` +
|
|
953
|
-
`\`${KAI_TOOL_PREFIX}*\` tool definition:\n ${cardRows.join(', ')}` +
|
|
954
|
-
`\nThe elements that HOST them (and carry the \`cardTypes\` / \`cardSchemas\` props): ${cardHostTags().join(', ')}` +
|
|
955
|
-
`\n\nCall component_reference with { name: "invariants" } for the full diagnosis and ` +
|
|
956
|
-
'wrong/right examples behind every invariant id shown on an element lookup.' +
|
|
957
|
-
`\n\nCall component_reference with { name: "recipes" } for the full wiring notes behind ` +
|
|
958
|
-
'every surface recipe an element lookup names.' +
|
|
959
|
-
`\n\nCall component_reference with { name: "programmatic" } for the @kitn.ai/ui/state + ` +
|
|
960
|
-
'@kitn.ai/ui/wire API — createAssistantStream, the part folds, createMockResponder ' +
|
|
961
|
-
'(and its scripted tool calls), the SSE readers and the provider encoders. That layer ' +
|
|
962
|
-
'is what a host wires when it composes elements by hand instead of using <kai-chat>.' +
|
|
963
|
-
`\n\nComplete pasteable compositions (code recipes): ${listCodeRecipes()
|
|
964
|
-
.map((r) => `{ name: "${r.id}" } — ${r.title}`)
|
|
965
|
-
.join('; ')}.`;
|
|
966
|
-
} else if (name === 'invariants') {
|
|
967
|
-
text = renderInvariantAppendix().join('\n');
|
|
968
|
-
} else if (name === 'recipes') {
|
|
969
|
-
text = renderRecipeAppendix().join('\n');
|
|
970
|
-
} else if ((PROGRAMMATIC_ALIASES as readonly string[]).includes(name)) {
|
|
971
|
-
text = renderProgrammaticAppendix();
|
|
972
|
-
} else if (getCodeRecipe(name)) {
|
|
973
|
-
text = renderCodeRecipe(getCodeRecipe(name)!);
|
|
974
|
-
} else {
|
|
975
|
-
text = formatReference(name, provider);
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
return { content: [{ type: 'text' as const, text }] };
|
|
979
|
-
},
|
|
980
|
-
};
|