@kitn.ai/ui 0.25.2 → 0.27.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 +17 -6
- package/bin/mcp.js +16 -3
- package/bin/route.js +23 -0
- package/bin/route.test.js +58 -0
- package/dist/{elements/chunks/Icon-b5A8hlHs.js → Icon-BnFKqqtY.js} +1 -1
- package/dist/action-icons-CBskfBMz.js +1 -0
- package/dist/arrow-down-Br0qtpsz.js +1 -0
- package/dist/arrow-left-Dj7xgE12.js +1 -0
- package/dist/artifact-CvXEm1lS.js +1 -0
- package/dist/assets/dev-5XzXYR21.js +91 -0
- package/dist/attachments-C43ZegEq.js +1 -0
- package/dist/audio-visualizer-B-79y1Tj.js +1 -0
- package/dist/badge-BpUbq8c0.js +1 -0
- package/dist/bash-InADTalH.js +1 -6
- package/dist/bell-sn17Ip9v.js +1 -0
- package/dist/{elements/chunks/button-B9okqG73.js → button-BH6rN0U-.js} +1 -1
- package/dist/card-renderer-Cb1gQmth.js +1 -0
- package/dist/card-routing-DifQgS7n.js +1 -0
- package/dist/check-DPeeMUYx.js +1 -0
- package/dist/checkbox-Dc9Yov_B.js +1 -0
- package/dist/checkbox-group-B1kDLLYk.js +1 -0
- package/dist/chevron-down-CHSWk7ZT.js +1 -0
- package/dist/chevron-right-B7l_fMgx.js +1 -0
- package/dist/choice-card-BT3c1S8g.js +1 -0
- package/dist/circle-Bb0yOpqM.js +1 -0
- package/dist/circle-check-BGZpCiz7.js +1 -0
- package/dist/circle-x-wobWkoSx.js +1 -0
- package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
- package/dist/code-block-CUQ5mtv0.js +1 -0
- package/dist/collapsible-CPJbf6FM.js +1 -0
- package/dist/components/attachment-types.d.ts +53 -1
- package/dist/components/attachments.d.ts +31 -0
- package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
- package/dist/components/audio-visualizer/index.d.ts +15 -1
- package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
- package/dist/components/card-renderer.d.ts +13 -0
- package/dist/components/card.d.ts +4 -0
- package/dist/components/chat-thread.d.ts +49 -42
- package/dist/components/code-block.d.ts +22 -0
- package/dist/components/conversation-item.d.ts +66 -1
- package/dist/components/conversation-list.d.ts +77 -0
- package/dist/components/form-widgets.d.ts +67 -2
- package/dist/components/form.d.ts +89 -0
- package/dist/components/message.d.ts +29 -0
- package/dist/components/reasoning.d.ts +6 -0
- package/dist/components/scroll-button.d.ts +11 -0
- package/dist/components/thread.d.ts +5 -0
- package/dist/components/toast.d.ts +2 -1
- package/dist/components/tool-types.d.ts +9 -0
- package/dist/components/voice-input.d.ts +8 -0
- package/dist/components/voice-output.d.ts +12 -1
- package/dist/components/workspace-shell.d.ts +87 -0
- package/dist/composer-CjngLzal.js +106 -0
- package/dist/confirm-card-DCx_A4bU.js +1 -0
- package/dist/construct-cli.es.js +1169 -0
- package/dist/context-BY8V-Nlp.js +1 -0
- package/dist/controllable-D43BKmtX.js +1 -0
- package/dist/conversation-list-D4lLU_yS.js +1 -0
- package/dist/copy-B6DO4PqB.js +1 -0
- package/dist/core-AYMC6_lb.js +12 -5874
- package/dist/{create-tween-CUzOlaMS.js → create-tween-BPzaefTp.js} +1 -1
- package/dist/{create-tween-B5Y4Im8G.js → create-tween-CnMHviKB.js} +1 -1
- package/dist/{create-tween-4z1XYLkR.js → create-tween-D1aiGZZh.js} +1 -1
- package/dist/{elements/chunks/create-tween-CUrM6D_o.js → create-tween-DUSQUKpr.js} +2 -2
- package/dist/css-M7EaDHN_.js +1 -6
- package/dist/custom-elements.json +3468 -1927
- package/dist/default-input-CucQEOqH.js +1 -0
- package/dist/define-CGGX-7Vg.js +1 -0
- package/dist/define.d.ts +4 -0
- package/dist/define.js +510 -0
- package/dist/define.server.d.ts +5 -0
- package/dist/define.server.js +506 -0
- package/dist/diagnostics/hook.d.ts +81 -0
- package/dist/diagnostics/index.d.ts +7 -0
- package/dist/diagnostics/report-request.d.ts +61 -0
- package/dist/diagnostics.d.ts +5 -0
- package/dist/diagnostics.js +209 -0
- package/dist/disclosure-CbLtajUQ.js +1 -0
- package/dist/dropdown-BwhViJFd.js +1 -0
- 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/autoloader.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.d.ts +1 -0
- package/dist/elements/checkbox-group.js +1 -0
- package/dist/elements/checkbox.d.ts +1 -0
- package/dist/elements/checkbox.js +1 -0
- 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.d.ts +1 -0
- package/dist/elements/conversation-item.js +1 -0
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +3 -3
- package/dist/elements/define-entry.d.ts +12 -0
- package/dist/elements/define.d.ts +27 -0
- package/dist/elements/diagnostic-events.d.ts +74 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/dock.d.ts +1 -0
- package/dist/elements/dock.js +243 -0
- package/dist/elements/dropdown.d.ts +1 -0
- package/dist/elements/dropdown.js +1 -0
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +37 -0
- package/dist/elements/element-diagnostics.d.ts +81 -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-grid.d.ts +1 -0
- package/dist/elements/pane-grid.js +1 -0
- 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.d.ts +1 -0
- package/dist/elements/radio-group.js +1 -0
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/register.d.ts +2 -0
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +3 -3
- 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.d.ts +1 -0
- package/dist/elements/select.js +1 -0
- 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.d.ts +1 -0
- package/dist/elements/slider.js +1 -0
- package/dist/elements/slots.d.ts +36 -4
- 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/elements.d.ts +589 -167
- package/dist/{elements/chunks/ellipsis-CVxqfsDZ.js → ellipsis-DFr4Vqr3.js} +1 -1
- package/dist/embed-5s_vU4J0.js +1 -0
- package/dist/engine-javascript-vq0WuIJl.js +14 -2516
- package/dist/{elements/chunks/external-link-DG2sRdQL.js → external-link-u9d85ORQ.js} +1 -1
- package/dist/file-text-CX7_x42o.js +1 -0
- package/dist/{elements/chunks/file-tree-yGWNK0Js.js → file-tree-D3kBjXI5.js} +1 -1
- package/dist/folder-V-YdIL8f.js +1 -0
- package/dist/form-BRNUMCN2.js +1 -0
- package/dist/github-dark-dimmed-DUshB20C.js +1 -4
- package/dist/github-light-JYsPkUQd.js +1 -4
- package/dist/hover-card-DaeiYrTA.js +1 -0
- package/dist/html-CPZ3oZQ7.js +1 -10
- package/dist/icon-BpixdZNq.js +1 -0
- package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +8473 -6470
- package/dist/index.server.js +6495 -4958
- package/dist/info-8mFsIjS3.js +1 -0
- package/dist/input-d1Yuu-hz.js +1 -0
- package/dist/javascript-C25yR2R2.js +1 -6
- package/dist/json-DxJze_jm.js +1 -6
- package/dist/kai-provider.es.js +40 -40
- package/dist/kai.es.js +1 -1
- package/dist/kbd-961zMPFB.js +1 -0
- package/dist/link-DlZZBGaR.js +1 -0
- package/dist/{elements/chunks/link-preview-Cf5KOP-i.js → link-preview-DIIbV2Sd.js} +1 -1
- package/dist/loader-YQszHFaW.js +1 -0
- package/dist/{elements/chunks/markdown-DbozyYqa.js → markdown-CVk1MPsj.js} +1 -1
- package/dist/mcp.es.js +3873 -544
- package/dist/message-CwKVEdZg.js +1 -0
- package/dist/message-DS8lzHc1.js +1 -0
- package/dist/message-circle-Xf8Q-vZp.js +1 -0
- package/dist/message-square-Cxnwgkns.js +1 -0
- package/dist/{elements/chunks/minimize-2-SegJ_oku.js → minimize-2-UEZmP2QT.js} +1 -1
- package/dist/{elements/chunks/model-switcher-D7JrFFHp.js → model-switcher-Kk1jEQ5t.js} +1 -1
- package/dist/{elements/chunks/overlay-CV7z2YuX.js → overlay-C1od6LOz.js} +1 -1
- package/dist/panel-right-ryET0yyn.js +1 -0
- package/dist/paperclip-BDNoZFJP.js +1 -0
- package/dist/play-OFIvYXUQ.js +1 -0
- package/dist/primitives/card-data-types.d.ts +49 -0
- package/dist/primitives/card-routing.d.ts +1 -33
- package/dist/primitives/card-validate.d.ts +2 -2
- package/dist/primitives/chat-config.d.ts +29 -2
- package/dist/primitives/field-mask.d.ts +96 -0
- package/dist/primitives/field-semantics.d.ts +36 -0
- package/dist/primitives/input-mask.d.ts +46 -0
- package/dist/primitives/url-scheme-policy.d.ts +34 -0
- package/dist/primitives/use-resize-observer.d.ts +23 -0
- package/dist/primitives/use-speech-recognition.d.ts +8 -0
- package/dist/primitives/use-text-stream.d.ts +5 -0
- package/dist/progress-bar-BvYX0aoy.js +1 -0
- package/dist/prompt-suggestion-BRFu2lcu.js +1 -0
- package/dist/radio-DcL23cNJ.js +1 -0
- package/dist/react/index.d.ts +306 -283
- package/dist/react.js +309 -247
- package/dist/reasoning-Cackq4Rh.js +1 -0
- package/dist/register-impl-C7rENvPK.js +424 -0
- package/dist/{elements/chunks/resizable-Dpzjlvp4.js → resizable-Cp9HUYih.js} +1 -1
- package/dist/rotate-ccw-0DLRDHH5.js +1 -0
- package/dist/rotate-cw-DOB9IGcU.js +1 -0
- package/dist/schemas/form.schema.json +21 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/tool-defs.d.ts +45 -0
- package/dist/schemas.js +398 -305
- package/dist/scroll-area-emVmWP4K.js +1 -0
- package/dist/scroll-button-CeP_gv1x.js +1 -0
- package/dist/select-CWmu00tS.js +1 -0
- package/dist/{elements/chunks/separator-DH2r_ZSZ.js → separator-CE6vly6z.js} +1 -1
- package/dist/{elements/chunks/settings-BFMOd6yB.js → settings-CE-78SvZ.js} +1 -1
- package/dist/{elements/chunks/settings-group-B3VZKIcz.js → settings-group-ZFWNxFQR.js} +1 -1
- package/dist/{elements/chunks/skeleton-N8BuWYmf.js → skeleton-BebdP4mf.js} +1 -1
- package/dist/slider-BAKRYUlz.js +1 -0
- package/dist/slots-DaNjX0rc.js +1 -0
- package/dist/{solid-BMuDmFo_.js → solid-BE5ui6sy.js} +10672 -8116
- package/dist/{solid-CGYNdLRR.js → solid-DFhsce3O.js} +8137 -6056
- package/dist/solid.d.ts +15 -0
- package/dist/solid.js +248 -235
- package/dist/solid.server.js +248 -235
- package/dist/source-B0FlguSx.js +1 -0
- package/dist/star-CBMZvLuN.js +1 -0
- package/dist/state/index.d.ts +5 -1
- package/dist/state/mock.d.ts +32 -2
- package/dist/state/persistence.d.ts +51 -0
- package/dist/state/stream.d.ts +50 -0
- package/dist/state/threads.d.ts +71 -0
- package/dist/state.js +297 -172
- package/dist/store-7eoadydQ.js +1 -0
- package/dist/svelte--5p79yCD.js +1 -15
- package/dist/switch-CViARZCy.js +1 -0
- package/dist/tasks-card-MjCcOhR_.js +1 -0
- package/dist/text-shimmer-DKlwRF2G.js +1 -0
- package/dist/textarea-3ay2Me2-.js +1 -0
- package/dist/theme.tokens.css +82 -13
- package/dist/{elements/chunks/thumbs-up-DQe0hvkZ.js → thumbs-up-DQcu2HMO.js} +1 -1
- package/dist/toast-store-C6yKOhbk.js +1 -0
- package/dist/{elements/chunks/tool-C1YtxwPu.js → tool-BCYNlfKy.js} +1 -1
- package/dist/{elements/chunks/tooltip-BqwnFWhn.js → tooltip-05zI4hjs.js} +1 -1
- package/dist/trash-2-BR1RxGky.js +1 -0
- package/dist/{elements/chunks/triangle-alert-B6or7F5u.js → triangle-alert-DHohDOCy.js} +1 -1
- package/dist/tsx-B8rCNbgL.js +1 -6
- package/dist/types.d.ts +4 -2
- package/dist/typescript-RycA9KXf.js +1 -6
- package/dist/ui/checkbox-group.d.ts +83 -0
- package/dist/ui/checkbox.d.ts +40 -0
- package/dist/ui/dock.d.ts +131 -0
- package/dist/ui/hover-card.d.ts +44 -0
- package/dist/ui/icon.d.ts +3 -0
- package/dist/ui/input.d.ts +48 -2
- package/dist/ui/radio.d.ts +85 -0
- package/dist/ui/select.d.ts +71 -0
- package/dist/ui/slider.d.ts +65 -0
- package/dist/ui/switch.d.ts +9 -2
- package/dist/upload-BbGW6A_u.js +1 -0
- package/dist/url-scheme-policy-DHpoTJwB.js +1 -0
- package/dist/use-card-resolution-CJW4grFa.js +1 -0
- package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-BUOVgPOB.js} +27 -27
- package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CUsUJvFI.js} +28 -28
- package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CW2i4bfr.js} +2 -2
- package/dist/{elements/chunks/variant-aurora-QXTZPyST.js → variant-aurora-xiMPty8f.js} +2 -2
- package/dist/variant-custom-BQtOnmeO.js +1 -0
- package/dist/{variant-custom-BhS9wIpU.js → variant-custom-CAm9L-E5.js} +65 -65
- package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-CAnzzppW.js} +40 -40
- package/dist/variant-custom-D91HjAKz.js +1 -0
- package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-Ca1Ls4_y.js} +21 -21
- package/dist/{variant-wave-CbVsmgwT.js → variant-wave-CxX39DKd.js} +25 -25
- package/dist/{variant-wave-BwzrHD1s.js → variant-wave-DYyzIIZv.js} +2 -2
- package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-uY5crU_K.js} +2 -2
- package/dist/vue-BmIZj4XD.js +1 -33
- package/dist/wire/chunk.d.ts +47 -0
- package/dist/wire/diagnostics.d.ts +575 -0
- package/dist/wire/encode-probe.d.ts +70 -0
- package/dist/wire/encode.d.ts +24 -0
- package/dist/wire/index.d.ts +2 -0
- package/dist/wire/sse.d.ts +10 -2
- package/dist/wire.js +917 -480
- package/dist/x-C5m1JFgi.js +1 -0
- package/frameworks/react/index.tsx +325 -108
- package/llms-full.txt +1354 -82
- package/llms.txt +6 -3
- package/package.json +39 -6
- package/src/agent-tooling/archetypes.ts +41 -9
- package/src/agent-tooling/catalog/README.md +676 -0
- package/src/agent-tooling/catalog/catalog-types.ts +231 -0
- package/src/agent-tooling/catalog/fabrications.ts +96 -0
- package/src/agent-tooling/catalog/invariants.ts +284 -0
- package/src/agent-tooling/catalog/labs-titles.ts +114 -0
- package/src/agent-tooling/catalog/scenarios.ts +87 -0
- package/src/agent-tooling/catalog/surfaces.ts +347 -0
- package/src/agent-tooling/construct/cli-entry.ts +8 -0
- package/src/agent-tooling/construct/cli.ts +131 -0
- package/src/agent-tooling/construct/codegen.ts +1353 -0
- package/src/agent-tooling/construct/construct.v1.schema.json +250 -0
- package/src/agent-tooling/construct/dev.ts +148 -0
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +7 -0
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +44 -0
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +23 -0
- package/src/agent-tooling/construct/schema.ts +371 -0
- package/src/agent-tooling/integrations/anthropic.ts +7 -1
- package/src/agent-tooling/integrations/cloudflare.ts +43 -2
- package/src/agent-tooling/integrations/langgraph.ts +7 -1
- package/src/agent-tooling/integrations/mastra.ts +7 -1
- package/src/agent-tooling/integrations/mock.ts +92 -17
- package/src/agent-tooling/integrations/ollama.ts +7 -1
- package/src/agent-tooling/integrations/openai.ts +7 -1
- package/src/agent-tooling/integrations/openrouter.ts +7 -1
- package/src/agent-tooling/integrations/pi.ts +56 -1
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
- package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
- package/src/agent-tooling/mcp/manifest.ts +100 -1
- package/src/agent-tooling/mcp/server.ts +63 -6
- package/src/agent-tooling/mcp/tools/construct.ts +130 -0
- package/src/agent-tooling/mcp/tools/debug.ts +126 -4
- package/src/agent-tooling/mcp/tools/reference.ts +542 -5
- package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
- package/src/agent-tooling/mcp/tools/theme.ts +146 -30
- package/src/agent-tooling/mcp/validate-args.ts +141 -0
- package/src/agent-tooling/recipes/composed-thread.ts +714 -0
- package/src/agent-tooling/recipes/index.ts +22 -0
- package/src/agent-tooling/recipes/types.ts +32 -0
- package/src/agent-tooling/registry.ts +24 -7
- package/src/agent-tooling/route-emit.ts +26 -2
- package/src/components/attachment-types.ts +54 -1
- package/src/components/attachments.tsx +169 -22
- package/src/components/audio-visualizer/fit-scale.ts +112 -0
- package/src/components/audio-visualizer/index.tsx +80 -3
- package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
- package/src/components/audio-visualizer/variant-bar.tsx +38 -6
- package/src/components/audio-visualizer/variant-custom.tsx +8 -2
- package/src/components/audio-visualizer/variant-grid.tsx +16 -11
- package/src/components/audio-visualizer/variant-radial.tsx +15 -10
- package/src/components/audio-visualizer/variant-wave.tsx +7 -2
- package/src/components/card-renderer.tsx +39 -8
- package/src/components/card.tsx +10 -2
- package/src/components/chat-container.tsx +4 -1
- package/src/components/chat-scope-picker.tsx +2 -2
- package/src/components/chat-thread.tsx +105 -13
- package/src/components/choice-card.tsx +102 -37
- package/src/components/coachmark.tsx +1 -1
- package/src/components/code-block.tsx +81 -5
- package/src/components/composer.tsx +89 -8
- package/src/components/confirm-card.tsx +20 -4
- package/src/components/conversation-item.tsx +138 -4
- package/src/components/conversation-list.tsx +230 -15
- package/src/components/embed.tsx +4 -0
- package/src/components/empty.tsx +14 -3
- package/src/components/file-tree.tsx +5 -1
- package/src/components/form-widgets.tsx +257 -195
- package/src/components/form.tsx +336 -21
- package/src/components/loader.tsx +12 -5
- package/src/components/message-skills.tsx +1 -1
- package/src/components/message.tsx +142 -12
- package/src/components/prompt-input.tsx +7 -1
- package/src/components/prompt-suggestion.tsx +4 -1
- package/src/components/reasoning.tsx +30 -3
- package/src/components/response-compare.tsx +2 -2
- package/src/components/response-stream.tsx +13 -7
- package/src/components/screen.tsx +5 -0
- package/src/components/scroll-button.tsx +63 -4
- package/src/components/source.tsx +6 -1
- package/src/components/tasks-card.tsx +58 -16
- package/src/components/thread.tsx +10 -1
- package/src/components/toast.tsx +11 -5
- package/src/components/tool-types.ts +9 -0
- package/src/components/voice-input.tsx +35 -3
- package/src/components/voice-output.tsx +46 -6
- package/src/components/workspace-shell.tsx +285 -0
- package/src/diagnostics/hook.ts +352 -0
- package/src/diagnostics/index.ts +82 -0
- package/src/diagnostics/report-request.ts +296 -0
- package/src/elements/attachments.tsx +9 -8
- package/src/elements/audio-visualizer.tsx +48 -4
- package/src/elements/chat-workspace.tsx +159 -287
- package/src/elements/chat.tsx +31 -10
- package/src/elements/checkbox-group.tsx +164 -0
- package/src/elements/checkbox.tsx +134 -0
- package/src/elements/code-block.tsx +19 -1
- package/src/elements/command.tsx +4 -1
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +12 -1
- package/src/elements/conversation-item.tsx +120 -0
- package/src/elements/conversation-list.tsx +60 -11
- package/src/elements/default-input.tsx +5 -5
- package/src/elements/define-entry.ts +12 -0
- package/src/elements/define.tsx +168 -8
- package/src/elements/diagnostic-events.ts +114 -0
- package/src/elements/dialog.tsx +47 -0
- package/src/elements/disclosure.ts +34 -12
- package/src/elements/dock.tsx +215 -0
- package/src/elements/dropdown.tsx +123 -0
- package/src/elements/element-data-types.ts +40 -0
- package/src/elements/element-diagnostics.ts +392 -0
- package/src/elements/element-manifest.json +36 -0
- package/src/elements/element-meta.json +1483 -560
- package/src/elements/element-nonscalar.json +185 -0
- package/src/elements/element-types.d.ts +589 -167
- package/src/elements/feedback-bar.tsx +5 -0
- package/src/elements/icon-names.json +29 -0
- package/src/elements/input.tsx +312 -23
- package/src/elements/menu.tsx +13 -0
- package/src/elements/message.tsx +2 -0
- package/src/elements/pane-grid.tsx +111 -0
- package/src/elements/prompt-dock.tsx +2 -1
- package/src/elements/prompt-input.tsx +16 -10
- package/src/elements/radio-group.tsx +129 -0
- package/src/elements/register-impl.ts +52 -0
- package/src/elements/register.ts +28 -0
- package/src/elements/resizable.tsx +52 -25
- package/src/elements/scroll-button.tsx +59 -6
- package/src/elements/select.tsx +165 -0
- package/src/elements/slider.tsx +171 -0
- package/src/elements/slots.ts +108 -13
- package/src/elements/styles.css +119 -9
- package/src/elements/thinking-bar.tsx +16 -7
- package/src/elements/thread.tsx +2 -0
- package/src/elements/toast.tsx +17 -1
- package/src/elements/tool.tsx +26 -5
- package/src/elements/voice-input.tsx +11 -2
- package/src/elements/voice-output.tsx +16 -3
- package/src/index.ts +4 -1
- package/src/primitives/card-data-types.ts +49 -0
- package/src/primitives/card-host.tsx +4 -2
- package/src/primitives/card-routing.ts +7 -56
- package/src/primitives/card-schemas/form.schema.json +21 -1
- package/src/primitives/card-validate.ts +10 -2
- package/src/primitives/chat-config.tsx +33 -6
- package/src/primitives/field-mask.ts +256 -0
- package/src/primitives/field-semantics.ts +115 -0
- package/src/primitives/input-mask.ts +853 -0
- package/src/primitives/toast-store.ts +66 -4
- package/src/primitives/url-scheme-policy.ts +70 -0
- package/src/primitives/use-resize-observer.ts +33 -0
- package/src/primitives/use-speech-recognition.ts +12 -1
- package/src/primitives/use-stick-to-bottom.ts +34 -2
- package/src/primitives/use-text-stream.ts +33 -2
- package/src/remote/provider-runtime.ts +6 -3
- package/src/schemas/index.ts +1 -0
- package/src/schemas/tool-defs.ts +307 -6
- package/src/solid.ts +15 -0
- package/src/state/index.ts +13 -1
- package/src/state/mock.ts +92 -6
- package/src/state/persistence.ts +180 -0
- package/src/state/stream.ts +71 -4
- package/src/state/threads.ts +142 -0
- package/src/types.ts +4 -2
- package/src/ui/agent-card.tsx +2 -2
- package/src/ui/avatar.tsx +1 -1
- package/src/ui/checkbox-group.tsx +153 -0
- package/src/ui/checkbox.tsx +63 -0
- package/src/ui/dialog.tsx +6 -0
- package/src/ui/dock.tsx +584 -0
- package/src/ui/dropdown.tsx +67 -23
- package/src/ui/hover-card.tsx +156 -6
- package/src/ui/icon.tsx +53 -0
- package/src/ui/input.tsx +275 -16
- package/src/ui/kbd.tsx +1 -1
- package/src/ui/nav.tsx +1 -1
- package/src/ui/pane-group.tsx +2 -2
- package/src/ui/radio.tsx +150 -0
- package/src/ui/resizable.tsx +11 -0
- package/src/ui/select.tsx +168 -0
- package/src/ui/slider.tsx +178 -0
- package/src/ui/switch.tsx +49 -18
- package/src/utils/cn.ts +11 -5
- package/src/wire/chunk.ts +47 -0
- package/src/wire/consume.ts +185 -26
- package/src/wire/diagnostics.ts +727 -0
- package/src/wire/encode-probe.ts +214 -0
- package/src/wire/encode.ts +267 -14
- package/src/wire/formats/anthropic.ts +8 -1
- package/src/wire/formats/openai.ts +5 -0
- package/src/wire/index.ts +22 -0
- package/src/wire/read.ts +250 -6
- package/src/wire/sse.ts +16 -3
- package/theme.css +84 -13
- package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
- package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
- package/dist/elements/chunks/artifact-BSuPYFHY.js +0 -1
- package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
- package/dist/elements/chunks/badge-TIMiJFKc.js +0 -1
- package/dist/elements/chunks/bash-InADTalH.js +0 -1
- package/dist/elements/chunks/card-renderer-CSoTL_e1.js +0 -1
- package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
- package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
- package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
- package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
- package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
- package/dist/elements/chunks/choice-card-CGMc3kek.js +0 -1
- package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
- package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
- package/dist/elements/chunks/circle-x-mhH7pOK2.js +0 -1
- package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
- package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
- package/dist/elements/chunks/composer-CZZmtYOT.js +0 -69
- package/dist/elements/chunks/confirm-card-BWjf2-xo.js +0 -1
- package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
- package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
- package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
- package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
- package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
- package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
- package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
- package/dist/elements/chunks/download-DnCyWFJE.js +0 -1
- package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
- package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
- package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
- package/dist/elements/chunks/file-text-D0J9F6M7.js +0 -1
- package/dist/elements/chunks/folder-NV1pi_ud.js +0 -1
- package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
- package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
- package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
- package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
- package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
- package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
- package/dist/elements/chunks/info-C8r5Q6cc.js +0 -1
- package/dist/elements/chunks/input-DrseEjhp.js +0 -1
- package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
- package/dist/elements/chunks/json-DxJze_jm.js +0 -1
- package/dist/elements/chunks/kbd-OGJDUT-O.js +0 -1
- package/dist/elements/chunks/link-BdsfLB7b.js +0 -1
- package/dist/elements/chunks/loader-B5QzK_8_.js +0 -1
- package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
- package/dist/elements/chunks/message-DtXKPqiR.js +0 -1
- package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
- package/dist/elements/chunks/paperclip-Bg0ITU3b.js +0 -1
- package/dist/elements/chunks/progress-bar-D1_rzt6N.js +0 -1
- package/dist/elements/chunks/prompt-suggestion-D5Sm8xF1.js +0 -1
- package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
- package/dist/elements/chunks/rotate-cw-DzVDJOA1.js +0 -1
- package/dist/elements/chunks/scroll-area-93A1bbeG.js +0 -1
- package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
- package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
- package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
- package/dist/elements/chunks/source-w9V0NnBn.js +0 -1
- package/dist/elements/chunks/star-DHvACxtm.js +0 -1
- package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
- package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
- package/dist/elements/chunks/tasks-card-lPxoodlA.js +0 -1
- package/dist/elements/chunks/text-shimmer-BY_rI3s5.js +0 -1
- package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
- package/dist/elements/chunks/toast-store-VUZZBhzH.js +0 -1
- package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
- package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
- package/dist/elements/chunks/use-card-resolution-DJg32jGH.js +0 -1
- package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
- package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
- package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
- package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
- package/dist/llms/llms-full.txt +0 -2834
- package/dist/llms/llms.txt +0 -156
- package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
- package/dist/register-impl-DGmGzrEM.js +0 -145
- package/dist/ui/stat.d.ts +0 -16
- package/dist/variant-custom-MkTNTycd.js +0 -1
- package/src/primitives/card-validate-generator.testlib.ts +0 -38
- package/src/ui/stat.tsx +0 -41
- /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
- /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
|
@@ -20,9 +20,64 @@ import type { OpenAIWireMessage } from '@kitn.ai/ui/wire';
|
|
|
20
20
|
const app = express();
|
|
21
21
|
app.use(express.json());
|
|
22
22
|
|
|
23
|
+
class ChatRequestError extends Error {
|
|
24
|
+
constructor(readonly status: number, message: string) { super(message); }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Narrow the JSON body once, at the edge. A bare GET or a missing messages
|
|
28
|
+
* array is a ChatRequestError with a status — NEVER an unhandled throw
|
|
29
|
+
* (findings F-10). Malformed JSON is rejected upstream by express.json(),
|
|
30
|
+
* which the error handler below turns into a JSON 400. */
|
|
31
|
+
function readChatRequest(req: express.Request): { messages: OpenAIWireMessage[] } {
|
|
32
|
+
if (req.method !== 'POST') {
|
|
33
|
+
throw new ChatRequestError(405, \`Method \${req.method} not allowed — POST /api/chat.\`);
|
|
34
|
+
}
|
|
35
|
+
const body = (req.body ?? {}) as { messages?: OpenAIWireMessage[] };
|
|
36
|
+
if (!Array.isArray(body.messages)) {
|
|
37
|
+
throw new ChatRequestError(400, 'Request body must carry a messages array.');
|
|
38
|
+
}
|
|
39
|
+
return body as { messages: OpenAIWireMessage[] };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Map a guard rejection to the response its status demands; rethrow anything
|
|
43
|
+
* else — an unexpected error should be loud, not laundered into a 400. */
|
|
44
|
+
function toChatErrorResponse(error: unknown, res: express.Response): void {
|
|
45
|
+
if (error instanceof ChatRequestError) {
|
|
46
|
+
res.status(error.status).json({ error: { message: error.message } });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// express.json() rejects a malformed body at the MIDDLEWARE level, before any
|
|
53
|
+
// handler runs — without this it surfaces as Express's default HTML error page.
|
|
54
|
+
app.use(
|
|
55
|
+
(
|
|
56
|
+
err: { status?: number; message?: string },
|
|
57
|
+
_req: express.Request,
|
|
58
|
+
res: express.Response,
|
|
59
|
+
_next: express.NextFunction,
|
|
60
|
+
) => {
|
|
61
|
+
res.status(err?.status ?? 500).json({ error: { message: err?.message ?? 'Request failed.' } });
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// A bare GET is a 405 with the method named, not Express's default 404 —
|
|
66
|
+
// the resource exists, the verb is wrong.
|
|
67
|
+
app.get('/api/chat', (_req, res) => {
|
|
68
|
+
res.status(405).json({ error: { message: 'Method not allowed — POST /api/chat.' } });
|
|
69
|
+
});
|
|
70
|
+
|
|
23
71
|
// POST /api/chat: bridge a Pi RPC session to the browser as SSE.
|
|
24
72
|
app.post('/api/chat', (req, res) => {
|
|
25
|
-
|
|
73
|
+
let chatBody: { messages: OpenAIWireMessage[] };
|
|
74
|
+
try {
|
|
75
|
+
chatBody = readChatRequest(req);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
toChatErrorResponse(error, res);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { messages } = chatBody;
|
|
26
81
|
const last = messages.at(-1)?.content;
|
|
27
82
|
// \`content\` is a plain string until the turn carries an attachment, at which
|
|
28
83
|
// point it is an ARRAY of content parts. Pi's RPC mode takes a TEXT prompt and
|
|
@@ -169,7 +169,13 @@ const FINISH_REASONS: Record<string, string> = {
|
|
|
169
169
|
};
|
|
170
170
|
|
|
171
171
|
async function chatHandler(request: Request): Promise<Response> {
|
|
172
|
-
|
|
172
|
+
let chatBody: ChatRequestBody;
|
|
173
|
+
try {
|
|
174
|
+
chatBody = await readChatRequest(request);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
return toChatErrorResponse(error);
|
|
177
|
+
}
|
|
178
|
+
const { messages, tools } = chatBody;
|
|
173
179
|
const toolSet = toToolSet(tools);
|
|
174
180
|
const prompt = toModelMessages(messages);
|
|
175
181
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// `*.css?raw` — Vite inlines the file's TEXT as a string at build time.
|
|
2
|
+
//
|
|
3
|
+
// tools/theme.ts uses it to read the real `--kai-*` token names out of
|
|
4
|
+
// theme.css instead of restating them. The declaration lives here rather than
|
|
5
|
+
// coming from `vite/client` because tsconfig.mcp.json deliberately runs with
|
|
6
|
+
// `types: ["node"]` and no DOM — this is a Node bundle that emits HTML as
|
|
7
|
+
// strings. One narrow module pattern is cheaper than pulling the whole browser
|
|
8
|
+
// client typing into that pass.
|
|
9
|
+
declare module '*.css?raw' {
|
|
10
|
+
const content: string;
|
|
11
|
+
export default content;
|
|
12
|
+
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `cardTagForType` for the rule and for what happens when an eighth card type lands.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
20
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
21
21
|
import { fileURLToPath } from 'node:url';
|
|
22
22
|
import { join, dirname, resolve } from 'node:path';
|
|
23
23
|
// The package's own public entry, by the same specifier the scaffolder tells a
|
|
@@ -236,6 +236,105 @@ export function listElements(): string[] {
|
|
|
236
236
|
.sort();
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
// ── Per-element entry map ─────────────────────────────────────────────────────
|
|
240
|
+
//
|
|
241
|
+
// A STATIC import, not an fs read off resolveManifestPath's dual-context pattern:
|
|
242
|
+
// element-manifest.json (unlike custom-elements.json) is never copied into dist/,
|
|
243
|
+
// so an fs read relative to this module's own URL would resolve in the vitest/source
|
|
244
|
+
// context and 404 in the bundled dist/mcp.es.js. A static import sidesteps the gap
|
|
245
|
+
// entirely — Rollup inlines the JSON at build time, so the bundled bin carries the
|
|
246
|
+
// data with no runtime file dependency. NAMED import (not the whole module), matching
|
|
247
|
+
// the same tradeoff element-diagnostics.ts already made for this file: a default
|
|
248
|
+
// import would pull `files` in too for 0 benefit here.
|
|
249
|
+
import { tags as ELEMENT_ENTRY_TAGS } from '../../elements/element-manifest.json';
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The per-element entry basename for a tag, e.g. 'kai-chat' -> 'chat'.
|
|
253
|
+
*
|
|
254
|
+
* Read from element-manifest.json's `tags` map rather than derived by stripping
|
|
255
|
+
* the `kai-` prefix: TEN of the eighty elements do not match that derivation
|
|
256
|
+
* (`kai-conversations` -> `conversation-list`), so a derived path would emit a
|
|
257
|
+
* broken import for them.
|
|
258
|
+
*/
|
|
259
|
+
export function entryForTag(tag: string): string | undefined {
|
|
260
|
+
return (ELEMENT_ENTRY_TAGS as Record<string, string>)[tag];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* The per-element entry basename for a tag the register-all bundle does NOT
|
|
265
|
+
* carry, e.g. 'kai-remote' -> 'remote'. `undefined` for every tag `entryForTag`
|
|
266
|
+
* already answers, and for a tag no built module registers.
|
|
267
|
+
*
|
|
268
|
+
* WHY THIS EXISTS. `entryForTag` reads element-manifest.json, which is generated
|
|
269
|
+
* from the import list in register-impl.ts — so an opt-in element is absent from
|
|
270
|
+
* it by construction, and the reference had nothing to name. It said "find the
|
|
271
|
+
* entry point in the package's published exports", which is the one place in the
|
|
272
|
+
* reference where "how to make this element exist" does not answer itself.
|
|
273
|
+
*
|
|
274
|
+
* WHY IT IS READ AND NOT DERIVED. Stripping `kai-` is wrong for ten of the eighty
|
|
275
|
+
* elements, so guessing here risks exactly the broken import this tool exists to
|
|
276
|
+
* catch. The fact is stated in vite.config.elements.ts, which adds an explicit
|
|
277
|
+
* entry for each opt-in element precisely "so `@kitn.ai/ui/elements/remote`
|
|
278
|
+
* resolves to a real dist file" — but a vite config is not shipped in the
|
|
279
|
+
* package, so the runtime reads that intent where it LANDS: dist/elements/. A
|
|
280
|
+
* candidate is a built module that element-manifest.json does not already claim
|
|
281
|
+
* (plus the two non-element entries the same build emits), and it is matched to a
|
|
282
|
+
* tag by the tag literal it registers. So the answer is the built artifact's,
|
|
283
|
+
* confirmed against the tag rather than assumed from a filename.
|
|
284
|
+
*
|
|
285
|
+
* dist/elements/ is a sibling of the manifest in both contexts — the bundled bin
|
|
286
|
+
* (dist/mcp.es.js) and vitest-over-source, which resolveManifestPath already
|
|
287
|
+
* normalises — so this needs no second resolution strategy. A missing or
|
|
288
|
+
* unreadable directory yields `undefined` rather than throwing: the caller's
|
|
289
|
+
* fallback is the honest "this is opt-in" paragraph it already prints.
|
|
290
|
+
*/
|
|
291
|
+
export function optInEntryForTag(tag: string): string | undefined {
|
|
292
|
+
if (entryForTag(tag)) return undefined;
|
|
293
|
+
return optInEntries().get(tag);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Not element entries: the register-all barrel and the DOM autoloader, both
|
|
297
|
+
* emitted into dist/elements/ by the same per-element build. */
|
|
298
|
+
const NON_ELEMENT_ENTRIES = new Set(['index', 'autoloader']);
|
|
299
|
+
|
|
300
|
+
let _optInEntries: Map<string, string> | undefined;
|
|
301
|
+
|
|
302
|
+
function optInEntries(): Map<string, string> {
|
|
303
|
+
if (_optInEntries) return _optInEntries;
|
|
304
|
+
_optInEntries = new Map();
|
|
305
|
+
|
|
306
|
+
const dir = join(dirname(resolveManifestPath()), 'elements');
|
|
307
|
+
let candidates: string[];
|
|
308
|
+
try {
|
|
309
|
+
const registered = new Set(Object.values(ELEMENT_ENTRY_TAGS as Record<string, string>));
|
|
310
|
+
candidates = readdirSync(dir)
|
|
311
|
+
.filter((f) => f.endsWith('.js'))
|
|
312
|
+
.map((f) => f.slice(0, -'.js'.length))
|
|
313
|
+
.filter((base) => !registered.has(base) && !NON_ELEMENT_ENTRIES.has(base));
|
|
314
|
+
} catch {
|
|
315
|
+
return _optInEntries;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Only the tags element-manifest.json does not already answer for. Narrow on
|
|
319
|
+
// purpose: an element module may mention a tag it merely renders, and matching
|
|
320
|
+
// against the whole tag list would let that be read as a registration.
|
|
321
|
+
const unclaimed = listElements().filter((t) => !entryForTag(t));
|
|
322
|
+
|
|
323
|
+
for (const base of candidates) {
|
|
324
|
+
let code: string;
|
|
325
|
+
try {
|
|
326
|
+
code = readFileSync(join(dir, `${base}.js`), 'utf-8');
|
|
327
|
+
} catch {
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
for (const tag of unclaimed) {
|
|
331
|
+
if (!_optInEntries.has(tag) && code.includes(`"${tag}"`)) _optInEntries.set(tag, base);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return _optInEntries;
|
|
336
|
+
}
|
|
337
|
+
|
|
239
338
|
// ── Which elements have anything to do with cards ────────────────────────────
|
|
240
339
|
//
|
|
241
340
|
// Two different populations, and conflating them would be the "attaches card
|
|
@@ -3,14 +3,65 @@ import {
|
|
|
3
3
|
CallToolRequestSchema,
|
|
4
4
|
ListToolsRequestSchema,
|
|
5
5
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
6
7
|
import { z } from 'zod';
|
|
7
8
|
import { reference } from './tools/reference';
|
|
8
9
|
import { scaffold } from './tools/scaffold';
|
|
9
10
|
import { theme } from './tools/theme';
|
|
10
11
|
import { debug } from './tools/debug';
|
|
12
|
+
import { constructTool } from './tools/construct';
|
|
11
13
|
import type { Tool } from './tools/types';
|
|
14
|
+
import { validateToolArgs } from './validate-args';
|
|
12
15
|
|
|
13
|
-
const tools: Tool[] = [reference, scaffold, theme, debug];
|
|
16
|
+
const tools: Tool[] = [reference, scaffold, theme, debug, constructTool];
|
|
17
|
+
|
|
18
|
+
const PACKAGE_NAME = '@kitn.ai/ui';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The `serverInfo` every MCP harness reads back on `initialize`. READ, NOT TYPED.
|
|
22
|
+
*
|
|
23
|
+
* This was a hand-typed `{ name: '@kitn.ai/ui', version: '0.15.0' }` and the kit kept
|
|
24
|
+
* releasing past it, so every harness that connected was told a version ten minors
|
|
25
|
+
* stale — the same "derive it, don't type it" failure as the CDN pins, minus their
|
|
26
|
+
* lint. Nothing here is allowed to restate the version: `server.test.ts` reads
|
|
27
|
+
* package.json off disk itself and compares.
|
|
28
|
+
*
|
|
29
|
+
* RESOLVED BY THE PACKAGE'S OWN NAME, not by path arithmetic. This module runs from
|
|
30
|
+
* two places — `<package>/src/agent-tooling/mcp/server.ts` under vitest, and inlined
|
|
31
|
+
* into `<package>/dist/mcp.es.js` for the bin — which sit at different depths, so a
|
|
32
|
+
* relative hop would need one rule per context (what manifest.ts has to do, because
|
|
33
|
+
* `dist/custom-elements.json` is a build artifact with no name to ask for). A
|
|
34
|
+
* self-reference has no depth to get wrong: Node resolves `@kitn.ai/ui/package.json`
|
|
35
|
+
* against the nearest package.json whose `name` matches, which is this package in
|
|
36
|
+
* both contexts and in an install. It also never escapes into a neighbouring
|
|
37
|
+
* checkout the way a parent-directory search can.
|
|
38
|
+
*
|
|
39
|
+
* WHY IT SURVIVES PUBLISHING. npm always ships package.json, `exports` carries
|
|
40
|
+
* `"./package.json": "./package.json"` (self-reference is restricted to the exports
|
|
41
|
+
* map, so that key is load-bearing — drop it and this throws, and the test goes red
|
|
42
|
+
* with it), and `bin/mcp.js` imports `../dist/mcp.es.js` by its own URL, so the
|
|
43
|
+
* resolver starts inside the installed package however it was launched (npx, global
|
|
44
|
+
* install, symlink). Not a JSON import: that inlines the version at BUILD time, which
|
|
45
|
+
* is a second copy that can disagree with the package.json shipped beside it, and it
|
|
46
|
+
* would need `resolveJsonModule` on the repo's browser tsc pass as well as this one.
|
|
47
|
+
*
|
|
48
|
+
* A broken resolve throws instead of falling back to a placeholder — `bin/mcp.js`
|
|
49
|
+
* turns that into a named fatal on stderr, which is the loud version. A wrong version
|
|
50
|
+
* silently announced to every harness is the quiet one.
|
|
51
|
+
*/
|
|
52
|
+
function packageIdentity(): { name: string; version: string } {
|
|
53
|
+
const specifier = `${PACKAGE_NAME}/package.json`;
|
|
54
|
+
const require = createRequire(import.meta.url);
|
|
55
|
+
const pkg = require(specifier) as { name?: string; version?: string };
|
|
56
|
+
if (pkg.name !== PACKAGE_NAME || typeof pkg.version !== 'string') {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`[${PACKAGE_NAME}] Refusing to report a serverInfo that is not this package's: ` +
|
|
59
|
+
`${specifier} resolved to ${require.resolve(specifier)}, whose name is ` +
|
|
60
|
+
`${JSON.stringify(pkg.name)} and version ${JSON.stringify(pkg.version)}.`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return { name: pkg.name, version: pkg.version };
|
|
64
|
+
}
|
|
14
65
|
|
|
15
66
|
/**
|
|
16
67
|
* The AI/UI MCP server. A stdio server (see ./stdio.ts) exposing the AI/UI tools
|
|
@@ -24,10 +75,7 @@ export interface AiUiServer extends Server {
|
|
|
24
75
|
}
|
|
25
76
|
|
|
26
77
|
export function createServer(): AiUiServer {
|
|
27
|
-
const server = new Server(
|
|
28
|
-
{ name: '@kitn.ai/ui', version: '0.15.0' },
|
|
29
|
-
{ capabilities: { tools: {} } },
|
|
30
|
-
) as AiUiServer;
|
|
78
|
+
const server = new Server(packageIdentity(), { capabilities: { tools: {} } }) as AiUiServer;
|
|
31
79
|
|
|
32
80
|
const byName = new Map(tools.map((t) => [t.name, t]));
|
|
33
81
|
|
|
@@ -50,7 +98,16 @@ export function createServer(): AiUiServer {
|
|
|
50
98
|
content: [{ type: 'text', text: `Unknown tool: ${request.params.name}` }],
|
|
51
99
|
};
|
|
52
100
|
}
|
|
53
|
-
|
|
101
|
+
const args = request.params.arguments ?? {};
|
|
102
|
+
// Enforce the schema each tool ADVERTISES (additionalProperties: false +
|
|
103
|
+
// required) — one path for all four tools. Without this, a wrong key was
|
|
104
|
+
// silently ignored and the handler answered a different question (see
|
|
105
|
+
// validate-args.ts for the observed failure).
|
|
106
|
+
const problem = validateToolArgs(tool.name, tool.inputSchema, args);
|
|
107
|
+
if (problem) {
|
|
108
|
+
return { isError: true, content: [{ type: 'text', text: problem }] };
|
|
109
|
+
}
|
|
110
|
+
return tool.handler(args);
|
|
54
111
|
});
|
|
55
112
|
|
|
56
113
|
server.__listToolsForTest = () => tools.map((t) => t.name);
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Tool } from './types';
|
|
3
|
+
import { validateConstruct, CONSTRUCT_SCHEMA_URL } from '../../construct/schema';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* construct — turn-by-turn authoring of a kitn construct (one JSON file → one
|
|
7
|
+
* web component). Stateless by design: the HARNESS owns the construct file;
|
|
8
|
+
* every call carries the full construct for THIS turn — that is what makes
|
|
9
|
+
* turn 40 safe, there is no server-side draft to corrupt.
|
|
10
|
+
*
|
|
11
|
+
* Two entry shapes: `intent` alone returns a STARTER construct plus the
|
|
12
|
+
* real-choice questions the intent leaves open (menu-honesty: never ask a
|
|
13
|
+
* question the intent already answers). `construct` (optionally with
|
|
14
|
+
* `intent`) validates — rejection is a NORMAL, non-error result, not a thrown
|
|
15
|
+
* error, because an invalid turn does not change the file: the previous good
|
|
16
|
+
* construct still stands.
|
|
17
|
+
*
|
|
18
|
+
* NOTE on the advertised schema: `Tool.inputSchema` is a plain `z.ZodObject`,
|
|
19
|
+
* and both `server.ts` (`z.toJSONSchema`) and `validate-args.ts`
|
|
20
|
+
* (`schema.shape`) need that exact shape — a `.superRefine` wrapper is a
|
|
21
|
+
* `ZodEffects`-like type with no `.shape`, so it can't be `tool.inputSchema`.
|
|
22
|
+
* The advertised schema therefore stays a plain `.strict()` object; the
|
|
23
|
+
* "at least one of intent/construct" rule is enforced here in the handler
|
|
24
|
+
* with the same message the skeleton's superRefine would have produced.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const inputSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
intent: z
|
|
30
|
+
.string()
|
|
31
|
+
.min(1)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('What the author wants, in their words. Alone: returns a starter construct.'),
|
|
34
|
+
construct: z
|
|
35
|
+
.record(z.string(), z.unknown())
|
|
36
|
+
.optional()
|
|
37
|
+
.describe('The FULL construct JSON for this turn. The harness owns the file; send all of it every turn.'),
|
|
38
|
+
})
|
|
39
|
+
.strict();
|
|
40
|
+
|
|
41
|
+
function starterFor(intent: string) {
|
|
42
|
+
// Derive what the intent already implies; ask only what it leaves open.
|
|
43
|
+
const impliesWidget = /widget|embed|bubble|corner|launcher/i.test(intent);
|
|
44
|
+
const name = 'my-chat'; // real-choice: always ask for the tag name (it is theirs)
|
|
45
|
+
return {
|
|
46
|
+
construct: {
|
|
47
|
+
$schema: CONSTRUCT_SCHEMA_URL,
|
|
48
|
+
name,
|
|
49
|
+
layout: 'widget',
|
|
50
|
+
provider: { mode: 'mock' },
|
|
51
|
+
},
|
|
52
|
+
stated: impliesWidget ? ['layout: widget (implied by your request)'] : [],
|
|
53
|
+
questions: [
|
|
54
|
+
`What should the element tag be? (kebab-case, e.g. "acme-support"; using "${name}" until you say)`,
|
|
55
|
+
...(impliesWidget ? [] : ['Layout: widget, fullscreen, aside, split, or custom?']),
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const constructTool: Tool = {
|
|
61
|
+
name: 'construct',
|
|
62
|
+
description:
|
|
63
|
+
'Author a kitn construct (one JSON file → one web component) turn by turn. ' +
|
|
64
|
+
'Send the full construct each turn; invalid turns come back REJECTED with per-path reasons and the previous good construct stands. ' +
|
|
65
|
+
`Schema: ${CONSTRUCT_SCHEMA_URL}. Preview with "kai dev <file>".`,
|
|
66
|
+
inputSchema,
|
|
67
|
+
handler: async (args) => {
|
|
68
|
+
const { intent, construct } = args as { intent?: string; construct?: Record<string, unknown> };
|
|
69
|
+
|
|
70
|
+
if (!intent && !construct) {
|
|
71
|
+
return {
|
|
72
|
+
isError: true,
|
|
73
|
+
content: [{ type: 'text', text: 'construct: pass intent, construct, or both' }],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!construct) {
|
|
78
|
+
const s = starterFor(intent ?? '');
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: 'text',
|
|
83
|
+
text: [
|
|
84
|
+
'STARTER construct (mock provider — keyless, previews immediately):',
|
|
85
|
+
'```json',
|
|
86
|
+
JSON.stringify(s.construct, null, 2),
|
|
87
|
+
'```',
|
|
88
|
+
...s.stated,
|
|
89
|
+
...s.questions,
|
|
90
|
+
].join('\n'),
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const out = validateConstruct(construct);
|
|
97
|
+
if (!out.ok) {
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: [
|
|
103
|
+
'REJECTED — this turn does not change the file; the previous good construct stands.',
|
|
104
|
+
...out.problems.map((p) => ` ${p.path || '(root)'}: ${p.message}`),
|
|
105
|
+
].join('\n'),
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const c = out.construct;
|
|
112
|
+
return {
|
|
113
|
+
content: [
|
|
114
|
+
{
|
|
115
|
+
type: 'text',
|
|
116
|
+
text: [
|
|
117
|
+
`VALID: <${c.name}> (${c.layout}, ${c.provider.mode}).`,
|
|
118
|
+
'```json',
|
|
119
|
+
JSON.stringify(c, null, 2),
|
|
120
|
+
'```',
|
|
121
|
+
`Preview: kai dev <file>. Compile: kai compile <file>.`,
|
|
122
|
+
...(c.provider.mode === 'endpoint'
|
|
123
|
+
? ['Backend route: use the scaffold tool — it emits a compiling route for your framework and wire.']
|
|
124
|
+
: []),
|
|
125
|
+
].join('\n'),
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
};
|
|
@@ -450,6 +450,123 @@ const RULES: Rule[] = [
|
|
|
450
450
|
'A malformed definition (not two candidates, missing/duplicate ids) fires `kai-error` ' +
|
|
451
451
|
'instead. The event is non-bubbling — listen on the element, not on `document`.',
|
|
452
452
|
},
|
|
453
|
+
{
|
|
454
|
+
// Rule 13 — kai-composer is the bare editor; attachments + send live on kai-prompt-input
|
|
455
|
+
// Source: src/elements/composer.tsx (element doc), src/elements/prompt-input.tsx,
|
|
456
|
+
// apps/docs components/composer.mdx (the taxonomy sentence). Rung-6 F-43.
|
|
457
|
+
id: 'composer-attachments',
|
|
458
|
+
test: (t) => {
|
|
459
|
+
// Attachment / send-button / toolbar questions asked ABOUT the composer.
|
|
460
|
+
if (!/kai-composer|composer\b/i.test(t)) return false;
|
|
461
|
+
return /attach|paperclip|file.?upload|upload|send.?button|toolbar|staging|staged/i.test(t);
|
|
462
|
+
},
|
|
463
|
+
title: '`<kai-composer>` is the bare editor — attachments and the send button live on `<kai-prompt-input>`',
|
|
464
|
+
cause:
|
|
465
|
+
'`<kai-composer>` is deliberately the bare editing surface: rich text, entity pills, ' +
|
|
466
|
+
'triggers, Enter-to-submit — and nothing else. No send button, no toolbar, no attachment ' +
|
|
467
|
+
'surface; its `kai-submit` detail is `{ doc, text, entities }` with no `attachments` field. ' +
|
|
468
|
+
'Nothing is missing — the batteries-included wrapper is a different element.',
|
|
469
|
+
fix:
|
|
470
|
+
'Reach for `<kai-prompt-input>`, which is built on the composer and adds the send button, ' +
|
|
471
|
+
'the toolbar, and attachments: a paperclip that stages files as chips, a ' +
|
|
472
|
+
'`kai-attachments-change` event, and `attachments` on its `kai-submit` detail.\n\n' +
|
|
473
|
+
'```html\n' +
|
|
474
|
+
'<kai-prompt-input placeholder="Send a message..."></kai-prompt-input>\n' +
|
|
475
|
+
'```\n\n' +
|
|
476
|
+
'```js\n' +
|
|
477
|
+
"document.querySelector('kai-prompt-input').addEventListener('kai-submit', (e) => {\n" +
|
|
478
|
+
' const { value, attachments } = e.detail; // attachments staged via the paperclip\n' +
|
|
479
|
+
'});\n' +
|
|
480
|
+
'```\n\n' +
|
|
481
|
+
'Keep `<kai-composer>` only when you are composing the input row yourself — then the ' +
|
|
482
|
+
'picker, staging tray and send control are yours to build, and every staged file’s ' +
|
|
483
|
+
'`url` must be a `data:` URI, never `URL.createObjectURL` (see the attachment-blob-url rule).',
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
// Rule 14 — blob: attachment URLs: the wire refuses them; use a data: URI
|
|
487
|
+
// Source: src/components/attachment-types.ts (AttachmentData.url doc),
|
|
488
|
+
// src/elements/default-input.tsx (readAsDataUrl), src/wire/files.ts (the refusal),
|
|
489
|
+
// apps/docs patterns/attachments-flow.mdx. Rung-6 F-44; the defect PR #186 shipped.
|
|
490
|
+
id: 'attachment-blob-url',
|
|
491
|
+
test: (t) => {
|
|
492
|
+
// The literal defect in a snippet, with attachment/file-staging context.
|
|
493
|
+
if (/createObjectURL/.test(t) && /attachment|type:\s*'file'|filename|kai|@kitn/i.test(t)) return true;
|
|
494
|
+
// A wire refusal or preview-works-send-fails symptom naming blob: URLs.
|
|
495
|
+
if (/blob:/.test(t) && /attachment|toOpenAIMessages|toAnthropicMessages|wire|kai|@kitn/i.test(t)) return true;
|
|
496
|
+
return false;
|
|
497
|
+
},
|
|
498
|
+
title: 'Never `URL.createObjectURL` in `AttachmentData.url` — read the file as a `data:` URI',
|
|
499
|
+
cause:
|
|
500
|
+
'An object URL resolves only inside the browser tab that minted it, so `url: ' +
|
|
501
|
+
'URL.createObjectURL(file)` renders a flawless local preview and is meaningless to any ' +
|
|
502
|
+
'provider. `toOpenAIMessages` / `toAnthropicMessages` REFUSE a `blob:` URL rather than ' +
|
|
503
|
+
'send an address the model cannot fetch — before they refused it, an attachment-only ' +
|
|
504
|
+
'turn reached the model as nothing at all. A mock-only app hides the defect ' +
|
|
505
|
+
'(`createMockResponder` never encodes the thread back); it surfaces the moment you point ' +
|
|
506
|
+
'at a real provider.',
|
|
507
|
+
fix:
|
|
508
|
+
'Read every staged file as a `data:` URI and put THAT in `url` — it previews identically ' +
|
|
509
|
+
'and is the one form both provider wires actually take:\n\n' +
|
|
510
|
+
'```js\n' +
|
|
511
|
+
'const readAsDataUrl = (file) =>\n' +
|
|
512
|
+
' new Promise((resolve, reject) => {\n' +
|
|
513
|
+
' const reader = new FileReader();\n' +
|
|
514
|
+
' reader.onload = () => resolve(String(reader.result));\n' +
|
|
515
|
+
' reader.onerror = () => reject(reader.error);\n' +
|
|
516
|
+
' reader.readAsDataURL(file);\n' +
|
|
517
|
+
' });\n\n' +
|
|
518
|
+
"const url = await readAsDataUrl(file); // data: URI — never URL.createObjectURL\n" +
|
|
519
|
+
"return { id, type: 'file', filename: file.name, mediaType: file.type, url };\n" +
|
|
520
|
+
'```\n\n' +
|
|
521
|
+
'`<kai-prompt-input>`’s built-in paperclip already does this for you; the conversion ' +
|
|
522
|
+
'is only yours when you stage files yourself. With `data:` URIs there is also nothing ' +
|
|
523
|
+
'to revoke — no object-URL lifecycle to manage.',
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
// Rule 15 — mock tool calls: MockTurn.toolCalls scripts them; the HOST resolves them
|
|
527
|
+
// Source: src/state/mock.ts (MockTurn/MockToolCall), src/wire/chunk.ts (ModelTurn.toolCalls),
|
|
528
|
+
// src/state/stream.ts (upsertTool). Rung-6 F-46/F-47/F-52.
|
|
529
|
+
id: 'mock-tool-calls',
|
|
530
|
+
test: (t) => {
|
|
531
|
+
const toolContext = /tool.?call|toolCalls|input-available/i.test(t);
|
|
532
|
+
// The mock responder asked about tool calls…
|
|
533
|
+
if (/createMockResponder|mock responder|MockTurn/i.test(t) && toolContext) return true;
|
|
534
|
+
// …or a tool part parked in input-available with kai/mock context.
|
|
535
|
+
if (toolContext && /\bmock\b/i.test(t) && /kai|@kitn|stream|responder/i.test(t)) return true;
|
|
536
|
+
return false;
|
|
537
|
+
},
|
|
538
|
+
title: 'Scripting mock tool calls — `MockTurn.toolCalls`; the HOST resolves the announced call',
|
|
539
|
+
cause:
|
|
540
|
+
'Two separate facts. (1) The default mock replies are text-only, so out of the box ' +
|
|
541
|
+
'`createMockResponder()` never announces a tool call — scripting one takes a `MockTurn` ' +
|
|
542
|
+
'reply. (2) A tool call — mock or real provider — is only ever ANNOUNCED by the stream: ' +
|
|
543
|
+
'the part parks at `state: \'input-available\'` and stays there. The kit parses and ' +
|
|
544
|
+
'renders the call; EXECUTING it and answering is the host’s job.',
|
|
545
|
+
fix:
|
|
546
|
+
'Script the call with a `MockTurn` reply (`{ text?, toolCalls? }`); the mock frames it ' +
|
|
547
|
+
'announce-then-arguments with `finish_reason: \'tool_calls\'`, exactly as a real ' +
|
|
548
|
+
'OpenAI-wire turn, so it flows through `readOpenAIStream` unchanged:\n\n' +
|
|
549
|
+
'```js\n' +
|
|
550
|
+
"import { createMockResponder } from '@kitn.ai/ui/state';\n\n" +
|
|
551
|
+
'const mock = createMockResponder({\n' +
|
|
552
|
+
' replies: [\n' +
|
|
553
|
+
" 'Plain text turn.',\n" +
|
|
554
|
+
" { text: 'Checking…', toolCalls: [{ name: 'get_weather', arguments: { city: 'Oslo' } }] },\n" +
|
|
555
|
+
' ],\n' +
|
|
556
|
+
'});\n' +
|
|
557
|
+
'```\n\n' +
|
|
558
|
+
'Then resolve each announced call yourself after the read settles — walk the returned ' +
|
|
559
|
+
'`ModelTurn.toolCalls` and patch the part to `output-available`:\n\n' +
|
|
560
|
+
'```js\n' +
|
|
561
|
+
'const result = await readOpenAIStream(response, stream);\n' +
|
|
562
|
+
'for (const call of result.toolCalls) {\n' +
|
|
563
|
+
' const output = await runTool(call.name, call.input); // your side of the seam\n' +
|
|
564
|
+
" stream.upsertTool(call.id, { state: 'output-available', output });\n" +
|
|
565
|
+
'}\n' +
|
|
566
|
+
'```\n\n' +
|
|
567
|
+
'Skip any call with `providerExecuted: true` — the provider already ran it and its ' +
|
|
568
|
+
'result arrived in-stream.',
|
|
569
|
+
},
|
|
453
570
|
];
|
|
454
571
|
|
|
455
572
|
function buildText(matched: Rule[]): string {
|
|
@@ -458,10 +575,15 @@ function buildText(matched: Rule[]): string {
|
|
|
458
575
|
'No known failure pattern matched. Suggested next steps:\n\n' +
|
|
459
576
|
'1. Use the `component_reference` tool to look up the real API for the element ' +
|
|
460
577
|
'(prop names, event names, attribute vs. property distinction).\n' +
|
|
461
|
-
'2.
|
|
462
|
-
'
|
|
463
|
-
'for
|
|
464
|
-
'
|
|
578
|
+
'2. If the problem is in host code rather than an element — streaming, ' +
|
|
579
|
+
'`createAssistantStream`, `createMockResponder`, the SSE readers, the encoders — ' +
|
|
580
|
+
'call `component_reference` with `{ name: "programmatic" }` for the full ' +
|
|
581
|
+
'`@kitn.ai/ui/state` + `@kitn.ai/ui/wire` API, and `{ name: "composed-thread" }` ' +
|
|
582
|
+
'for a complete hand-composed surface to compare wiring against.\n' +
|
|
583
|
+
'3. Check the **Streaming recipe** and the **Programmatic layer** sections in ' +
|
|
584
|
+
'`llms-full.txt` (`node_modules/@kitn.ai/ui/llms-full.txt` or ' +
|
|
585
|
+
'https://ui.kitn.ai/llms-full.txt) for correct streaming wiring.\n' +
|
|
586
|
+
'4. Paste `https://ui.kitn.ai/llms.txt` into your prompt for a compact orientation.'
|
|
465
587
|
);
|
|
466
588
|
}
|
|
467
589
|
|