@kitn.ai/ui 0.27.0 → 0.29.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 +10 -2
- package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
- package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.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-CjRU3JgV.js +1 -0
- package/dist/arrow-left-Bnpb1UEW.js +1 -0
- package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
- package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
- package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
- package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
- package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
- package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
- package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
- package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
- package/dist/check-njkVdZu2.js +1 -0
- package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
- package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
- package/dist/chevron-down-B72s6PXR.js +1 -0
- package/dist/chevron-right-BatuHzUm.js +1 -0
- package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
- package/dist/circle-check-B62pODB3.js +1 -0
- package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
- package/dist/circle-zx0ByzY9.js +1 -0
- package/dist/code-block-ClMLKb7C.js +1 -0
- package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
- package/dist/components/chat-thread.d.ts +89 -1
- package/dist/components/conversation-item.d.ts +16 -0
- package/dist/components/conversation-panel.d.ts +29 -0
- package/dist/components/home-panel.d.ts +34 -0
- package/dist/components/widget-tab-bar.d.ts +16 -0
- package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
- package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
- package/dist/construct-cli.es.js +185 -17
- package/dist/construct.d.ts +5 -0
- package/dist/construct.js +327 -0
- package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
- package/dist/controllable-CnGpMF6r.js +1 -0
- package/dist/conversation-item-BxwQLaFJ.js +1 -0
- package/dist/conversation-list-BCfGN1JU.js +1 -0
- package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
- package/dist/core-C8fzo39E.js +1 -12
- package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
- package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
- package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
- package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
- package/dist/custom-elements.json +51 -2
- package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
- package/dist/define-By-uL588.js +1 -0
- package/dist/define.js +2 -2
- package/dist/define.server.js +2 -2
- package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
- package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.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 +3 -3
- 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/elements.d.ts +20 -4
- package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
- package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
- package/dist/engine-javascript-C1x7zo1_.js +1 -141
- package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
- package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
- package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
- package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
- package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
- package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
- package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2842 -2703
- package/dist/index.server.js +2820 -2681
- package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
- package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
- package/dist/kai.es.js +1 -1
- package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
- package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
- package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
- package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
- package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
- package/dist/mcp.es.js +79 -5
- package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
- package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
- package/dist/message-circle-DruwObfX.js +1 -0
- package/dist/message-square-BG6q6mlm.js +1 -0
- package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
- package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
- package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
- package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
- package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
- package/dist/play-BvKKq3fX.js +1 -0
- package/dist/primitives/conversation-store.d.ts +54 -0
- package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
- package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
- package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
- package/dist/react/index.d.ts +393 -0
- package/dist/react.js +20 -20
- package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
- package/dist/register-impl-B1hLkrI8.js +424 -0
- package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
- package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
- package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
- package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
- package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
- package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
- package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
- package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
- package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
- package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
- package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
- package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
- package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
- package/dist/solid.d.ts +6 -2
- package/dist/solid.js +217 -210
- package/dist/solid.server.js +217 -210
- package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
- package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
- package/dist/store-Ciyk6eZG.js +1 -0
- package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
- package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
- package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
- package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
- package/dist/theme.tokens.css +28 -0
- package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
- package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
- package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
- package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
- package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
- package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
- package/dist/types.d.ts +48 -3
- package/dist/ui/dock.d.ts +29 -0
- package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
- package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
- package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
- package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
- package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
- package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
- package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
- package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
- package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
- package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
- package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
- package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
- package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
- package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
- package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
- package/dist/x-Z5UntkIJ.js +1 -0
- package/frameworks/react/index.tsx +14 -4
- package/llms-full.txt +7 -2
- package/package.json +16 -16
- package/src/elements/element-meta.json +49 -6
- package/theme.css +28 -0
- package/bin/route.test.js +0 -58
- package/dist/arrow-down-Br0qtpsz.js +0 -1
- package/dist/arrow-left-Dj7xgE12.js +0 -1
- package/dist/check-DPeeMUYx.js +0 -1
- package/dist/chevron-down-CHSWk7ZT.js +0 -1
- package/dist/chevron-right-B7l_fMgx.js +0 -1
- package/dist/circle-Bb0yOpqM.js +0 -1
- package/dist/circle-check-BGZpCiz7.js +0 -1
- package/dist/code-block-CUQ5mtv0.js +0 -1
- package/dist/controllable-D43BKmtX.js +0 -1
- package/dist/conversation-list-D4lLU_yS.js +0 -1
- package/dist/define-CGGX-7Vg.js +0 -1
- package/dist/message-circle-Xf8Q-vZp.js +0 -1
- package/dist/message-square-Cxnwgkns.js +0 -1
- package/dist/play-OFIvYXUQ.js +0 -1
- package/dist/register-impl-C7rENvPK.js +0 -424
- package/dist/store-7eoadydQ.js +0 -1
- package/dist/x-C5m1JFgi.js +0 -1
- 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 -131
- package/src/agent-tooling/construct/codegen.ts +0 -1353
- package/src/agent-tooling/construct/construct.v1.schema.json +0 -250
- 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 -23
- package/src/agent-tooling/construct/schema.ts +0 -371
- 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 -518
- 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 -218
- package/src/components/conversation-list.tsx +0 -429
- 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/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/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 -212
- 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 -185
- package/src/elements/element-types.d.ts +0 -4337
- 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/styles.css +0 -328
- 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 -428
- 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/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 -165
- 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 -53
- 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 -584
- 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
package/src/state/stream.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// src/state/stream.ts
|
|
2
|
-
import type { ChatMessage, MessagePart, Source } from '../elements/chat-types';
|
|
3
|
-
import type { ToolPart } from '../components/tool-types';
|
|
4
|
-
import type { CardEnvelope } from '../primitives/card-contract';
|
|
5
|
-
import type { AttachmentData } from '../components/attachment-types';
|
|
6
|
-
import { appendReasoningPart, appendTextPart, upsertCardPart, upsertToolPart, type ReasoningOpts } from './parts';
|
|
7
|
-
|
|
8
|
-
/** The one universal contract: a functional-updater setter (React setState shape). */
|
|
9
|
-
export type SetMessages = (updater: (prev: ChatMessage[]) => ChatMessage[]) => void;
|
|
10
|
-
|
|
11
|
-
/* --------------------------------------------------------------------------
|
|
12
|
-
* Bag exclusivity: why the mutators below do not just take their payload type.
|
|
13
|
-
*
|
|
14
|
-
* `Source`, `Partial<ToolPart>` and `ReasoningOpts` are WEAK types — not one
|
|
15
|
-
* required field between them — and TypeScript only excess-property-checks
|
|
16
|
-
* OBJECT LITERALS. Hand a mutator a VARIABLE and that check never runs, so any
|
|
17
|
-
* bag sharing a single optional key name flows straight in. `addSource(source:
|
|
18
|
-
* Source)` therefore accepted an `AttachmentData` and a `CardEnvelope`, and
|
|
19
|
-
* `addFile(a) { inner.addSource(a); }` compiled clean at exit 0 while writing a
|
|
20
|
-
* file payload into a `source` part. Nine such pairs existed across these three
|
|
21
|
-
* bags and not one of them was a type error; `./stream-types.test.ts` pins all
|
|
22
|
-
* nine, and fails with nine "Unused '@ts-expect-error'" if this guard is lifted.
|
|
23
|
-
*
|
|
24
|
-
* Tightening the PAYLOAD types is not available. A citation with no url and no
|
|
25
|
-
* title is a rendered, tested state (`citationTitle` in components/message.tsx
|
|
26
|
-
* falls through title -> url -> a generic word, and message.stories.tsx ships
|
|
27
|
-
* "a citation with no url at all"), and a patch/opts bag is optional by
|
|
28
|
-
* definition. So the exclusivity lives on the PARAMETER instead, which leaves
|
|
29
|
-
* every published data type — and every artifact generated from them — alone.
|
|
30
|
-
*
|
|
31
|
-
* The forbidden key set is DERIVED from the `MessagePart` union, the same
|
|
32
|
-
* derivation `verify:scaffold` and `lint:silent-drops` read, so a seventh
|
|
33
|
-
* variant re-fires this on its own rather than quietly widening the hole.
|
|
34
|
-
*
|
|
35
|
-
* THE BOUNDARY — three things this deliberately does NOT cover. Each is a
|
|
36
|
-
* decision with a reason, not an unfinished edge; they are collected here so
|
|
37
|
-
* the whole boundary reads in one place instead of being met one at a time.
|
|
38
|
-
*
|
|
39
|
-
* 1. A KEY NO SIBLING BAG OWNS still passes. `Unmixed` is a denylist over the
|
|
40
|
-
* sibling vocabulary, not an exact type, so a consumer's own superset of a
|
|
41
|
-
* citation — `{ url, title, relevance }` — keeps compiling. Full exactness
|
|
42
|
-
* would catch marginally more and push real callers toward a cast, and a
|
|
43
|
-
* cast to `Source` from an attachment is the original bug. A guard people
|
|
44
|
-
* route around is worse than a narrower guard they keep.
|
|
45
|
-
*
|
|
46
|
-
* 2. `addCard` / `addFile` ARE NOT WRAPPED. Both take STRONG types —
|
|
47
|
-
* `CardEnvelope` requires type+id+data, `AttachmentData` requires id+type —
|
|
48
|
-
* so ordinary assignability already does what `Unmixed` exists to do for a
|
|
49
|
-
* weak bag. Measured, not assumed: wrapping `addCard` buys ZERO (no sibling
|
|
50
|
-
* bag is assignable to `CardEnvelope`, because nothing else carries `data`).
|
|
51
|
-
* Wrapping `addFile` buys exactly one pair — `addFile(c)` with
|
|
52
|
-
* `c: CardEnvelope<'file', unknown>` — and costs two ordinary consumer
|
|
53
|
-
* shapes, since the derived denylist owns `state` and `index`:
|
|
54
|
-
*
|
|
55
|
-
* { id, type: 'file', filename, state: 'uploading' } // upload progress
|
|
56
|
-
* { id, type: 'file', filename, index: 3 } // display position
|
|
57
|
-
*
|
|
58
|
-
* That one pair needs a hand-written generic narrowing with no other
|
|
59
|
-
* purpose; an ordinarily-inferred `CardEnvelope` is ALREADY rejected.
|
|
60
|
-
* Rejecting likely code to block contrived code is the wrong trade — the
|
|
61
|
-
* same trade point 1 refused. Both facts this rests on are pinned in
|
|
62
|
-
* ./stream-types.test.ts, so it re-opens if either stops holding.
|
|
63
|
-
*
|
|
64
|
-
* 3. A HAND-BUILT PART BYPASSES ALL OF IT. `parts.push({ type: 'source',
|
|
65
|
-
* source: attachmentVariable })` compiles, because these mutators are not
|
|
66
|
-
* in the path. Closing it means intersecting the guard into `MessagePart`
|
|
67
|
-
* itself — and `docs/web-components.md` and `llms-full.txt` inline that
|
|
68
|
-
* union's fully-expanded structural text, so dozens of consumer-facing
|
|
69
|
-
* prop-table rows would grow `type?: undefined; state?: undefined;
|
|
70
|
-
* data?: undefined`. That cost lands on every consumer reading the docs
|
|
71
|
-
* while the benefit reaches only someone who has already stepped around
|
|
72
|
-
* the provided API. The mutators are the supported path; they are guarded.
|
|
73
|
-
* This is where the supported path ends, not a gap in it.
|
|
74
|
-
* ------------------------------------------------------------------------ */
|
|
75
|
-
|
|
76
|
-
/** Every OBJECT payload a `MessagePart` variant carries. `type`/`raw` are the
|
|
77
|
-
* variant's own bookkeeping, not payload; the primitive payloads (`text`,
|
|
78
|
-
* `label`, `index`, ...) drop out at `Extract<..., object>`. */
|
|
79
|
-
type PartPayload = Extract<
|
|
80
|
-
MessagePart extends infer P ? (P extends object ? P[Exclude<keyof P, 'type' | 'raw'>] : never) : never,
|
|
81
|
-
object
|
|
82
|
-
>;
|
|
83
|
-
|
|
84
|
-
/** Every bag one of these mutators takes: the part payloads plus the options
|
|
85
|
-
* bags that are not payloads themselves. */
|
|
86
|
-
type MutatorBag = PartPayload | ReasoningOpts;
|
|
87
|
-
|
|
88
|
-
/** `keyof` over a union member-by-member. The bare `keyof (A | B)` is the
|
|
89
|
-
* INTERSECTION of their keys, which is the opposite of what this needs. */
|
|
90
|
-
type KeysOf<T> = T extends unknown ? keyof T : never;
|
|
91
|
-
|
|
92
|
-
/** `Shape`, but any key that belongs exclusively to a SIBLING bag is a compile
|
|
93
|
-
* error. Keys `Shape` never heard of are untouched, so a consumer's own
|
|
94
|
-
* superset of a citation still passes — only the mix-ups fail. That is a
|
|
95
|
-
* denylist, not an exact type, and deliberately so: boundary point 1. */
|
|
96
|
-
type Unmixed<Shape> = Shape & { [K in Exclude<KeysOf<MutatorBag>, keyof Shape>]?: never };
|
|
97
|
-
|
|
98
|
-
function newId(): string {
|
|
99
|
-
if (typeof crypto !== 'undefined' && crypto.randomUUID) return crypto.randomUUID();
|
|
100
|
-
return 'kai-' + Math.random().toString(36).slice(2);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** A fluent builder for one in-flight assistant message. Owns no state. */
|
|
104
|
-
export interface AssistantStream {
|
|
105
|
-
readonly id: string;
|
|
106
|
-
appendText(delta: string): AssistantStream;
|
|
107
|
-
appendReasoning(delta: string, opts?: Unmixed<ReasoningOpts>): AssistantStream;
|
|
108
|
-
upsertTool(toolCallId: string, patch: Unmixed<Partial<ToolPart>>): AssistantStream;
|
|
109
|
-
/** Adds a card, or REPLACES the existing one with the same `envelope.id`. A
|
|
110
|
-
* model that revises a card mid-turn re-sends the whole envelope, so a second
|
|
111
|
-
* call with a known id revises that card in place rather than rendering a
|
|
112
|
-
* second copy of it. See `upsertCardPart`. */
|
|
113
|
-
addCard(envelope: CardEnvelope): AssistantStream;
|
|
114
|
-
addSource(source: Unmixed<Source>): AssistantStream;
|
|
115
|
-
/* Unwrapped on purpose — these two take STRONG types, so ordinary
|
|
116
|
-
* assignability already holds. Measurements and the trade: boundary point 2. */
|
|
117
|
-
addFile(attachment: AttachmentData): AssistantStream;
|
|
118
|
-
done(): void;
|
|
119
|
-
/** Settles the turn as FAILED and puts `reason` where the reader can find it.
|
|
120
|
-
*
|
|
121
|
-
* WHERE THE REASON LANDS, in order:
|
|
122
|
-
* 1. every tool part that has NOT produced a result flips to `output-error`
|
|
123
|
-
* with `errorText: reason`, so no panel spins forever. A tool ALREADY in
|
|
124
|
-
* `output-error` with its own non-empty `errorText` is left exactly as it
|
|
125
|
-
* is: "search index offline" is the answer to what went wrong and
|
|
126
|
-
* "Connection lost." is the generic outer symptom, so overwriting the
|
|
127
|
-
* specific with the generic loses the only actionable thing on the
|
|
128
|
-
* message. It still counts as carrying the failure. A tool in
|
|
129
|
-
* `output-error` with NO text does get filled in — an error panel with
|
|
130
|
-
* nothing in it says no more than a blank bubble does.
|
|
131
|
-
* 2. if no part was able to carry it, the reason is APPENDED as its own text
|
|
132
|
-
* part.
|
|
133
|
-
*
|
|
134
|
-
* Never both — a turn does not report the same failure twice.
|
|
135
|
-
*
|
|
136
|
-
* "Where the reader can FIND it" is deliberate, and rule 1 and rule 2 are not
|
|
137
|
-
* equally loud. Rule 2 is text in the thread: read without any interaction.
|
|
138
|
-
* Rule 1 is a tool panel, which renders COLLAPSED — the header shows an error
|
|
139
|
-
* icon and a badge, so the failure is unmissable, but the `errorText` itself
|
|
140
|
-
* is one click away. That is the right default for a failed tool inside an
|
|
141
|
-
* otherwise readable answer, and it is why rule 2 exists rather than always
|
|
142
|
-
* stamping the panel and calling it reported.
|
|
143
|
-
*
|
|
144
|
-
* Rule 2 is the whole point and it used to be missing. `abort` only ever did
|
|
145
|
-
* rule 1, so a TEXT-ONLY turn — every turn of a text-only support widget —
|
|
146
|
-
* had nothing to stamp: the string was discarded and a failed request
|
|
147
|
-
* rendered an EMPTY assistant bubble, while the consumer that passed a
|
|
148
|
-
* perfectly good sentence believed it had reported the failure. That is the
|
|
149
|
-
* repo's "decide loudly" rule broken on the one path where being quiet is
|
|
150
|
-
* worst, and it shipped because the discard is invisible from the call site.
|
|
151
|
-
*
|
|
152
|
-
* It is a NEW part, never a merge onto the trailing text: gluing "Connection
|
|
153
|
-
* lost." onto the model's half-finished sentence reads as the model saying
|
|
154
|
-
* it. Text that already streamed stays exactly where it is.
|
|
155
|
-
*
|
|
156
|
-
* The reason is TRIMMED, and `abort()` with no reason — or one that is empty
|
|
157
|
-
* or all whitespace — appends nothing: there is no reason to discard, and the
|
|
158
|
-
* kit will not invent copy the consumer did not write. Rule 1 still runs,
|
|
159
|
-
* with `errorText: undefined`. Whitespace is not a pedantic case here: the
|
|
160
|
-
* scaffold hands over `err.message`, and an `Error` is free to carry `''`,
|
|
161
|
-
* which would otherwise render an INVISIBLE text part — a blank bubble that
|
|
162
|
-
* also claims to have said something.
|
|
163
|
-
*
|
|
164
|
-
* Settled is settled: after `done()` or a first `abort()`, this is a no-op
|
|
165
|
-
* like every other mutator, so the reason cannot be appended twice.
|
|
166
|
-
*
|
|
167
|
-
* The reason is CONSUMER-facing text and is rendered as markdown like any
|
|
168
|
-
* other text part. Pass a sentence a visitor can read, not a stack trace. */
|
|
169
|
-
abort(reason?: string): void;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Start an assistant message and drive it through `set`. New refs on every mutation. */
|
|
173
|
-
export function createAssistantStream(
|
|
174
|
-
set: SetMessages,
|
|
175
|
-
init: Partial<ChatMessage> = {},
|
|
176
|
-
): AssistantStream {
|
|
177
|
-
const id = init.id ?? newId();
|
|
178
|
-
let settled = false;
|
|
179
|
-
|
|
180
|
-
set((prev) => [...prev, { id, role: 'assistant', parts: [], ...init }]);
|
|
181
|
-
|
|
182
|
-
const mutate = (fn: (parts: MessagePart[]) => MessagePart[]) => {
|
|
183
|
-
if (settled) return;
|
|
184
|
-
set((prev) => {
|
|
185
|
-
const i = prev.findIndex((m) => m.id === id);
|
|
186
|
-
if (i < 0) return prev;
|
|
187
|
-
const next = fn(prev[i].parts);
|
|
188
|
-
if (next === prev[i].parts) return prev;
|
|
189
|
-
return [...prev.slice(0, i), { ...prev[i], parts: next }, ...prev.slice(i + 1)];
|
|
190
|
-
});
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const stream: AssistantStream = {
|
|
194
|
-
id,
|
|
195
|
-
appendText(delta) { mutate((p) => appendTextPart(p, delta)); return stream; },
|
|
196
|
-
appendReasoning(delta, opts) { mutate((p) => appendReasoningPart(p, delta, opts)); return stream; },
|
|
197
|
-
upsertTool(toolCallId, patch) { mutate((p) => upsertToolPart(p, toolCallId, patch)); return stream; },
|
|
198
|
-
// Upsert, not append: keyed on envelope.id so a revised card replaces itself.
|
|
199
|
-
addCard(envelope) { mutate((p) => upsertCardPart(p, envelope)); return stream; },
|
|
200
|
-
addSource(source) { mutate((p) => [...p, { type: 'source', source }]); return stream; },
|
|
201
|
-
addFile(attachment) { mutate((p) => [...p, { type: 'file', attachment }]); return stream; },
|
|
202
|
-
done() { settled = true; },
|
|
203
|
-
abort(reason) {
|
|
204
|
-
// Whitespace-only is the same nothing as empty. `err.message` on a thrown
|
|
205
|
-
// Error is free to be either, and appending it would render an INVISIBLE
|
|
206
|
-
// text part -- a blank bubble that also claims to have said something.
|
|
207
|
-
const text = reason?.trim() || undefined;
|
|
208
|
-
mutate((p) => {
|
|
209
|
-
let carried = false;
|
|
210
|
-
const next = p.map((part) => {
|
|
211
|
-
if (part.type !== 'tool' || part.tool.state === 'output-available') return part;
|
|
212
|
-
// Already showing its own, more specific failure: keep it, and count
|
|
213
|
-
// it as carrying. See the note above `abort`.
|
|
214
|
-
if (part.tool.state === 'output-error' && part.tool.errorText?.trim()) {
|
|
215
|
-
carried = true;
|
|
216
|
-
return part;
|
|
217
|
-
}
|
|
218
|
-
carried = true;
|
|
219
|
-
return { ...part, tool: { ...part.tool, state: 'output-error' as const, errorText: text } };
|
|
220
|
-
});
|
|
221
|
-
// The reason has to land SOMEWHERE. See the note above `abort`.
|
|
222
|
-
if (carried || !text) return next;
|
|
223
|
-
return [...next, { type: 'text', text }];
|
|
224
|
-
});
|
|
225
|
-
settled = true;
|
|
226
|
-
},
|
|
227
|
-
};
|
|
228
|
-
return stream;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/** Wrap a stream so `onSettle` fires on done/abort (used to toggle a `loading` flag).
|
|
232
|
-
* Preserves the fluent chain by returning the wrapper from every mutator. */
|
|
233
|
-
export function onStreamSettled(inner: AssistantStream, onSettle: () => void): AssistantStream {
|
|
234
|
-
const wrapper: AssistantStream = {
|
|
235
|
-
id: inner.id,
|
|
236
|
-
appendText(delta) { inner.appendText(delta); return wrapper; },
|
|
237
|
-
appendReasoning(delta, opts) { inner.appendReasoning(delta, opts); return wrapper; },
|
|
238
|
-
upsertTool(toolCallId, patch) { inner.upsertTool(toolCallId, patch); return wrapper; },
|
|
239
|
-
addCard(envelope) { inner.addCard(envelope); return wrapper; },
|
|
240
|
-
addSource(source) { inner.addSource(source); return wrapper; },
|
|
241
|
-
addFile(attachment) { inner.addFile(attachment); return wrapper; },
|
|
242
|
-
done() { inner.done(); onSettle(); },
|
|
243
|
-
abort(reason) { inner.abort(reason); onSettle(); },
|
|
244
|
-
};
|
|
245
|
-
return wrapper;
|
|
246
|
-
}
|
package/src/state/suggestions.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** Append a suggestion; no-op when already present. Returns a new array. */
|
|
2
|
-
export function addSuggestion(suggestions: string[], s: string): string[] {
|
|
3
|
-
return suggestions.includes(s) ? suggestions.slice() : [...suggestions, s];
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
/** Remove a suggestion by value. */
|
|
7
|
-
export function removeSuggestion(suggestions: string[], s: string): string[] {
|
|
8
|
-
return suggestions.filter((x) => x !== s);
|
|
9
|
-
}
|
package/src/state/threads.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// src/state/threads.ts — the thread-switching fold.
|
|
2
|
-
//
|
|
3
|
-
// The identity category from the workspace glue inventory (spec §1/§3b): an
|
|
4
|
-
// id-bound `SetMessages`, per-thread loading state, the abort map, and
|
|
5
|
-
// delete-under-stream safety. Pure folds + callbacks per the state charter —
|
|
6
|
-
// no fetch, no DOM, no storage; the only state a helper here owns is the
|
|
7
|
-
// irreducible kind (which turns are in flight), never the consumer's records.
|
|
8
|
-
import type { ChatMessage } from '../elements/chat-types';
|
|
9
|
-
import type { SetMessages } from './stream';
|
|
10
|
-
|
|
11
|
-
/** The minimal thread record the fold needs. The consumer's own record type
|
|
12
|
-
* (title, timestamps, whatever its storage keeps) extends this — those fields
|
|
13
|
-
* are policy and stay outside the kit. */
|
|
14
|
-
export interface ThreadLike {
|
|
15
|
-
id: string;
|
|
16
|
-
messages: ChatMessage[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** The functional-updater setter over the whole thread LIST — the same
|
|
20
|
-
* React-setState shape `SetMessages` is, one level up. */
|
|
21
|
-
export type SetThreads<T extends ThreadLike> = (updater: (prev: T[]) => T[]) => void;
|
|
22
|
-
|
|
23
|
-
export interface BindThreadOptions<T extends ThreadLike> {
|
|
24
|
-
/** Stamp the changed record (e.g. `updatedAt`). Runs on a hit only. Kept a
|
|
25
|
-
* callback because WHAT gets stamped — and with whose clock — is the
|
|
26
|
-
* consumer's record shape, not ours. */
|
|
27
|
-
touch?: (thread: T) => T;
|
|
28
|
-
/** A delta arrived for a thread that is no longer in the list (deleted while
|
|
29
|
-
* its reply was streaming). The delta is dropped either way — dropping is
|
|
30
|
-
* the only correct fold — but the drop is reported, not silent. */
|
|
31
|
-
onDrop?: (threadId: string) => void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Pure fold: apply `updater` to the messages of thread `id` within a list.
|
|
36
|
-
*
|
|
37
|
-
* reactivity-two-halves (CLAUDE.md): the hit gets a NEW containing array
|
|
38
|
-
* (which notifies) and a NEW record object (which makes the change visible);
|
|
39
|
-
* every other record keeps its reference. A MISS returns `threads` itself —
|
|
40
|
-
* the same reference — so a late delta for a deleted thread re-renders
|
|
41
|
-
* nothing and resurrects nothing.
|
|
42
|
-
*/
|
|
43
|
-
export function updateThreadMessages<T extends ThreadLike>(
|
|
44
|
-
threads: T[],
|
|
45
|
-
id: string,
|
|
46
|
-
updater: (prev: ChatMessage[]) => ChatMessage[],
|
|
47
|
-
opts: BindThreadOptions<T> = {},
|
|
48
|
-
): T[] {
|
|
49
|
-
let hit = false;
|
|
50
|
-
const next = threads.map((t) => {
|
|
51
|
-
if (t.id !== id) return t;
|
|
52
|
-
hit = true;
|
|
53
|
-
const updated = { ...t, messages: updater(t.messages) };
|
|
54
|
-
return opts.touch ? opts.touch(updated) : updated;
|
|
55
|
-
});
|
|
56
|
-
if (!hit) {
|
|
57
|
-
opts.onDrop?.(id);
|
|
58
|
-
return threads;
|
|
59
|
-
}
|
|
60
|
-
return next;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* A `SetMessages` bound to ONE thread. Capture the id when the user hits send
|
|
65
|
-
* and hand the result to `createAssistantStream`: the reply then lands in the
|
|
66
|
-
* thread that was open at send time, never whichever one is open when the
|
|
67
|
-
* tokens arrive — which is what makes switching away mid-reply (and coming
|
|
68
|
-
* back to a finished answer) safe.
|
|
69
|
-
*/
|
|
70
|
-
export function bindThreadMessages<T extends ThreadLike>(
|
|
71
|
-
setThreads: SetThreads<T>,
|
|
72
|
-
id: string,
|
|
73
|
-
opts: BindThreadOptions<T> = {},
|
|
74
|
-
): SetMessages {
|
|
75
|
-
return (updater) => {
|
|
76
|
-
setThreads((prev) => updateThreadMessages(prev, id, updater, opts));
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** The in-flight-turn bookkeeping for a multi-thread app: which threads are
|
|
81
|
-
* streaming, and the AbortController for each. See `createThreadSessions`. */
|
|
82
|
-
export interface ThreadSessions {
|
|
83
|
-
/** Register a new in-flight turn. One turn per thread: a prior in-flight
|
|
84
|
-
* turn for the SAME thread is aborted first. Pass the returned controller's
|
|
85
|
-
* `signal` to your fetch — the fetch line itself stays yours. */
|
|
86
|
-
begin(threadId: string): AbortController;
|
|
87
|
-
/** The turn settled (done or failed) — call from your `finally`. `controller`
|
|
88
|
-
* is required so a slow old turn's cleanup cannot clear a newer turn that
|
|
89
|
-
* has since begun on the same thread: a stale controller is a no-op. */
|
|
90
|
-
end(threadId: string, controller: AbortController): void;
|
|
91
|
-
/** Cancel the in-flight turn (the delete-under-stream story): aborts the
|
|
92
|
-
* controller and clears the streaming state. Returns whether anything was
|
|
93
|
-
* actually in flight. Pair it with the id-bound sink above, which drops any
|
|
94
|
-
* deltas that were already past the abort. */
|
|
95
|
-
abort(threadId: string): boolean;
|
|
96
|
-
isStreaming(threadId: string): boolean;
|
|
97
|
-
/** A fresh array snapshot each call — safe to hand straight to a setState. */
|
|
98
|
-
streamingIds(): string[];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Create the session tracker. `onChange` fires with a fresh `streamingIds()`
|
|
103
|
-
* snapshot after every transition — mirror it into your framework's state to
|
|
104
|
-
* derive `loading` (`sessions.isStreaming(activeId)` is the per-thread flag a
|
|
105
|
-
* single boolean cannot be, because a stream keeps running when you switch
|
|
106
|
-
* away).
|
|
107
|
-
*
|
|
108
|
-
* This is the one stateful object in the module, because an abort map is
|
|
109
|
-
* irreducibly stateful; it still does no I/O and owns no timer.
|
|
110
|
-
*/
|
|
111
|
-
export function createThreadSessions(onChange?: (streamingIds: string[]) => void): ThreadSessions {
|
|
112
|
-
const inFlight = new Map<string, AbortController>();
|
|
113
|
-
const snapshot = () => Array.from(inFlight.keys());
|
|
114
|
-
const notify = () => onChange?.(snapshot());
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
begin(threadId) {
|
|
118
|
-
inFlight.get(threadId)?.abort();
|
|
119
|
-
const controller = new AbortController();
|
|
120
|
-
inFlight.set(threadId, controller);
|
|
121
|
-
notify();
|
|
122
|
-
return controller;
|
|
123
|
-
},
|
|
124
|
-
end(threadId, controller) {
|
|
125
|
-
if (inFlight.get(threadId) !== controller) return;
|
|
126
|
-
inFlight.delete(threadId);
|
|
127
|
-
notify();
|
|
128
|
-
},
|
|
129
|
-
abort(threadId) {
|
|
130
|
-
const controller = inFlight.get(threadId);
|
|
131
|
-
if (!controller) return false;
|
|
132
|
-
controller.abort();
|
|
133
|
-
inFlight.delete(threadId);
|
|
134
|
-
notify();
|
|
135
|
-
return true;
|
|
136
|
-
},
|
|
137
|
-
isStreaming(threadId) {
|
|
138
|
-
return inFlight.has(threadId);
|
|
139
|
-
},
|
|
140
|
-
streamingIds: snapshot,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared fake `requestAnimationFrame` + `performance.now()` clock for tests
|
|
5
|
-
* that need to drive time deterministically instead of racing real timers.
|
|
6
|
-
*
|
|
7
|
-
* requestAnimationFrame's timestamp and performance.now() share a time origin
|
|
8
|
-
* per spec, so production code can read either. Stubbing them off the same
|
|
9
|
-
* fake `now` keeps the two from silently disagreeing.
|
|
10
|
-
*
|
|
11
|
-
* The stub holds a REAL per-registration queue, matching a real browser: a
|
|
12
|
-
* single frame fires every callback that was pending BEFORE that frame, all
|
|
13
|
-
* with the SAME advanced `now`, in registration order -- so two
|
|
14
|
-
* independently-animating things under test (e.g. a `createTween`'s own step
|
|
15
|
-
* loop and `ShaderCanvas`'s separate `draw` loop, both requestAnimationFrame
|
|
16
|
-
* consumers, both mounted at once) tick together on one `advance()` call
|
|
17
|
-
* instead of the second silently stealing the first's slot.
|
|
18
|
-
*
|
|
19
|
-
* This used to be a single PENDING-callback slot, not a queue: a second
|
|
20
|
-
* consumer scheduling a new frame before `advance()` ran overwrote the
|
|
21
|
-
* first rather than queueing behind it. That was fine for anything that only
|
|
22
|
-
* ever has ONE thing pending at a time (the common case, e.g. bar/grid/radial's
|
|
23
|
-
* single sequencer tick, or a lone `createTween`), which is why switching to a
|
|
24
|
-
* queue does not change any of those. It was NOT fine for a mounted shader
|
|
25
|
-
* variant, where a tween and ShaderCanvas's `draw` are both independently
|
|
26
|
-
* pending at once: `draw` always registers last and re-arms itself every
|
|
27
|
-
* `advance()`, so it permanently "won" the single slot and the tween's step
|
|
28
|
-
* never fired -- silently defeating any test trying to prove something holds
|
|
29
|
-
* while UNIFORM VALUES genuinely change every frame (see
|
|
30
|
-
* `variant-custom.test.tsx`'s recompile-guard test for the concrete case this
|
|
31
|
-
* was fixed for).
|
|
32
|
-
*
|
|
33
|
-
* `cancelAnimationFrame` cancels by id now (each `requestAnimationFrame` call
|
|
34
|
-
* gets its own), not by clearing whatever happens to be in the single slot --
|
|
35
|
-
* required once more than one callback can be pending at a time, so a
|
|
36
|
-
* `cancelAnimationFrame(idA)` cannot accidentally drop a DIFFERENT pending
|
|
37
|
-
* callback `idB`.
|
|
38
|
-
*
|
|
39
|
-
* Call once per `describe` block (or at file scope for the whole file); it
|
|
40
|
-
* registers `beforeEach`/`afterEach` hooks scoped to wherever it is called,
|
|
41
|
-
* exactly like inlining the hooks would, and returns the driver bound to
|
|
42
|
-
* that scope's fake clock.
|
|
43
|
-
*/
|
|
44
|
-
export function installFakeClock() {
|
|
45
|
-
let now = 0;
|
|
46
|
-
let nextId = 1;
|
|
47
|
-
let pending = new Map<number, (t: number) => void>();
|
|
48
|
-
|
|
49
|
-
beforeEach(() => {
|
|
50
|
-
now = 0;
|
|
51
|
-
nextId = 1;
|
|
52
|
-
pending = new Map();
|
|
53
|
-
vi.stubGlobal('requestAnimationFrame', (cb: FrameRequestCallback) => {
|
|
54
|
-
const id = nextId++;
|
|
55
|
-
pending.set(id, cb as (t: number) => void);
|
|
56
|
-
return id;
|
|
57
|
-
});
|
|
58
|
-
vi.stubGlobal('cancelAnimationFrame', (id: number) => {
|
|
59
|
-
pending.delete(id);
|
|
60
|
-
});
|
|
61
|
-
vi.stubGlobal('performance', { now: () => now });
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
afterEach(() => vi.unstubAllGlobals());
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Advance the fake clock and run every callback pending BEFORE this call,
|
|
68
|
-
* all at the new `now` -- one simulated frame. A callback that reschedules
|
|
69
|
-
* itself (the normal RAF-loop pattern) lands in a FRESH pending set for the
|
|
70
|
-
* NEXT `advance()`, not this one: snapshotting the callback list before
|
|
71
|
-
* invoking any of them is what keeps a self-rescheduling loop from looping
|
|
72
|
-
* forever inside a single `advance()` call, matching how a real browser
|
|
73
|
-
* frame never re-enters itself either.
|
|
74
|
-
*/
|
|
75
|
-
function advance(ms: number) {
|
|
76
|
-
now += ms;
|
|
77
|
-
const callbacks = Array.from(pending.values());
|
|
78
|
-
pending = new Map();
|
|
79
|
-
for (const cb of callbacks) cb(now);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Whether at least one requestAnimationFrame callback is currently pending. */
|
|
83
|
-
function isFramePending(): boolean {
|
|
84
|
-
return pending.size > 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return { advance, isFramePending };
|
|
88
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Types the chat kit components reference. Extracted from the kit's origin
|
|
2
|
-
// project (@tab-zen/shared) so the kit is self-contained. Only the types the
|
|
3
|
-
// components actually import are kept; the RAG/document/adapter types are dropped.
|
|
4
|
-
|
|
5
|
-
export interface ModelOption {
|
|
6
|
-
id: string;
|
|
7
|
-
name: string;
|
|
8
|
-
provider?: string;
|
|
9
|
-
/** A short subtitle shown under the name (e.g. "Flagship model"). Takes
|
|
10
|
-
* precedence over `provider` for the row subtitle when both are set. */
|
|
11
|
-
description?: string;
|
|
12
|
-
/** Optional group name. Models sharing a `group` are collected under a
|
|
13
|
-
* collapsible section (e.g. "Legacy models"); ungrouped models list first. */
|
|
14
|
-
group?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface SearchFilters {
|
|
18
|
-
tags?: string[];
|
|
19
|
-
authors?: string[];
|
|
20
|
-
contentType?: 'transcript' | 'markdown';
|
|
21
|
-
dateRange?: { from: string; to: string };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ConversationScope {
|
|
25
|
-
type: 'document' | 'collection';
|
|
26
|
-
documentId?: string;
|
|
27
|
-
filters?: SearchFilters;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ConversationSummary {
|
|
31
|
-
id: string;
|
|
32
|
-
title: string;
|
|
33
|
-
groupId?: string;
|
|
34
|
-
/** Only meaningful to scope-aware consumers; the list never reads it. */
|
|
35
|
-
scope?: ConversationScope;
|
|
36
|
-
messageCount: number;
|
|
37
|
-
/** Fallback for the auto relative time when updatedAt is absent. */
|
|
38
|
-
lastMessageAt?: string;
|
|
39
|
-
updatedAt: string;
|
|
40
|
-
/** Right-aligned trailing text on the row — a count, status, or "days ago".
|
|
41
|
-
* When omitted, a short relative time is auto-derived from `updatedAt`
|
|
42
|
-
* (fallback `lastMessageAt`). */
|
|
43
|
-
trailing?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface ConversationGroup {
|
|
47
|
-
id: string;
|
|
48
|
-
userId?: string;
|
|
49
|
-
teamId?: string;
|
|
50
|
-
name: string;
|
|
51
|
-
sortOrder: number;
|
|
52
|
-
createdAt: string;
|
|
53
|
-
}
|
package/src/ui/action-icons.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { Component } from 'solid-js';
|
|
2
|
-
import {
|
|
3
|
-
Copy, ThumbsUp, ThumbsDown, RefreshCw, Pencil,
|
|
4
|
-
Share, Bookmark, Download, Link, Trash2, Check, X, Star, Flag, Reply, MoreHorizontal, Volume2,
|
|
5
|
-
} from 'lucide-solid';
|
|
6
|
-
import type { ChatMessageAction } from '../elements/chat-types';
|
|
7
|
-
|
|
8
|
-
type IconComponent = Component<{ class?: string }>;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Curated `name → lucide-solid Component` registry for message action buttons.
|
|
12
|
-
*
|
|
13
|
-
* Fixed allow-list — NO arbitrary SVG/URL. Covers the five built-in action
|
|
14
|
-
* icons plus the common custom ones a host is likely to want. Reused across
|
|
15
|
-
* `kai-message`/`kai-chat` (and, later, kai-checkpoint/kai-empty).
|
|
16
|
-
*/
|
|
17
|
-
const ICONS: Record<string, IconComponent> = {
|
|
18
|
-
// built-in action icons
|
|
19
|
-
copy: Copy,
|
|
20
|
-
like: ThumbsUp,
|
|
21
|
-
dislike: ThumbsDown,
|
|
22
|
-
regenerate: RefreshCw,
|
|
23
|
-
edit: Pencil,
|
|
24
|
-
// common custom icons
|
|
25
|
-
share: Share,
|
|
26
|
-
bookmark: Bookmark,
|
|
27
|
-
download: Download,
|
|
28
|
-
link: Link,
|
|
29
|
-
trash: Trash2,
|
|
30
|
-
check: Check,
|
|
31
|
-
x: X,
|
|
32
|
-
star: Star,
|
|
33
|
-
flag: Flag,
|
|
34
|
-
reply: Reply,
|
|
35
|
-
more: MoreHorizontal,
|
|
36
|
-
'volume-2': Volume2,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/** Resolve a curated icon name to its component, or `undefined` when unknown
|
|
40
|
-
* (the caller then renders a label-only button). */
|
|
41
|
-
export function actionIcon(name?: string): IconComponent | undefined {
|
|
42
|
-
if (!name) return undefined;
|
|
43
|
-
return ICONS[name];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Default labels for the built-in actions (also used as the `aria-label`). */
|
|
47
|
-
export const BUILTIN_ACTION_LABEL: Record<ChatMessageAction, string> = {
|
|
48
|
-
copy: 'Copy',
|
|
49
|
-
like: 'Like',
|
|
50
|
-
dislike: 'Dislike',
|
|
51
|
-
regenerate: 'Regenerate',
|
|
52
|
-
edit: 'Edit',
|
|
53
|
-
};
|