@signalflare-ai/ui 0.5.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/CHANGELOG.md +96 -0
- package/README.md +527 -0
- package/ai/USAGE.md +200 -0
- package/ai/component-registry.json +7103 -0
- package/ai/component-registry.md +3046 -0
- package/ai/schemas.ts +1230 -0
- package/bin/intent.js +23 -0
- package/bin/sf.js +34 -0
- package/dist/.build-complete +1 -0
- package/dist/ai/schemas.d.ts +7056 -0
- package/dist/ai/schemas.d.ts.map +1 -0
- package/dist/ai-actions-DG1dhDMP.js +57 -0
- package/dist/ai-actions-DG1dhDMP.js.map +1 -0
- package/dist/ai-agent-card-BbtL4NII.js +171 -0
- package/dist/ai-agent-card-BbtL4NII.js.map +1 -0
- package/dist/ai-approval-Mb7-BY6i.js +184 -0
- package/dist/ai-approval-Mb7-BY6i.js.map +1 -0
- package/dist/ai-code-block-BI_z0UVR.js +110 -0
- package/dist/ai-code-block-BI_z0UVR.js.map +1 -0
- package/dist/ai-conversation-DYtExcrw.js +184 -0
- package/dist/ai-conversation-DYtExcrw.js.map +1 -0
- package/dist/ai-info-banner-BpzauUAY.js +76 -0
- package/dist/ai-info-banner-BpzauUAY.js.map +1 -0
- package/dist/ai-loader-Cr3eQkNS.js +134 -0
- package/dist/ai-loader-Cr3eQkNS.js.map +1 -0
- package/dist/ai-message-CV8SBoHM.js +286 -0
- package/dist/ai-message-CV8SBoHM.js.map +1 -0
- package/dist/ai-mission-header-ByYkJ6YP.js +171 -0
- package/dist/ai-mission-header-ByYkJ6YP.js.map +1 -0
- package/dist/ai-prompt-input-Bo1YuJly.js +769 -0
- package/dist/ai-prompt-input-Bo1YuJly.js.map +1 -0
- package/dist/ai-question-Dp1g9k2o.js +149 -0
- package/dist/ai-question-Dp1g9k2o.js.map +1 -0
- package/dist/ai-reasoning-UAmNx_LD.js +270 -0
- package/dist/ai-reasoning-UAmNx_LD.js.map +1 -0
- package/dist/ai-response-BWoVsNQG.js +42 -0
- package/dist/ai-response-BWoVsNQG.js.map +1 -0
- package/dist/ai-shimmer-BpOmfonu.js +43 -0
- package/dist/ai-shimmer-BpOmfonu.js.map +1 -0
- package/dist/ai-status-badge-WhbKVeqn.js +63 -0
- package/dist/ai-status-badge-WhbKVeqn.js.map +1 -0
- package/dist/ai-streaming-text-ClL7FwvD.js +81 -0
- package/dist/ai-streaming-text-ClL7FwvD.js.map +1 -0
- package/dist/ai-subagent-BruGN1UE.js +133 -0
- package/dist/ai-subagent-BruGN1UE.js.map +1 -0
- package/dist/ai-suggestion-CNsCZj5P.js +55 -0
- package/dist/ai-suggestion-CNsCZj5P.js.map +1 -0
- package/dist/ai-task-list-B9CpMDYN.js +120 -0
- package/dist/ai-task-list-B9CpMDYN.js.map +1 -0
- package/dist/ai-timeline-Bb5ntsr3.js +373 -0
- package/dist/ai-timeline-Bb5ntsr3.js.map +1 -0
- package/dist/ai-tool-BGH8nQ_D.js +437 -0
- package/dist/ai-tool-BGH8nQ_D.js.map +1 -0
- package/dist/ai-usage-bar-BI-p-JBk.js +70 -0
- package/dist/ai-usage-bar-BI-p-JBk.js.map +1 -0
- package/dist/badge-D_eaA6wv.js +128 -0
- package/dist/badge-D_eaA6wv.js.map +1 -0
- package/dist/banner-B_6oBrsu.js +54 -0
- package/dist/banner-B_6oBrsu.js.map +1 -0
- package/dist/breadcrumbs-BlmeYfgq.js +128 -0
- package/dist/breadcrumbs-BlmeYfgq.js.map +1 -0
- package/dist/button-De0267YU.js +170 -0
- package/dist/button-De0267YU.js.map +1 -0
- package/dist/catalog.js +506 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chart-Bes4MN3C.js +618 -0
- package/dist/chart-Bes4MN3C.js.map +1 -0
- package/dist/checkbox-CPX7lBaU.js +153 -0
- package/dist/checkbox-CPX7lBaU.js.map +1 -0
- package/dist/clipboard-text-92YeCybc.js +176 -0
- package/dist/clipboard-text-92YeCybc.js.map +1 -0
- package/dist/cn-YROP2_ox.js +25 -0
- package/dist/cn-YROP2_ox.js.map +1 -0
- package/dist/code-DE1Yy1Cu.js +97 -0
- package/dist/code-DE1Yy1Cu.js.map +1 -0
- package/dist/collapsible-DWsXeXmS.js +72 -0
- package/dist/collapsible-DWsXeXmS.js.map +1 -0
- package/dist/combobox-B0bLdsX8.js +197 -0
- package/dist/combobox-B0bLdsX8.js.map +1 -0
- package/dist/command-line/cli.js +823 -0
- package/dist/command-palette-CBTY8EiF.js +484 -0
- package/dist/command-palette-CBTY8EiF.js.map +1 -0
- package/dist/components/ai-actions.js +3 -0
- package/dist/components/ai-agent-card.js +3 -0
- package/dist/components/ai-approval.js +3 -0
- package/dist/components/ai-code-block.js +3 -0
- package/dist/components/ai-conversation.js +3 -0
- package/dist/components/ai-info-banner.js +3 -0
- package/dist/components/ai-loader.js +3 -0
- package/dist/components/ai-message.js +3 -0
- package/dist/components/ai-mission-header.js +3 -0
- package/dist/components/ai-prompt-input.js +3 -0
- package/dist/components/ai-question.js +3 -0
- package/dist/components/ai-reasoning.js +3 -0
- package/dist/components/ai-response.js +3 -0
- package/dist/components/ai-shimmer.js +3 -0
- package/dist/components/ai-status-badge.js +3 -0
- package/dist/components/ai-streaming-text.js +3 -0
- package/dist/components/ai-subagent.js +3 -0
- package/dist/components/ai-suggestion.js +3 -0
- package/dist/components/ai-task-list.js +3 -0
- package/dist/components/ai-timeline.js +3 -0
- package/dist/components/ai-tool.js +3 -0
- package/dist/components/ai-usage-bar.js +3 -0
- package/dist/components/badge.js +3 -0
- package/dist/components/banner.js +3 -0
- package/dist/components/breadcrumbs.js +3 -0
- package/dist/components/button.js +3 -0
- package/dist/components/chart.js +3 -0
- package/dist/components/checkbox.js +3 -0
- package/dist/components/clipboard-text.js +3 -0
- package/dist/components/code.js +3 -0
- package/dist/components/collapsible.js +3 -0
- package/dist/components/combobox.js +3 -0
- package/dist/components/command-palette.js +3 -0
- package/dist/components/data-grid.js +3 -0
- package/dist/components/date-picker.js +3 -0
- package/dist/components/date-range-picker.js +3 -0
- package/dist/components/dialog.js +3 -0
- package/dist/components/dropdown.js +3 -0
- package/dist/components/empty.js +3 -0
- package/dist/components/field.js +3 -0
- package/dist/components/filters.js +3 -0
- package/dist/components/flow.js +3 -0
- package/dist/components/grid.js +3 -0
- package/dist/components/input.js +4 -0
- package/dist/components/label.js +3 -0
- package/dist/components/layer-card.js +3 -0
- package/dist/components/link.js +92 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/loader.js +4 -0
- package/dist/components/menubar.js +3 -0
- package/dist/components/meter.js +3 -0
- package/dist/components/pagination.js +3 -0
- package/dist/components/popover.js +3 -0
- package/dist/components/radio.js +3 -0
- package/dist/components/select.js +3 -0
- package/dist/components/sensitive-input.js +3 -0
- package/dist/components/sidebar.js +3 -0
- package/dist/components/signalflare-ai-logo.js +3 -0
- package/dist/components/surface.js +3 -0
- package/dist/components/switch.js +3 -0
- package/dist/components/table.js +3 -0
- package/dist/components/tabs.js +3 -0
- package/dist/components/text.js +3 -0
- package/dist/components/theme-toggle.js +3 -0
- package/dist/components/toast.js +3 -0
- package/dist/components/tooltip.js +3 -0
- package/dist/components/use-agent-harness.js +3 -0
- package/dist/data-grid-UJ9ja5cu.js +305 -0
- package/dist/data-grid-UJ9ja5cu.js.map +1 -0
- package/dist/date-picker-ebekkC3R.js +57 -0
- package/dist/date-picker-ebekkC3R.js.map +1 -0
- package/dist/date-range-picker-D75LLINc.js +347 -0
- package/dist/date-range-picker-D75LLINc.js.map +1 -0
- package/dist/dialog-CyHEQXEY.js +104 -0
- package/dist/dialog-CyHEQXEY.js.map +1 -0
- package/dist/dist-BNlyONdD.js +3546 -0
- package/dist/dist-BNlyONdD.js.map +1 -0
- package/dist/dropdown-J5T4pHaR.js +202 -0
- package/dist/dropdown-J5T4pHaR.js.map +1 -0
- package/dist/empty-D2TypIId.js +90 -0
- package/dist/empty-D2TypIId.js.map +1 -0
- package/dist/favicon.svg +4 -0
- package/dist/field-Y_UK1_Cg.js +57 -0
- package/dist/field-Y_UK1_Cg.js.map +1 -0
- package/dist/filters-BdBogf7D.js +682 -0
- package/dist/filters-BdBogf7D.js.map +1 -0
- package/dist/flow-BRsYUCJa.js +741 -0
- package/dist/flow-BRsYUCJa.js.map +1 -0
- package/dist/genui.js +40 -0
- package/dist/genui.js.map +1 -0
- package/dist/grid-qUAN9hFx.js +119 -0
- package/dist/grid-qUAN9hFx.js.map +1 -0
- package/dist/highlight-to-react-ClEfL81q.js +57 -0
- package/dist/highlight-to-react-ClEfL81q.js.map +1 -0
- package/dist/index.js +215 -0
- package/dist/index.js.map +1 -0
- package/dist/input-BxQAnXki.js +81 -0
- package/dist/input-BxQAnXki.js.map +1 -0
- package/dist/input-Cn25I4o5.js +121 -0
- package/dist/input-Cn25I4o5.js.map +1 -0
- package/dist/label-QtJxtJ4u.js +70 -0
- package/dist/label-QtJxtJ4u.js.map +1 -0
- package/dist/layer-card-BME0eljh.js +44 -0
- package/dist/layer-card-BME0eljh.js.map +1 -0
- package/dist/link-provider-BUZKXaNE.js +25 -0
- package/dist/link-provider-BUZKXaNE.js.map +1 -0
- package/dist/loader-DAcc-Uag.js +84 -0
- package/dist/loader-DAcc-Uag.js.map +1 -0
- package/dist/logo.svg +1 -0
- package/dist/menubar-C8NzAjfd.js +102 -0
- package/dist/menubar-C8NzAjfd.js.map +1 -0
- package/dist/meter-CpmTenEr.js +37 -0
- package/dist/meter-CpmTenEr.js.map +1 -0
- package/dist/pagination-C_YqCy8l.js +117 -0
- package/dist/pagination-C_YqCy8l.js.map +1 -0
- package/dist/popover-BRQZ2b6z.js +147 -0
- package/dist/popover-BRQZ2b6z.js.map +1 -0
- package/dist/primitives/accordion.js +2 -0
- package/dist/primitives/alert-dialog.js +2 -0
- package/dist/primitives/autocomplete.js +2 -0
- package/dist/primitives/avatar.js +2 -0
- package/dist/primitives/button.js +2 -0
- package/dist/primitives/checkbox-group.js +2 -0
- package/dist/primitives/checkbox.js +2 -0
- package/dist/primitives/collapsible.js +2 -0
- package/dist/primitives/combobox.js +2 -0
- package/dist/primitives/context-menu.js +2 -0
- package/dist/primitives/csp-provider.js +2 -0
- package/dist/primitives/dialog.js +2 -0
- package/dist/primitives/direction-provider.js +2 -0
- package/dist/primitives/drawer.js +2 -0
- package/dist/primitives/field.js +2 -0
- package/dist/primitives/fieldset.js +2 -0
- package/dist/primitives/form.js +2 -0
- package/dist/primitives/input.js +2 -0
- package/dist/primitives/menu.js +2 -0
- package/dist/primitives/menubar.js +2 -0
- package/dist/primitives/meter.js +2 -0
- package/dist/primitives/navigation-menu.js +2 -0
- package/dist/primitives/number-field.js +2 -0
- package/dist/primitives/popover.js +2 -0
- package/dist/primitives/preview-card.js +2 -0
- package/dist/primitives/progress.js +2 -0
- package/dist/primitives/radio-group.js +2 -0
- package/dist/primitives/radio.js +2 -0
- package/dist/primitives/scroll-area.js +2 -0
- package/dist/primitives/select.js +2 -0
- package/dist/primitives/separator.js +2 -0
- package/dist/primitives/slider.js +2 -0
- package/dist/primitives/switch.js +2 -0
- package/dist/primitives/tabs.js +2 -0
- package/dist/primitives/toast.js +2 -0
- package/dist/primitives/toggle-group.js +2 -0
- package/dist/primitives/toggle.js +2 -0
- package/dist/primitives/toolbar.js +2 -0
- package/dist/primitives/tooltip.js +2 -0
- package/dist/primitives.js +40 -0
- package/dist/radio-B7zg1wUI.js +101 -0
- package/dist/radio-B7zg1wUI.js.map +1 -0
- package/dist/registry.js +1 -0
- package/dist/select-9p721G00.js +95 -0
- package/dist/select-9p721G00.js.map +1 -0
- package/dist/sensitive-input-D5je2NLl.js +248 -0
- package/dist/sensitive-input-D5je2NLl.js.map +1 -0
- package/dist/sidebar-DOwBrq57.js +964 -0
- package/dist/sidebar-DOwBrq57.js.map +1 -0
- package/dist/signalflare-ai-logo-DDhxMJD6.js +260 -0
- package/dist/signalflare-ai-logo-DDhxMJD6.js.map +1 -0
- package/dist/skeleton-line-Do3UmGk9.js +36 -0
- package/dist/skeleton-line-Do3UmGk9.js.map +1 -0
- package/dist/src/blocks/agent-harness/agent-harness.d.ts +177 -0
- package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -0
- package/dist/src/blocks/agent-harness/agent-harness.tsx +1122 -0
- package/dist/src/blocks/agent-harness/index.d.ts +2 -0
- package/dist/src/blocks/agent-harness/index.d.ts.map +1 -0
- package/dist/src/blocks/commander/commander.d.ts +101 -0
- package/dist/src/blocks/commander/commander.d.ts.map +1 -0
- package/dist/src/blocks/commander/commander.tsx +477 -0
- package/dist/src/blocks/commander/index.d.ts +2 -0
- package/dist/src/blocks/commander/index.d.ts.map +1 -0
- package/dist/src/blocks/delete-resource/delete-resource.d.ts +46 -0
- package/dist/src/blocks/delete-resource/delete-resource.d.ts.map +1 -0
- package/dist/src/blocks/delete-resource/delete-resource.tsx +214 -0
- package/dist/src/blocks/delete-resource/index.d.ts +2 -0
- package/dist/src/blocks/delete-resource/index.d.ts.map +1 -0
- package/dist/src/blocks/map-block/index.d.ts +2 -0
- package/dist/src/blocks/map-block/index.d.ts.map +1 -0
- package/dist/src/blocks/map-block/map-block.d.ts +79 -0
- package/dist/src/blocks/map-block/map-block.d.ts.map +1 -0
- package/dist/src/blocks/map-block/map-block.tsx +522 -0
- package/dist/src/blocks/page-header/index.d.ts +2 -0
- package/dist/src/blocks/page-header/index.d.ts.map +1 -0
- package/dist/src/blocks/page-header/page-header.d.ts +38 -0
- package/dist/src/blocks/page-header/page-header.d.ts.map +1 -0
- package/dist/src/blocks/page-header/page-header.tsx +96 -0
- package/dist/src/blocks/resource-list/index.d.ts +2 -0
- package/dist/src/blocks/resource-list/index.d.ts.map +1 -0
- package/dist/src/blocks/resource-list/resource-list.d.ts +18 -0
- package/dist/src/blocks/resource-list/resource-list.d.ts.map +1 -0
- package/dist/src/blocks/resource-list/resource-list.test.tsx +27 -0
- package/dist/src/blocks/resource-list/resource-list.tsx +65 -0
- package/dist/src/catalog/catalog.d.ts +75 -0
- package/dist/src/catalog/catalog.d.ts.map +1 -0
- package/dist/src/catalog/data.d.ts +44 -0
- package/dist/src/catalog/data.d.ts.map +1 -0
- package/dist/src/catalog/index.d.ts +35 -0
- package/dist/src/catalog/index.d.ts.map +1 -0
- package/dist/src/catalog/sf-components.d.ts +8 -0
- package/dist/src/catalog/sf-components.d.ts.map +1 -0
- package/dist/src/catalog/sf-registry.d.ts +4 -0
- package/dist/src/catalog/sf-registry.d.ts.map +1 -0
- package/dist/src/catalog/types.d.ts +226 -0
- package/dist/src/catalog/types.d.ts.map +1 -0
- package/dist/src/catalog/visibility.d.ts +37 -0
- package/dist/src/catalog/visibility.d.ts.map +1 -0
- package/dist/src/command-line/build-cli.d.ts +7 -0
- package/dist/src/command-line/build-cli.d.ts.map +1 -0
- package/dist/src/command-line/cli.d.ts +13 -0
- package/dist/src/command-line/cli.d.ts.map +1 -0
- package/dist/src/command-line/commands/add.d.ts +10 -0
- package/dist/src/command-line/commands/add.d.ts.map +1 -0
- package/dist/src/command-line/commands/ai.d.ts +10 -0
- package/dist/src/command-line/commands/ai.d.ts.map +1 -0
- package/dist/src/command-line/commands/blocks.d.ts +10 -0
- package/dist/src/command-line/commands/blocks.d.ts.map +1 -0
- package/dist/src/command-line/commands/doc.d.ts +14 -0
- package/dist/src/command-line/commands/doc.d.ts.map +1 -0
- package/dist/src/command-line/commands/init.d.ts +18 -0
- package/dist/src/command-line/commands/init.d.ts.map +1 -0
- package/dist/src/command-line/commands/ls.d.ts +10 -0
- package/dist/src/command-line/commands/ls.d.ts.map +1 -0
- package/dist/src/command-line/commands/migrate.d.ts +10 -0
- package/dist/src/command-line/commands/migrate.d.ts.map +1 -0
- package/dist/src/command-line/utils/config.d.ts +42 -0
- package/dist/src/command-line/utils/config.d.ts.map +1 -0
- package/dist/src/command-line/utils/transformer.d.ts +21 -0
- package/dist/src/command-line/utils/transformer.d.ts.map +1 -0
- package/dist/src/components/ai-actions/ai-actions.d.ts +35 -0
- package/dist/src/components/ai-actions/ai-actions.d.ts.map +1 -0
- package/dist/src/components/ai-actions/index.d.ts +2 -0
- package/dist/src/components/ai-actions/index.d.ts.map +1 -0
- package/dist/src/components/ai-agent-card/ai-agent-card.d.ts +82 -0
- package/dist/src/components/ai-agent-card/ai-agent-card.d.ts.map +1 -0
- package/dist/src/components/ai-agent-card/index.d.ts +2 -0
- package/dist/src/components/ai-agent-card/index.d.ts.map +1 -0
- package/dist/src/components/ai-approval/ai-approval.d.ts +102 -0
- package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -0
- package/dist/src/components/ai-approval/index.d.ts +2 -0
- package/dist/src/components/ai-approval/index.d.ts.map +1 -0
- package/dist/src/components/ai-code-block/ai-code-block.d.ts +48 -0
- package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -0
- package/dist/src/components/ai-code-block/index.d.ts +2 -0
- package/dist/src/components/ai-code-block/index.d.ts.map +1 -0
- package/dist/src/components/ai-conversation/ai-conversation.d.ts +125 -0
- package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -0
- package/dist/src/components/ai-conversation/index.d.ts +2 -0
- package/dist/src/components/ai-conversation/index.d.ts.map +1 -0
- package/dist/src/components/ai-info-banner/ai-info-banner.d.ts +55 -0
- package/dist/src/components/ai-info-banner/ai-info-banner.d.ts.map +1 -0
- package/dist/src/components/ai-info-banner/index.d.ts +2 -0
- package/dist/src/components/ai-info-banner/index.d.ts.map +1 -0
- package/dist/src/components/ai-loader/ai-loader.d.ts +44 -0
- package/dist/src/components/ai-loader/ai-loader.d.ts.map +1 -0
- package/dist/src/components/ai-loader/index.d.ts +2 -0
- package/dist/src/components/ai-loader/index.d.ts.map +1 -0
- package/dist/src/components/ai-message/ai-message.d.ts +97 -0
- package/dist/src/components/ai-message/ai-message.d.ts.map +1 -0
- package/dist/src/components/ai-message/index.d.ts +2 -0
- package/dist/src/components/ai-message/index.d.ts.map +1 -0
- package/dist/src/components/ai-mission-header/ai-mission-header.d.ts +62 -0
- package/dist/src/components/ai-mission-header/ai-mission-header.d.ts.map +1 -0
- package/dist/src/components/ai-mission-header/index.d.ts +2 -0
- package/dist/src/components/ai-mission-header/index.d.ts.map +1 -0
- package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +260 -0
- package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -0
- package/dist/src/components/ai-prompt-input/index.d.ts +2 -0
- package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -0
- package/dist/src/components/ai-question/ai-question.d.ts +73 -0
- package/dist/src/components/ai-question/ai-question.d.ts.map +1 -0
- package/dist/src/components/ai-question/index.d.ts +2 -0
- package/dist/src/components/ai-question/index.d.ts.map +1 -0
- package/dist/src/components/ai-reasoning/ai-reasoning.d.ts +107 -0
- package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -0
- package/dist/src/components/ai-reasoning/index.d.ts +2 -0
- package/dist/src/components/ai-reasoning/index.d.ts.map +1 -0
- package/dist/src/components/ai-response/ai-response.d.ts +26 -0
- package/dist/src/components/ai-response/ai-response.d.ts.map +1 -0
- package/dist/src/components/ai-response/index.d.ts +2 -0
- package/dist/src/components/ai-response/index.d.ts.map +1 -0
- package/dist/src/components/ai-shimmer/ai-shimmer.d.ts +29 -0
- package/dist/src/components/ai-shimmer/ai-shimmer.d.ts.map +1 -0
- package/dist/src/components/ai-shimmer/index.d.ts +2 -0
- package/dist/src/components/ai-shimmer/index.d.ts.map +1 -0
- package/dist/src/components/ai-status-badge/ai-status-badge.d.ts +46 -0
- package/dist/src/components/ai-status-badge/ai-status-badge.d.ts.map +1 -0
- package/dist/src/components/ai-status-badge/index.d.ts +2 -0
- package/dist/src/components/ai-status-badge/index.d.ts.map +1 -0
- package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts +27 -0
- package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts.map +1 -0
- package/dist/src/components/ai-streaming-text/index.d.ts +2 -0
- package/dist/src/components/ai-streaming-text/index.d.ts.map +1 -0
- package/dist/src/components/ai-subagent/ai-subagent.d.ts +74 -0
- package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -0
- package/dist/src/components/ai-subagent/index.d.ts +2 -0
- package/dist/src/components/ai-subagent/index.d.ts.map +1 -0
- package/dist/src/components/ai-suggestion/ai-suggestion.d.ts +40 -0
- package/dist/src/components/ai-suggestion/ai-suggestion.d.ts.map +1 -0
- package/dist/src/components/ai-suggestion/index.d.ts +2 -0
- package/dist/src/components/ai-suggestion/index.d.ts.map +1 -0
- package/dist/src/components/ai-task-list/ai-task-list.d.ts +61 -0
- package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -0
- package/dist/src/components/ai-task-list/index.d.ts +2 -0
- package/dist/src/components/ai-task-list/index.d.ts.map +1 -0
- package/dist/src/components/ai-timeline/ai-timeline.d.ts +130 -0
- package/dist/src/components/ai-timeline/ai-timeline.d.ts.map +1 -0
- package/dist/src/components/ai-timeline/index.d.ts +2 -0
- package/dist/src/components/ai-timeline/index.d.ts.map +1 -0
- package/dist/src/components/ai-tool/ai-tool.d.ts +138 -0
- package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -0
- package/dist/src/components/ai-tool/index.d.ts +2 -0
- package/dist/src/components/ai-tool/index.d.ts.map +1 -0
- package/dist/src/components/ai-usage-bar/ai-usage-bar.d.ts +38 -0
- package/dist/src/components/ai-usage-bar/ai-usage-bar.d.ts.map +1 -0
- package/dist/src/components/ai-usage-bar/index.d.ts +2 -0
- package/dist/src/components/ai-usage-bar/index.d.ts.map +1 -0
- package/dist/src/components/badge/badge.d.ts +129 -0
- package/dist/src/components/badge/badge.d.ts.map +1 -0
- package/dist/src/components/badge/index.d.ts +2 -0
- package/dist/src/components/badge/index.d.ts.map +1 -0
- package/dist/src/components/banner/banner.d.ts +80 -0
- package/dist/src/components/banner/banner.d.ts.map +1 -0
- package/dist/src/components/banner/index.d.ts +2 -0
- package/dist/src/components/banner/index.d.ts.map +1 -0
- package/dist/src/components/breadcrumbs/breadcrumbs.d.ts +78 -0
- package/dist/src/components/breadcrumbs/breadcrumbs.d.ts.map +1 -0
- package/dist/src/components/breadcrumbs/index.d.ts +2 -0
- package/dist/src/components/breadcrumbs/index.d.ts.map +1 -0
- package/dist/src/components/button/button.d.ts +212 -0
- package/dist/src/components/button/button.d.ts.map +1 -0
- package/dist/src/components/button/index.d.ts +2 -0
- package/dist/src/components/button/index.d.ts.map +1 -0
- package/dist/src/components/chart/color.d.ts +98 -0
- package/dist/src/components/chart/color.d.ts.map +1 -0
- package/dist/src/components/chart/echart.d.ts +135 -0
- package/dist/src/components/chart/echart.d.ts.map +1 -0
- package/dist/src/components/chart/index.d.ts +5 -0
- package/dist/src/components/chart/index.d.ts.map +1 -0
- package/dist/src/components/chart/legend.d.ts +42 -0
- package/dist/src/components/chart/legend.d.ts.map +1 -0
- package/dist/src/components/chart/timeseries-chart.d.ts +119 -0
- package/dist/src/components/chart/timeseries-chart.d.ts.map +1 -0
- package/dist/src/components/checkbox/checkbox.d.ts +174 -0
- package/dist/src/components/checkbox/checkbox.d.ts.map +1 -0
- package/dist/src/components/checkbox/index.d.ts +2 -0
- package/dist/src/components/checkbox/index.d.ts.map +1 -0
- package/dist/src/components/clipboard-text/clipboard-text.d.ts +86 -0
- package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -0
- package/dist/src/components/clipboard-text/index.d.ts +2 -0
- package/dist/src/components/clipboard-text/index.d.ts.map +1 -0
- package/dist/src/components/code/code.d.ts +165 -0
- package/dist/src/components/code/code.d.ts.map +1 -0
- package/dist/src/components/code/index.d.ts +4 -0
- package/dist/src/components/code/index.d.ts.map +1 -0
- package/dist/src/components/collapsible/collapsible.d.ts +72 -0
- package/dist/src/components/collapsible/collapsible.d.ts.map +1 -0
- package/dist/src/components/collapsible/index.d.ts +2 -0
- package/dist/src/components/collapsible/index.d.ts.map +1 -0
- package/dist/src/components/combobox/combobox.d.ts +188 -0
- package/dist/src/components/combobox/combobox.d.ts.map +1 -0
- package/dist/src/components/combobox/index.d.ts +2 -0
- package/dist/src/components/combobox/index.d.ts.map +1 -0
- package/dist/src/components/command-palette/command-palette.d.ts +260 -0
- package/dist/src/components/command-palette/command-palette.d.ts.map +1 -0
- package/dist/src/components/command-palette/index.d.ts +3 -0
- package/dist/src/components/command-palette/index.d.ts.map +1 -0
- package/dist/src/components/command-palette/types.d.ts +149 -0
- package/dist/src/components/command-palette/types.d.ts.map +1 -0
- package/dist/src/components/data-grid/data-grid.d.ts +78 -0
- package/dist/src/components/data-grid/data-grid.d.ts.map +1 -0
- package/dist/src/components/data-grid/index.d.ts +3 -0
- package/dist/src/components/data-grid/index.d.ts.map +1 -0
- package/dist/src/components/data-grid/types.d.ts +236 -0
- package/dist/src/components/data-grid/types.d.ts.map +1 -0
- package/dist/src/components/date-picker/date-picker.d.ts +65 -0
- package/dist/src/components/date-picker/date-picker.d.ts.map +1 -0
- package/dist/src/components/date-picker/index.d.ts +4 -0
- package/dist/src/components/date-picker/index.d.ts.map +1 -0
- package/dist/src/components/date-range-picker/date-range-picker.d.ts +125 -0
- package/dist/src/components/date-range-picker/date-range-picker.d.ts.map +1 -0
- package/dist/src/components/date-range-picker/index.d.ts +5 -0
- package/dist/src/components/date-range-picker/index.d.ts.map +1 -0
- package/dist/src/components/dialog/dialog.d.ts +189 -0
- package/dist/src/components/dialog/dialog.d.ts.map +1 -0
- package/dist/src/components/dialog/index.d.ts +2 -0
- package/dist/src/components/dialog/index.d.ts.map +1 -0
- package/dist/src/components/dropdown/dropdown.d.ts +91 -0
- package/dist/src/components/dropdown/dropdown.d.ts.map +1 -0
- package/dist/src/components/dropdown/index.d.ts +2 -0
- package/dist/src/components/dropdown/index.d.ts.map +1 -0
- package/dist/src/components/empty/empty.d.ts +69 -0
- package/dist/src/components/empty/empty.d.ts.map +1 -0
- package/dist/src/components/empty/index.d.ts +2 -0
- package/dist/src/components/empty/index.d.ts.map +1 -0
- package/dist/src/components/field/field.d.ts +68 -0
- package/dist/src/components/field/field.d.ts.map +1 -0
- package/dist/src/components/field/index.d.ts +2 -0
- package/dist/src/components/field/index.d.ts.map +1 -0
- package/dist/src/components/filters/filters.d.ts +54 -0
- package/dist/src/components/filters/filters.d.ts.map +1 -0
- package/dist/src/components/filters/helpers.d.ts +56 -0
- package/dist/src/components/filters/helpers.d.ts.map +1 -0
- package/dist/src/components/filters/index.d.ts +3 -0
- package/dist/src/components/filters/index.d.ts.map +1 -0
- package/dist/src/components/filters/types.d.ts +148 -0
- package/dist/src/components/filters/types.d.ts.map +1 -0
- package/dist/src/components/flow/connectors.d.ts +35 -0
- package/dist/src/components/flow/connectors.d.ts.map +1 -0
- package/dist/src/components/flow/diagram.d.ts +62 -0
- package/dist/src/components/flow/diagram.d.ts.map +1 -0
- package/dist/src/components/flow/index.d.ts +26 -0
- package/dist/src/components/flow/index.d.ts.map +1 -0
- package/dist/src/components/flow/node.d.ts +52 -0
- package/dist/src/components/flow/node.d.ts.map +1 -0
- package/dist/src/components/flow/parallel.d.ts +5 -0
- package/dist/src/components/flow/parallel.d.ts.map +1 -0
- package/dist/src/components/flow/use-children.d.ts +69 -0
- package/dist/src/components/flow/use-children.d.ts.map +1 -0
- package/dist/src/components/grid/grid.d.ts +135 -0
- package/dist/src/components/grid/grid.d.ts.map +1 -0
- package/dist/src/components/grid/index.d.ts +2 -0
- package/dist/src/components/grid/index.d.ts.map +1 -0
- package/dist/src/components/input/index.d.ts +4 -0
- package/dist/src/components/input/index.d.ts.map +1 -0
- package/dist/src/components/input/input-area.d.ts +65 -0
- package/dist/src/components/input/input-area.d.ts.map +1 -0
- package/dist/src/components/input/input-group.d.ts +39 -0
- package/dist/src/components/input/input-group.d.ts.map +1 -0
- package/dist/src/components/input/input.d.ts +172 -0
- package/dist/src/components/input/input.d.ts.map +1 -0
- package/dist/src/components/label/index.d.ts +2 -0
- package/dist/src/components/label/index.d.ts.map +1 -0
- package/dist/src/components/label/label.d.ts +67 -0
- package/dist/src/components/label/label.d.ts.map +1 -0
- package/dist/src/components/layer-card/index.d.ts +2 -0
- package/dist/src/components/layer-card/index.d.ts.map +1 -0
- package/dist/src/components/layer-card/layer-card.d.ts +29 -0
- package/dist/src/components/layer-card/layer-card.d.ts.map +1 -0
- package/dist/src/components/link/index.d.ts +2 -0
- package/dist/src/components/link/index.d.ts.map +1 -0
- package/dist/src/components/link/link.d.ts +55 -0
- package/dist/src/components/link/link.d.ts.map +1 -0
- package/dist/src/components/loader/index.d.ts +3 -0
- package/dist/src/components/loader/index.d.ts.map +1 -0
- package/dist/src/components/loader/loader.d.ts +65 -0
- package/dist/src/components/loader/loader.d.ts.map +1 -0
- package/dist/src/components/loader/skeleton-line.d.ts +10 -0
- package/dist/src/components/loader/skeleton-line.d.ts.map +1 -0
- package/dist/src/components/menubar/index.d.ts +3 -0
- package/dist/src/components/menubar/index.d.ts.map +1 -0
- package/dist/src/components/menubar/menubar.d.ts +66 -0
- package/dist/src/components/menubar/menubar.d.ts.map +1 -0
- package/dist/src/components/menubar/use-menu-navigation.d.ts +8 -0
- package/dist/src/components/menubar/use-menu-navigation.d.ts.map +1 -0
- package/dist/src/components/meter/index.d.ts +2 -0
- package/dist/src/components/meter/index.d.ts.map +1 -0
- package/dist/src/components/meter/meter.d.ts +44 -0
- package/dist/src/components/meter/meter.d.ts.map +1 -0
- package/dist/src/components/pagination/index.d.ts +2 -0
- package/dist/src/components/pagination/index.d.ts.map +1 -0
- package/dist/src/components/pagination/pagination.d.ts +60 -0
- package/dist/src/components/pagination/pagination.d.ts.map +1 -0
- package/dist/src/components/popover/index.d.ts +3 -0
- package/dist/src/components/popover/index.d.ts.map +1 -0
- package/dist/src/components/popover/popover.d.ts +138 -0
- package/dist/src/components/popover/popover.d.ts.map +1 -0
- package/dist/src/components/radio/index.d.ts +2 -0
- package/dist/src/components/radio/index.d.ts.map +1 -0
- package/dist/src/components/radio/radio.d.ts +163 -0
- package/dist/src/components/radio/radio.d.ts.map +1 -0
- package/dist/src/components/select/index.d.ts +2 -0
- package/dist/src/components/select/index.d.ts.map +1 -0
- package/dist/src/components/select/select.d.ts +150 -0
- package/dist/src/components/select/select.d.ts.map +1 -0
- package/dist/src/components/sensitive-input/index.d.ts +2 -0
- package/dist/src/components/sensitive-input/index.d.ts.map +1 -0
- package/dist/src/components/sensitive-input/sensitive-input.d.ts +94 -0
- package/dist/src/components/sensitive-input/sensitive-input.d.ts.map +1 -0
- package/dist/src/components/sidebar/index.d.ts +2 -0
- package/dist/src/components/sidebar/index.d.ts.map +1 -0
- package/dist/src/components/sidebar/sidebar.d.ts +556 -0
- package/dist/src/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/src/components/signalflare-ai-logo/index.d.ts +2 -0
- package/dist/src/components/signalflare-ai-logo/index.d.ts.map +1 -0
- package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts +171 -0
- package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -0
- package/dist/src/components/surface/index.d.ts +2 -0
- package/dist/src/components/surface/index.d.ts.map +1 -0
- package/dist/src/components/surface/surface.d.ts +60 -0
- package/dist/src/components/surface/surface.d.ts.map +1 -0
- package/dist/src/components/switch/index.d.ts +2 -0
- package/dist/src/components/switch/index.d.ts.map +1 -0
- package/dist/src/components/switch/switch.d.ts +169 -0
- package/dist/src/components/switch/switch.d.ts.map +1 -0
- package/dist/src/components/table/index.d.ts +2 -0
- package/dist/src/components/table/index.d.ts.map +1 -0
- package/dist/src/components/table/table.d.ts +89 -0
- package/dist/src/components/table/table.d.ts.map +1 -0
- package/dist/src/components/tabs/index.d.ts +3 -0
- package/dist/src/components/tabs/index.d.ts.map +1 -0
- package/dist/src/components/tabs/tabs.d.ts +105 -0
- package/dist/src/components/tabs/tabs.d.ts.map +1 -0
- package/dist/src/components/text/index.d.ts +2 -0
- package/dist/src/components/text/index.d.ts.map +1 -0
- package/dist/src/components/text/text.d.ts +181 -0
- package/dist/src/components/text/text.d.ts.map +1 -0
- package/dist/src/components/theme-toggle/index.d.ts +2 -0
- package/dist/src/components/theme-toggle/index.d.ts.map +1 -0
- package/dist/src/components/theme-toggle/theme-toggle.d.ts +68 -0
- package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -0
- package/dist/src/components/toast/index.d.ts +5 -0
- package/dist/src/components/toast/index.d.ts.map +1 -0
- package/dist/src/components/toast/toast.d.ts +152 -0
- package/dist/src/components/toast/toast.d.ts.map +1 -0
- package/dist/src/components/tooltip/index.d.ts +2 -0
- package/dist/src/components/tooltip/index.d.ts.map +1 -0
- package/dist/src/components/tooltip/tooltip.d.ts +82 -0
- package/dist/src/components/tooltip/tooltip.d.ts.map +1 -0
- package/dist/src/components/use-agent-harness/index.d.ts +2 -0
- package/dist/src/components/use-agent-harness/index.d.ts.map +1 -0
- package/dist/src/components/use-agent-harness/use-agent-harness.d.ts +642 -0
- package/dist/src/components/use-agent-harness/use-agent-harness.d.ts.map +1 -0
- package/dist/src/genui/genui.d.ts +17 -0
- package/dist/src/genui/genui.d.ts.map +1 -0
- package/dist/src/genui/index.d.ts +19 -0
- package/dist/src/genui/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +102 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/lib/utils.d.ts +2 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/primitives/accordion.d.ts +13 -0
- package/dist/src/primitives/accordion.d.ts.map +1 -0
- package/dist/src/primitives/alert-dialog.d.ts +13 -0
- package/dist/src/primitives/alert-dialog.d.ts.map +1 -0
- package/dist/src/primitives/autocomplete.d.ts +13 -0
- package/dist/src/primitives/autocomplete.d.ts.map +1 -0
- package/dist/src/primitives/avatar.d.ts +13 -0
- package/dist/src/primitives/avatar.d.ts.map +1 -0
- package/dist/src/primitives/button.d.ts +13 -0
- package/dist/src/primitives/button.d.ts.map +1 -0
- package/dist/src/primitives/checkbox-group.d.ts +13 -0
- package/dist/src/primitives/checkbox-group.d.ts.map +1 -0
- package/dist/src/primitives/checkbox.d.ts +13 -0
- package/dist/src/primitives/checkbox.d.ts.map +1 -0
- package/dist/src/primitives/collapsible.d.ts +13 -0
- package/dist/src/primitives/collapsible.d.ts.map +1 -0
- package/dist/src/primitives/combobox.d.ts +13 -0
- package/dist/src/primitives/combobox.d.ts.map +1 -0
- package/dist/src/primitives/context-menu.d.ts +13 -0
- package/dist/src/primitives/context-menu.d.ts.map +1 -0
- package/dist/src/primitives/csp-provider.d.ts +13 -0
- package/dist/src/primitives/csp-provider.d.ts.map +1 -0
- package/dist/src/primitives/dialog.d.ts +13 -0
- package/dist/src/primitives/dialog.d.ts.map +1 -0
- package/dist/src/primitives/direction-provider.d.ts +13 -0
- package/dist/src/primitives/direction-provider.d.ts.map +1 -0
- package/dist/src/primitives/drawer.d.ts +13 -0
- package/dist/src/primitives/drawer.d.ts.map +1 -0
- package/dist/src/primitives/field.d.ts +13 -0
- package/dist/src/primitives/field.d.ts.map +1 -0
- package/dist/src/primitives/fieldset.d.ts +13 -0
- package/dist/src/primitives/fieldset.d.ts.map +1 -0
- package/dist/src/primitives/form.d.ts +13 -0
- package/dist/src/primitives/form.d.ts.map +1 -0
- package/dist/src/primitives/index.d.ts +54 -0
- package/dist/src/primitives/index.d.ts.map +1 -0
- package/dist/src/primitives/input.d.ts +13 -0
- package/dist/src/primitives/input.d.ts.map +1 -0
- package/dist/src/primitives/menu.d.ts +13 -0
- package/dist/src/primitives/menu.d.ts.map +1 -0
- package/dist/src/primitives/menubar.d.ts +13 -0
- package/dist/src/primitives/menubar.d.ts.map +1 -0
- package/dist/src/primitives/meter.d.ts +13 -0
- package/dist/src/primitives/meter.d.ts.map +1 -0
- package/dist/src/primitives/navigation-menu.d.ts +13 -0
- package/dist/src/primitives/navigation-menu.d.ts.map +1 -0
- package/dist/src/primitives/number-field.d.ts +13 -0
- package/dist/src/primitives/number-field.d.ts.map +1 -0
- package/dist/src/primitives/popover.d.ts +13 -0
- package/dist/src/primitives/popover.d.ts.map +1 -0
- package/dist/src/primitives/preview-card.d.ts +13 -0
- package/dist/src/primitives/preview-card.d.ts.map +1 -0
- package/dist/src/primitives/progress.d.ts +13 -0
- package/dist/src/primitives/progress.d.ts.map +1 -0
- package/dist/src/primitives/radio-group.d.ts +13 -0
- package/dist/src/primitives/radio-group.d.ts.map +1 -0
- package/dist/src/primitives/radio.d.ts +13 -0
- package/dist/src/primitives/radio.d.ts.map +1 -0
- package/dist/src/primitives/scroll-area.d.ts +13 -0
- package/dist/src/primitives/scroll-area.d.ts.map +1 -0
- package/dist/src/primitives/select.d.ts +13 -0
- package/dist/src/primitives/select.d.ts.map +1 -0
- package/dist/src/primitives/separator.d.ts +13 -0
- package/dist/src/primitives/separator.d.ts.map +1 -0
- package/dist/src/primitives/slider.d.ts +13 -0
- package/dist/src/primitives/slider.d.ts.map +1 -0
- package/dist/src/primitives/switch.d.ts +13 -0
- package/dist/src/primitives/switch.d.ts.map +1 -0
- package/dist/src/primitives/tabs.d.ts +13 -0
- package/dist/src/primitives/tabs.d.ts.map +1 -0
- package/dist/src/primitives/toast.d.ts +13 -0
- package/dist/src/primitives/toast.d.ts.map +1 -0
- package/dist/src/primitives/toggle-group.d.ts +13 -0
- package/dist/src/primitives/toggle-group.d.ts.map +1 -0
- package/dist/src/primitives/toggle.d.ts +13 -0
- package/dist/src/primitives/toggle.d.ts.map +1 -0
- package/dist/src/primitives/toolbar.d.ts +13 -0
- package/dist/src/primitives/toolbar.d.ts.map +1 -0
- package/dist/src/primitives/tooltip.d.ts +13 -0
- package/dist/src/primitives/tooltip.d.ts.map +1 -0
- package/dist/src/registry/index.d.ts +8 -0
- package/dist/src/registry/index.d.ts.map +1 -0
- package/dist/src/registry/types.d.ts +191 -0
- package/dist/src/registry/types.d.ts.map +1 -0
- package/dist/src/utils/cn.d.ts +4 -0
- package/dist/src/utils/cn.d.ts.map +1 -0
- package/dist/src/utils/highlight-to-react.d.ts +12 -0
- package/dist/src/utils/highlight-to-react.d.ts.map +1 -0
- package/dist/src/utils/index.d.ts +3 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/link-provider.d.ts +12 -0
- package/dist/src/utils/link-provider.d.ts.map +1 -0
- package/dist/src/utils/prop-examples.d.ts +36 -0
- package/dist/src/utils/prop-examples.d.ts.map +1 -0
- package/dist/styles/sf-binding.css +255 -0
- package/dist/styles/sf-standalone.css +2 -0
- package/dist/styles/sf.css +596 -0
- package/dist/styles/theme-fedramp.css +22 -0
- package/dist/styles/theme-minimal.css +127 -0
- package/dist/styles/theme-navigator.css +137 -0
- package/dist/styles/theme-sf.css +191 -0
- package/dist/surface-BduI7Ehl.js +18 -0
- package/dist/surface-BduI7Ehl.js.map +1 -0
- package/dist/switch-CzZBRBL7.js +169 -0
- package/dist/switch-CzZBRBL7.js.map +1 -0
- package/dist/table-CIMx0Oq0.js +200 -0
- package/dist/table-CIMx0Oq0.js.map +1 -0
- package/dist/tabs-1cHrYoel.js +54 -0
- package/dist/tabs-1cHrYoel.js.map +1 -0
- package/dist/text-KJmGkwnf.js +103 -0
- package/dist/text-KJmGkwnf.js.map +1 -0
- package/dist/theme-toggle-Dpgnoj_Q.js +129 -0
- package/dist/theme-toggle-Dpgnoj_Q.js.map +1 -0
- package/dist/toast-Nw28a5Cx.js +161 -0
- package/dist/toast-Nw28a5Cx.js.map +1 -0
- package/dist/tooltip-Cb7QW-7H.js +79 -0
- package/dist/tooltip-Cb7QW-7H.js.map +1 -0
- package/dist/use-agent-harness-DZzcn96L.js +929 -0
- package/dist/use-agent-harness-DZzcn96L.js.map +1 -0
- package/dist/utils.js +4 -0
- package/package.json +620 -0
- package/scripts/component-registry/cache.ts +124 -0
- package/scripts/component-registry/discovery.ts +464 -0
- package/scripts/component-registry/example-cleanup.ts +168 -0
- package/scripts/component-registry/index.test.ts +678 -0
- package/scripts/component-registry/index.ts +931 -0
- package/scripts/component-registry/markdown-generator.ts +222 -0
- package/scripts/component-registry/metadata.ts +653 -0
- package/scripts/component-registry/props-filter.ts +313 -0
- package/scripts/component-registry/schema-generator.ts +332 -0
- package/scripts/component-registry/sub-components.ts +350 -0
- package/scripts/component-registry/types.ts +156 -0
- package/scripts/component-registry/utils.ts +280 -0
- package/scripts/component-registry/variant-parser.ts +262 -0
- package/scripts/css-build.ts +117 -0
- package/scripts/generate-primitives.ts +178 -0
- package/scripts/theme-generator/config.ts +538 -0
- package/scripts/theme-generator/generate-css.ts +256 -0
- package/scripts/theme-generator/index.ts +161 -0
- package/scripts/theme-generator/migrate.ts +584 -0
- package/scripts/theme-generator/types.ts +86 -0
- package/skills/component-selection/SKILL.md +64 -0
- package/skills/installing-blocks/SKILL.md +47 -0
- package/skills/theming-and-tokens/SKILL.md +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-prompt-input-Bo1YuJly.js","names":[],"sources":["../src/components/ai-prompt-input/ai-prompt-input.tsx"],"sourcesContent":["\"use client\";\n\nimport { Menu as DropdownMenuPrimitive } from \"@base-ui/react/menu\";\nimport {\n ArrowUpIcon,\n CaretDownIcon,\n FileIcon,\n FileTextIcon,\n ImageIcon,\n MicrophoneIcon,\n PaperclipIcon,\n PlusIcon,\n SpinnerGapIcon,\n SquareIcon,\n XIcon,\n} from \"@phosphor-icons/react\";\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n ComponentProps,\n FormEvent,\n FormEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from \"react\";\nimport {\n Fragment,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { InputGroup } from \"../input\";\nimport { Tooltip } from \"../tooltip\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_PROMPT_INPUT_VARIANTS = {\n status: {\n idle: { classes: \"\", description: \"Ready to accept input\" },\n submitted: {\n classes: \"\",\n description: \"Waiting for response (shows spinner)\",\n },\n streaming: { classes: \"\", description: \"Streaming response (shows stop)\" },\n error: { classes: \"\", description: \"Error state (shows X)\" },\n },\n} as const;\n\nexport const SF_AI_PROMPT_INPUT_DEFAULT_VARIANTS = {\n status: \"idle\",\n} as const;\n\nexport type SFAiPromptInputStatus =\n keyof typeof SF_AI_PROMPT_INPUT_VARIANTS.status;\n\n// ─── Attachment types ─────────────────────────────────────────────────────────\n\nexport type AttachmentFile = {\n id: string;\n url: string;\n mediaType: string;\n filename: string;\n};\n\nexport type AttachmentsContext = {\n files: AttachmentFile[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n};\n\n// ─── Provider Context & Types ─────────────────────────────────────────────────\n\nexport type TextInputContext = {\n value: string;\n setInput: (v: string) => void;\n clear: () => void;\n};\n\nexport type PromptInputController = {\n textInput: TextInputContext;\n attachments: AttachmentsContext;\n /** INTERNAL: Allows PromptInput to register its file input + \"open\" callback */\n __registerFileInput: (\n ref: RefObject<HTMLInputElement | null>,\n open: () => void\n ) => void;\n};\n\nconst PromptInputContext = createContext<PromptInputController | null>(null);\nconst ProviderAttachmentsContext = createContext<AttachmentsContext | null>(\n null\n);\n\nexport const usePromptInputController = () => {\n const ctx = useContext(PromptInputContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use usePromptInputController().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalPromptInputController = () => useContext(PromptInputContext);\n\nexport const useProviderAttachments = () => {\n const ctx = useContext(ProviderAttachmentsContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use useProviderAttachments().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalProviderAttachments = () =>\n useContext(ProviderAttachmentsContext);\n\n// ─── PromptInputProvider ──────────────────────────────────────────────────────\n\nexport type PromptInputProviderProps = PropsWithChildren<{\n initialInput?: string;\n}>;\n\n/**\n * Optional global provider that lifts PromptInput state outside of PromptInput.\n * If you don't use it, PromptInput stays fully self-managed.\n *\n * @example\n * ```tsx\n * <PromptInputProvider>\n * <PromptInput onSubmit={handleSubmit}>...</PromptInput>\n * </PromptInputProvider>\n * ```\n */\nexport function PromptInputProvider({\n initialInput = \"\",\n children,\n}: PromptInputProviderProps) {\n const [textInput, setTextInput] = useState(initialInput);\n const clearInput = useCallback(() => setTextInput(\"\"), []);\n\n const [attachmentItems, setAttachmentItems] = useState<AttachmentFile[]>([]);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n const openRef = useRef<() => void>(() => {});\n\n const add = useCallback((files: File[] | FileList) => {\n const incoming = Array.from(files);\n if (incoming.length === 0) return;\n setAttachmentItems((prev) =>\n prev.concat(\n incoming.map((file) => ({\n id: `${Date.now()}-${Math.random()}`,\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }))\n )\n );\n }, []);\n\n const remove = useCallback((id: string) => {\n setAttachmentItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachmentItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n }, []);\n\n const openFileDialog = useCallback(() => {\n openRef.current?.();\n }, []);\n\n const attachments = useMemo<AttachmentsContext>(\n () => ({\n files: attachmentItems,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef,\n }),\n [attachmentItems, add, remove, clear, openFileDialog]\n );\n\n const __registerFileInput = useCallback(\n (ref: RefObject<HTMLInputElement | null>, open: () => void) => {\n fileInputRef.current = ref.current;\n openRef.current = open;\n },\n []\n );\n\n const controller = useMemo<PromptInputController>(\n () => ({\n textInput: {\n value: textInput,\n setInput: setTextInput,\n clear: clearInput,\n },\n attachments,\n __registerFileInput,\n }),\n [textInput, clearInput, attachments, __registerFileInput]\n );\n\n return (\n <PromptInputContext.Provider value={controller}>\n <ProviderAttachmentsContext.Provider value={attachments}>\n {children}\n </ProviderAttachmentsContext.Provider>\n </PromptInputContext.Provider>\n );\n}\n\n// ─── Local Attachments Context ────────────────────────────────────────────────\n\nconst LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n const provider = useOptionalProviderAttachments();\n const local = useContext(LocalAttachmentsContext);\n const context = provider ?? local;\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput or PromptInputProvider\"\n );\n }\n return context;\n};\n\n// ─── Helpers (module-level) ───────────────────────────────────────────────────\n\n/** Convert a blob URL to a base64 data URL for serialization. */\nasync function convertBlobToDataUrl(url: string): Promise<string> {\n const response = await fetch(url);\n const blob = await response.blob();\n // FileReader is callback-only — no Promise-based API exists for this\n // oxlint-disable-next-line avoid-new\n return new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.addEventListener(\"loadend\", () => resolve(reader.result as string));\n reader.addEventListener(\"error\", () =>\n reject(new Error(\"FileReader error\"))\n );\n reader.readAsDataURL(blob);\n });\n}\n\nfunction makeAttachmentId() {\n return `${Date.now()}-${Math.random()}`;\n}\n\n// ─── PromptInputMessage ───────────────────────────────────────────────────────\n\nexport type PromptInputMessage = {\n text?: string;\n files?: AttachmentFile[];\n};\n\n// ─── PromptInput ─────────────────────────────────────────────────────────────\n\nexport type PromptInputProps = Omit<\n HTMLAttributes<HTMLFormElement>,\n \"onSubmit\" | \"onError\"\n> & {\n /** Accepted file types — e.g. `\"image/*\"`. Default: any. */\n accept?: string;\n /** Allow selecting multiple files. */\n multiple?: boolean;\n /** When true, accept drops anywhere on document. Default false. */\n globalDrop?: boolean;\n /** Maximum number of attached files. */\n maxFiles?: number;\n /** Maximum file size in bytes. */\n maxFileSize?: number;\n onError?: (err: {\n code: \"max_files\" | \"max_file_size\" | \"accept\";\n message: string;\n }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>\n ) => void | Promise<void>;\n /**\n * Content rendered in the collapsible back layer (e.g. HITL approvals, task\n * lists). When provided the prompt input is wrapped in a LayerCard shell with\n * a header row containing a chevron toggle.\n * Use `PromptInputBackLayer` to compose structured content for this slot.\n */\n backLayer?: ReactNode;\n /**\n * Title shown in the back layer header row. Defaults to `\"Context\"`.\n */\n backLayerTitle?: string;\n /**\n * Controls whether the back layer is visible. Pair with `onBackLayerOpenChange`\n * for a controlled pattern.\n */\n backLayerOpen?: boolean;\n /** Called when the chevron toggle changes the back layer open state. */\n onBackLayerOpenChange?: (open: boolean) => void;\n /**\n * Automatically opens the back layer when this condition is true.\n * Useful for showing pending approvals/questions without manual toggle.\n */\n autoOpenBackLayerWhen?: boolean;\n};\n\n/**\n * Prompt input form. Can be self-managed or controlled via `PromptInputProvider`.\n *\n * @example\n * ```tsx\n * <PromptInput onSubmit={({ text, files }) => send(text, files)}>\n * <PromptInputAttachments>{(f) => <PromptInputAttachment data={f} />}</PromptInputAttachments>\n * <PromptInputTextarea placeholder=\"Ask anything…\" />\n * <PromptInputToolbar>\n * <PromptInputTools>\n * <PromptInputAttachButton />\n * </PromptInputTools>\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport const PromptInput = ({\n className,\n accept,\n multiple,\n globalDrop,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n children,\n backLayer,\n backLayerTitle = \"Context\",\n backLayerOpen,\n onBackLayerOpenChange,\n autoOpenBackLayerWhen,\n ...props\n}: PromptInputProps) => {\n const hasBackLayer = backLayer !== undefined;\n const controller = useOptionalPromptInputController();\n const usingProvider = !!controller;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLSpanElement>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n\n useEffect(() => {\n const root = anchorRef.current?.closest(\"form\");\n if (root instanceof HTMLFormElement) {\n formRef.current = root;\n }\n }, []);\n\n // Auto-open back layer when condition is true\n useEffect(() => {\n if (autoOpenBackLayerWhen) {\n onBackLayerOpenChange?.(true);\n }\n }, [autoOpenBackLayerWhen, onBackLayerOpenChange]);\n\n // Local attachment state (only when no provider)\n const [items, setItems] = useState<AttachmentFile[]>([]);\n const files = usingProvider ? controller.attachments.files : items;\n\n const openFileDialogLocal = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") return true;\n if (accept.includes(\"image/*\")) return f.type.startsWith(\"image/\");\n return true;\n },\n [accept]\n );\n\n const addLocal = useCallback(\n (fileList: File[] | FileList) => {\n const incoming = Array.from(fileList);\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (incoming.length && accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: \"No files match the accepted types.\",\n });\n return;\n }\n const withinSize = (f: File) =>\n maxFileSize ? f.size <= maxFileSize : true;\n const sized = accepted.filter(withinSize);\n if (accepted.length > 0 && sized.length === 0) {\n onError?.({\n code: \"max_file_size\",\n message: \"All files exceed the maximum size.\",\n });\n return;\n }\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\"\n ? Math.max(0, maxFiles - prev.length)\n : undefined;\n const capped =\n typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: \"Too many files. Some were not added.\",\n });\n }\n const next: AttachmentFile[] = capped.map((file) => ({\n id: makeAttachmentId(),\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }));\n return prev.concat(next);\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError]\n );\n\n const add = usingProvider\n ? (f: File[] | FileList) => controller.attachments.add(f)\n : addLocal;\n\n const remove = usingProvider\n ? (id: string) => controller.attachments.remove(id)\n : (id: string) =>\n setItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n\n const clear = usingProvider\n ? () => controller.attachments.clear()\n : () =>\n setItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n\n const openFileDialog = usingProvider\n ? () => controller.attachments.openFileDialog()\n : openFileDialogLocal;\n\n useEffect(() => {\n if (!usingProvider) return;\n controller.__registerFileInput(inputRef, () => inputRef.current?.click());\n }, [usingProvider, controller]);\n\n // File drag-drop on the form\n useEffect(() => {\n const form = formRef.current;\n if (!form) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add]);\n\n useEffect(() => {\n if (!globalDrop) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0)\n add(e.dataTransfer.files);\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n // Cleanup blob URLs on unmount (local mode only)\n useEffect(() => {\n return () => {\n if (!usingProvider) {\n for (const f of files) if (f.url) URL.revokeObjectURL(f.url);\n }\n };\n }, [usingProvider, files]);\n\n const handleFileInputChange: ChangeEventHandler<HTMLInputElement> = (\n event\n ) => {\n if (event.currentTarget.files) add(event.currentTarget.files);\n };\n\n const ctx = useMemo<AttachmentsContext>(\n () => ({\n files,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef: inputRef,\n }),\n [files, add, remove, clear, openFileDialog]\n );\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n const form = event.currentTarget;\n const text = usingProvider\n ? controller.textInput.value\n : (() => {\n const formData = new FormData(form);\n return (formData.get(\"message\") as string) || \"\";\n })();\n\n if (!usingProvider) form.reset();\n\n const doSubmit = async () => {\n const convertedFiles = await Promise.all(\n files.map(async (item) => {\n if (item.url.startsWith(\"blob:\")) {\n return { ...item, url: await convertBlobToDataUrl(item.url) };\n }\n return item;\n })\n );\n\n try {\n await onSubmit({ text, files: convertedFiles }, event);\n clear();\n if (usingProvider) controller.textInput.clear();\n } catch {\n // Don't clear on error — user may want to retry\n }\n };\n\n doSubmit().catch(() => {});\n };\n\n const isBackLayerOpen = backLayerOpen ?? false;\n\n const inputShell = hasBackLayer ? (\n // LayerCard-style shell: elevated outer card with header + collapsible back\n // layer + primary layer housing the actual input.\n <div className=\"flex w-full flex-col overflow-hidden rounded-xl bg-sf-elevated ring ring-sf-line/50\">\n {/* Header row — always visible, contains title + chevron toggle */}\n <button\n aria-expanded={isBackLayerOpen}\n aria-label={isBackLayerOpen ? \"Collapse context\" : \"Expand context\"}\n className=\"flex w-full items-center justify-between gap-2 px-3 py-2 text-left\"\n onClick={() => onBackLayerOpenChange?.(!isBackLayerOpen)}\n type=\"button\"\n >\n <span className=\"text-sm font-medium text-sf-subtle uppercase tracking-wide select-none\">\n {backLayerTitle}\n </span>\n <CaretDownIcon\n className={cn(\n \"size-3.5 text-sf-subtle transition-transform duration-200\",\n isBackLayerOpen && \"rotate-180\"\n )}\n />\n </button>\n {/* Collapsible back layer content */}\n <PromptInputBackLayerPanel open={isBackLayerOpen}>\n {backLayer}\n </PromptInputBackLayerPanel>\n {/* Primary layer — the input itself, visually raised off the back layer */}\n <div className=\"flex flex-col overflow-hidden rounded-xl bg-sf-base ring ring-sf-line/50 focus-within:ring-sf-ring\">\n {children}\n </div>\n </div>\n ) : (\n <InputGroup>{children}</InputGroup>\n );\n\n const inner = (\n <>\n <span aria-hidden=\"true\" className=\"hidden\" ref={anchorRef} />\n <input\n accept={accept}\n aria-label=\"Upload files\"\n className=\"hidden\"\n multiple={multiple}\n onChange={handleFileInputChange}\n ref={inputRef}\n type=\"file\"\n />\n <form\n className={cn(\"w-full\", className)}\n onSubmit={handleSubmit}\n {...props}\n >\n {inputShell}\n </form>\n </>\n );\n\n return usingProvider ? (\n inner\n ) : (\n <LocalAttachmentsContext.Provider value={ctx}>\n {inner}\n </LocalAttachmentsContext.Provider>\n );\n};\n\n// ─── PromptInputBody ──────────────────────────────────────────────────────────\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n className,\n ...props\n}: PromptInputBodyProps) => (\n <div className={cn(\"contents\", className)} {...props} />\n);\n\n// ─── PromptInputBackLayerPanel (internal) ─────────────────────────────────────\n// Grid-rows animation: collapses to 0fr when closed, expands to 1fr when open.\n\ntype PromptInputBackLayerPanelProps = PropsWithChildren<{\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}>;\n\nfunction PromptInputBackLayerPanel({\n open,\n children,\n}: PromptInputBackLayerPanelProps) {\n const isOpen = open ?? false;\n\n return (\n <div\n aria-hidden={!isOpen}\n className=\"grid\"\n style={{\n gridTemplateRows: isOpen ? \"1fr\" : \"0fr\",\n opacity: isOpen ? 1 : 0,\n transition: \"grid-template-rows 200ms ease-out, opacity 200ms ease-out\",\n }}\n >\n {/* min-h-0 lets the grid row collapse to 0 */}\n <div className=\"min-h-0 overflow-hidden\">{children}</div>\n </div>\n );\n}\n\n// ─── PromptInputBackLayer (public) ────────────────────────────────────────────\n\nexport type PromptInputBackLayerProps = PropsWithChildren<{\n className?: string;\n}>;\n\n/**\n * Container for back-layer content (HITL approvals, task lists, agent status,\n * etc.). Pass instances of this as the `backLayer` prop on `PromptInput`.\n *\n * @example\n * ```tsx\n * <PromptInput\n * onSubmit={handleSubmit}\n * backLayer={<PromptInputBackLayer>...</PromptInputBackLayer>}\n * backLayerOpen={open}\n * onBackLayerOpenChange={setOpen}\n * >\n * <PromptInputTextarea />\n * <PromptInputToolbar>\n * <PromptInputTools />\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport function PromptInputBackLayer({\n children,\n className,\n}: PromptInputBackLayerProps) {\n return (\n <div\n className={cn(\n \"flex flex-col gap-2 px-3 py-2.5 text-sm text-sf-default\",\n className\n )}\n >\n {children}\n </div>\n );\n}\n\n// ─── Textarea helpers (module-level) ──────────────────────────────────────────\n\nconst handleTextareaKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (\n e\n) => {\n if (e.key === \"Enter\") {\n if (e.nativeEvent.isComposing) return;\n if (e.shiftKey) return;\n e.preventDefault();\n e.currentTarget.form?.requestSubmit();\n }\n};\n\n// ─── PromptInputTextarea ──────────────────────────────────────────────────────\n\nexport type PromptInputTextareaProps = ComponentProps<\"textarea\"> & {\n placeholder?: string;\n};\n\n/**\n * Auto-resizing textarea for the prompt. Submits on Enter (Shift+Enter for newline).\n * Pastes files into attachments.\n */\nexport const PromptInputTextarea = ({\n onChange,\n className,\n placeholder = \"What would you like to know?\",\n ...props\n}: PromptInputTextareaProps) => {\n const controller = useOptionalPromptInputController();\n const attachments = usePromptInputAttachments();\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const pastedFiles: File[] = [];\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) pastedFiles.push(file);\n }\n }\n if (pastedFiles.length > 0) {\n event.preventDefault();\n attachments.add(pastedFiles);\n }\n };\n\n const controlledProps = controller\n ? {\n value: controller.textInput.value,\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n controller.textInput.setInput(e.currentTarget.value);\n onChange?.(e);\n },\n }\n : { onChange };\n\n return (\n <textarea\n className={cn(\n \"field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 py-2 text-sm text-sf-default outline-none placeholder:text-sf-inactive\",\n className\n )}\n name=\"message\"\n onKeyDown={handleTextareaKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n rows={1}\n {...props}\n {...controlledProps}\n />\n );\n};\n\n// ─── PromptInputToolbar ───────────────────────────────────────────────────────\n\nexport type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputToolbar = ({\n className,\n ...props\n}: PromptInputToolbarProps) => (\n <div\n className={cn(\n \"flex items-center justify-between gap-1 px-2 py-1.5\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputTools ─────────────────────────────────────────────────────────\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n className,\n ...props\n}: PromptInputToolsProps) => (\n <div className={cn(\"flex items-center gap-1\", className)} {...props} />\n);\n\n// ─── PromptInputButton ────────────────────────────────────────────────────────\n\nexport type PromptInputButtonProps = ComponentProps<typeof Button> & {\n \"aria-label\": string;\n};\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n size = \"sm\",\n className,\n ...props\n}: PromptInputButtonProps) => (\n <Button\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n />\n);\n\n// ─── PromptInputSubmit ────────────────────────────────────────────────────────\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n status?: SFAiPromptInputStatus;\n};\n\n/**\n * Submit button. Icon changes based on `status`:\n * - `idle` → send arrow\n * - `submitted` → spinner\n * - `streaming` → stop square\n * - `error` → X\n */\nexport const PromptInputSubmit = ({\n className,\n variant = \"primary\",\n size = \"sm\",\n status = \"idle\",\n children,\n ...props\n}: PromptInputSubmitProps) => {\n let Icon: ReactNode;\n if (status === \"submitted\") {\n Icon = <SpinnerGapIcon className=\"size-4 animate-spin\" />;\n } else if (status === \"streaming\") {\n Icon = <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n } else {\n Icon = <ArrowUpIcon className=\"size-4\" />;\n }\n\n return (\n <Button\n aria-label=\"Submit\"\n className={cn(className)}\n size={size}\n type=\"submit\"\n variant={variant}\n {...props}\n >\n {children ?? Icon}\n </Button>\n );\n};\n\n// ─── PromptInputActionMenu ────────────────────────────────────────────────────\n\nconst DropdownMenu = DropdownMenuPrimitive;\n\nexport type PromptInputActionMenuProps = ComponentProps<\n typeof DropdownMenu.Root\n>;\n\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu.Root {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n \"aria-label\": ariaLabel = \"More actions\",\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenu.Trigger\n render={\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <PlusIcon className=\"size-4\" />}\n </Button>\n }\n />\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<\n typeof DropdownMenu.Positioner\n> & { className?: string; children?: ReactNode };\n\nexport const PromptInputActionMenuContent = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenu.Positioner className=\"z-50\" side=\"top\" align=\"start\" {...props}>\n <DropdownMenu.Popup\n className={cn(\n \"min-w-[160px] rounded-lg bg-sf-elevated p-1 shadow-md\",\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 transition-opacity duration-100\",\n className\n )}\n >\n {children}\n </DropdownMenu.Popup>\n </DropdownMenu.Positioner>\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<\n typeof DropdownMenu.Item\n>;\n\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => (\n <DropdownMenu.Item\n className={cn(\n \"flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sf-default outline-none\",\n \"data-highlighted:bg-sf-tint\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputActionAddAttachments ─────────────────────────────────────────\n\nexport type PromptInputActionAddAttachmentsProps =\n PromptInputActionMenuItemProps & {\n label?: string;\n };\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n const handleSelect = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <PromptInputActionMenuItem {...props} onSelect={handleSelect}>\n <ImageIcon className=\"size-4\" />\n {label}\n </PromptInputActionMenuItem>\n );\n};\n\n// ─── PromptInputModeSelector ───────────────────────────────────────────────────\n\nexport type PromptInputModeSelectorProps = {\n modes: { modeId: string; modeName: string }[];\n value?: string;\n onChange?: (modeId: string) => void;\n};\n\nexport const PromptInputModeSelector = ({\n modes,\n value,\n onChange,\n}: PromptInputModeSelectorProps) => {\n if (modes.length === 0) return null;\n\n const selectedMode = modes.find((m) => m.modeId === value);\n const displayName = selectedMode?.modeName ?? value ?? modes[0]?.modeName;\n\n return (\n <div\n className={cn(\"flex items-center gap-0.5 rounded-md bg-sf-tint p-0.5\")}\n role=\"group\"\n aria-label=\"Select mode\"\n >\n {modes.map((mode) => {\n const isSelected =\n mode.modeId === value || mode.modeName === displayName;\n return (\n <button\n key={mode.modeId}\n aria-pressed={isSelected}\n className={cn(\n \"cursor-pointer rounded-[4px] px-2 py-0.5 text-[11px] font-medium transition-colors\",\n isSelected\n ? \"bg-sf-elevated text-sf-default shadow-sm\"\n : \"text-sf-subtle hover:text-sf-default\"\n )}\n onClick={() => onChange?.(mode.modeId)}\n type=\"button\"\n >\n {mode.modeName}\n </button>\n );\n })}\n </div>\n );\n};\n\n// ─── Attachment display helpers ───────────────────────────────────────────────\n\nconst IMAGE_EXTS = new Set([\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"svg\"]);\n\nfunction getFileIcon(filename: string): ReactNode {\n const ext = filename.split(\".\").pop()?.toLowerCase() ?? \"\";\n if (IMAGE_EXTS.has(ext)) return <ImageIcon className=\"size-3.5\" />;\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"md\"].includes(ext))\n return <FileTextIcon className=\"size-3.5\" />;\n return <FileIcon className=\"size-3.5\" />;\n}\n\n// ─── PromptInputAttachment ────────────────────────────────────────────────────\n\nexport type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentFile;\n};\n\n/**\n * Single attachment chip for images or files. Includes a remove button.\n */\nexport function PromptInputAttachment({\n data,\n className,\n ...props\n}: PromptInputAttachmentProps) {\n const attachments = usePromptInputAttachments();\n const isImage = data.mediaType?.startsWith(\"image/\") && data.url;\n\n const handleRemove = useCallback(() => {\n attachments.remove(data.id);\n }, [attachments, data.id]);\n\n if (isImage) {\n return (\n <div\n className={cn(\n \"group relative size-14 overflow-hidden rounded-md\",\n className\n )}\n {...props}\n >\n <img\n alt={data.filename || \"attachment\"}\n className=\"size-full object-cover\"\n src={data.url}\n />\n <Button\n aria-label=\"Remove attachment\"\n className=\"absolute top-1 right-1 size-5 rounded-full bg-sf-overlay/80 p-0 opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n }\n\n const ext = data.filename.split(\".\").pop()?.toUpperCase() ?? \"FILE\";\n const name = data.filename.replace(/\\.[^/.]+$/, \"\");\n\n return (\n <div\n className={cn(\n \"group relative inline-flex h-8 items-center gap-2 rounded-md bg-sf-tint/50 px-2 text-sm\",\n className\n )}\n {...props}\n >\n <div className=\"flex size-5 shrink-0 items-center justify-center text-sf-subtle\">\n {getFileIcon(data.filename)}\n </div>\n <Tooltip content={data.filename}>\n <span className=\"max-w-[160px] truncate font-medium text-sf-default\">\n {name || \"File\"}\n </span>\n </Tooltip>\n <span className=\"rounded bg-sf-tint px-1 py-0.5 font-semibold text-sf-subtle text-[10px] uppercase\">\n {ext}\n </span>\n <Button\n aria-label=\"Remove attachment\"\n className=\"ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n}\n\n// ─── PromptInputAttachments ───────────────────────────────────────────────────\n\nexport type PromptInputAttachmentsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (attachment: AttachmentFile) => ReactNode;\n};\n\n/**\n * Renders all attachments using a render prop. Hidden when no files.\n * Animates height as files are added/removed.\n */\nexport function PromptInputAttachments({\n className,\n children,\n ...props\n}: PromptInputAttachmentsProps) {\n const attachments = usePromptInputAttachments();\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n // Re-measure when file count changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional re-measure on count change\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (el) setHeight(el.getBoundingClientRect().height);\n }, [attachments.files.length]);\n\n if (attachments.files.length === 0) return null;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden px-2 transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: attachments.files.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 py-1\" ref={contentRef}>\n {attachments.files.map((file) => (\n <Fragment key={file.id}>{children(file)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\n// ─── Speech recognition types ─────────────────────────────────────────────────\n\ntype SpeechRecognitionInstance = EventTarget & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n};\n\ntype SpeechRecognitionResultEvent = Event & {\n results: {\n readonly length: number;\n item(index: number): {\n isFinal: boolean;\n [i: number]: { transcript: string };\n };\n [index: number]: { isFinal: boolean; [i: number]: { transcript: string } };\n };\n};\n\ntype SpeechRecognitionConstructor = new () => SpeechRecognitionInstance;\n\ndeclare global {\n interface Window {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n }\n}\n\n// ─── PromptInputSpeechButton ──────────────────────────────────────────────────\n\nexport type PromptInputSpeechButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n textareaRef?: RefObject<HTMLTextAreaElement | null>;\n onTranscriptionChange?: (text: string) => void;\n};\n\n/**\n * Voice input button. Uses the Web Speech API (Chrome/Edge). Hidden on unsupported browsers.\n * Pulses while listening.\n */\nexport const PromptInputSpeechButton = ({\n className,\n textareaRef,\n onTranscriptionChange,\n \"aria-label\": ariaLabel = \"Voice input\",\n ...props\n}: PromptInputSpeechButtonProps) => {\n const [isListening, setIsListening] = useState(false);\n const [recognition, setRecognition] =\n useState<SpeechRecognitionInstance | null>(null);\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;\n if (!SR) return;\n\n const sr = new SR() as SpeechRecognitionInstance & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n };\n sr.continuous = true;\n sr.interimResults = true;\n sr.lang = \"en-US\";\n\n const handleStart = () => setIsListening(true);\n const handleEnd = () => setIsListening(false);\n const handleResult = (event: Event) => {\n const e = event as SpeechRecognitionResultEvent;\n let final = \"\";\n for (const result of Array.from(\n { length: e.results.length },\n (_, i) => e.results[i]\n )) {\n if (result?.isFinal && result[0]?.transcript) {\n final += result[0].transcript;\n }\n }\n if (final && textareaRef?.current) {\n const ta = textareaRef.current;\n const next = ta.value + (ta.value ? \" \" : \"\") + final;\n ta.value = next;\n ta.dispatchEvent(new Event(\"input\", { bubbles: true }));\n onTranscriptionChange?.(next);\n }\n };\n const handleError = (_event: Event) => setIsListening(false);\n\n sr.addEventListener(\"start\", handleStart);\n sr.addEventListener(\"end\", handleEnd);\n sr.addEventListener(\"result\", handleResult);\n sr.addEventListener(\"error\", handleError);\n\n recognitionRef.current = sr;\n setRecognition(sr);\n\n return () => {\n sr.removeEventListener(\"start\", handleStart);\n sr.removeEventListener(\"end\", handleEnd);\n sr.removeEventListener(\"result\", handleResult);\n sr.removeEventListener(\"error\", handleError);\n recognitionRef.current?.stop();\n };\n }, [textareaRef, onTranscriptionChange]);\n\n const handleToggleListening = useCallback(() => {\n if (!recognition) return;\n const sr = recognition as SpeechRecognitionInstance & {\n start(): void;\n stop(): void;\n };\n if (isListening) sr.stop();\n else sr.start();\n }, [recognition, isListening]);\n\n const button = (\n <Button\n aria-label={ariaLabel}\n className={cn(\n \"text-sf-subtle hover:text-sf-default transition-all\",\n isListening && \"animate-pulse text-sf-brand\",\n className\n )}\n disabled={!recognition}\n onClick={handleToggleListening}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <MicrophoneIcon className=\"size-4\" />\n </Button>\n );\n\n if (!recognition) return null;\n\n return (\n <Tooltip content={isListening ? \"Stop listening\" : \"Voice input\"}>\n {button}\n </Tooltip>\n );\n};\n\n// ─── PromptInputAttachButton ──────────────────────────────────────────────────\n\nexport type PromptInputAttachButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\n/**\n * Convenience button that opens the file dialog directly (no dropdown needed).\n */\nexport const PromptInputAttachButton = ({\n \"aria-label\": ariaLabel = \"Attach file\",\n className,\n ...props\n}: PromptInputAttachButtonProps) => {\n const attachments = usePromptInputAttachments();\n const handleClick = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <Tooltip content={ariaLabel}>\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n onClick={handleClick}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <PaperclipIcon className=\"size-4\" />\n </Button>\n </Tooltip>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as cn } from "./cn-YROP2_ox.js";
|
|
3
|
+
import { t as Button } from "./button-De0267YU.js";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { ChatCircleDotsIcon, CheckIcon } from "@phosphor-icons/react";
|
|
7
|
+
//#region src/components/ai-question/ai-question.tsx
|
|
8
|
+
var SF_AI_QUESTION_VARIANTS = { status: {
|
|
9
|
+
pending: {
|
|
10
|
+
classes: "",
|
|
11
|
+
description: "Waiting for answer"
|
|
12
|
+
},
|
|
13
|
+
answered: {
|
|
14
|
+
classes: "",
|
|
15
|
+
description: "User has answered"
|
|
16
|
+
}
|
|
17
|
+
} };
|
|
18
|
+
var SF_AI_QUESTION_DEFAULT_VARIANTS = { status: "pending" };
|
|
19
|
+
/**
|
|
20
|
+
* Agent question card. Renders when the agent uses the `ask_user` built-in
|
|
21
|
+
* tool and needs a response before continuing.
|
|
22
|
+
*
|
|
23
|
+
* Maps to harness event: `ask_question`.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <AiQuestion
|
|
28
|
+
* questionId="q-123"
|
|
29
|
+
* question="How should I handle the failing tests?"
|
|
30
|
+
* header="Decision needed"
|
|
31
|
+
* options={[
|
|
32
|
+
* { label: "Fix them", description: "Update the test expectations" },
|
|
33
|
+
* { label: "Skip them", description: "Mark as skipped for now" },
|
|
34
|
+
* ]}
|
|
35
|
+
* onAnswer={(id, answer) => harness.respondToQuestion({ questionId: id, answer })}
|
|
36
|
+
* />
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function AiQuestion({ questionId, question, header, status = "pending", options, multiple = false, allowCustom = true, icon, onAnswer, answeredWith, children, className, ...props }) {
|
|
40
|
+
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
41
|
+
const [customText, setCustomText] = useState("");
|
|
42
|
+
const isPending = status === "pending";
|
|
43
|
+
const IconComponent = icon ?? ChatCircleDotsIcon;
|
|
44
|
+
const toggleOption = useCallback((label) => {
|
|
45
|
+
setSelected((prev) => {
|
|
46
|
+
const next = new Set(prev);
|
|
47
|
+
if (multiple) if (next.has(label)) next.delete(label);
|
|
48
|
+
else next.add(label);
|
|
49
|
+
else if (next.has(label)) next.clear();
|
|
50
|
+
else {
|
|
51
|
+
next.clear();
|
|
52
|
+
next.add(label);
|
|
53
|
+
}
|
|
54
|
+
return next;
|
|
55
|
+
});
|
|
56
|
+
}, [multiple]);
|
|
57
|
+
const handleSubmit = useCallback(() => {
|
|
58
|
+
const answer = customText.trim() || [...selected].join(", ");
|
|
59
|
+
if (answer) onAnswer?.(questionId, answer);
|
|
60
|
+
}, [
|
|
61
|
+
customText,
|
|
62
|
+
selected,
|
|
63
|
+
questionId,
|
|
64
|
+
onAnswer
|
|
65
|
+
]);
|
|
66
|
+
const hasAnswer = customText.trim() || selected.size > 0;
|
|
67
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
68
|
+
className: cn("flex flex-col gap-2.5 rounded-lg bg-sf-tint/50 p-3", !isPending && "opacity-75", className),
|
|
69
|
+
...props,
|
|
70
|
+
children: [
|
|
71
|
+
/* @__PURE__ */ jsxs("div", {
|
|
72
|
+
className: "flex items-start gap-2.5",
|
|
73
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
74
|
+
className: "mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-md bg-sf-brand/10 text-sf-brand",
|
|
75
|
+
children: /* @__PURE__ */ jsx(IconComponent, {
|
|
76
|
+
className: "size-4",
|
|
77
|
+
weight: "bold"
|
|
78
|
+
})
|
|
79
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
80
|
+
className: "flex min-w-0 flex-col gap-0.5",
|
|
81
|
+
children: [header && /* @__PURE__ */ jsx("span", {
|
|
82
|
+
className: "text-sm font-medium text-sf-subtle uppercase tracking-wide",
|
|
83
|
+
children: header
|
|
84
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: "text-sm font-medium text-sf-default",
|
|
86
|
+
children: question
|
|
87
|
+
})]
|
|
88
|
+
})]
|
|
89
|
+
}),
|
|
90
|
+
children,
|
|
91
|
+
isPending && options && options.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
92
|
+
className: "flex flex-col gap-1 pl-0.5",
|
|
93
|
+
children: options.map((opt) => {
|
|
94
|
+
const isSelected = selected.has(opt.label);
|
|
95
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
96
|
+
className: cn("flex items-center gap-2.5 rounded-md border px-2.5 py-2 text-left text-sm transition-colors", isSelected ? "border-sf-line/50 bg-sf-tint text-sf-default" : "border-transparent bg-transparent text-sf-default hover:bg-sf-tint/50"),
|
|
97
|
+
onClick: () => toggleOption(opt.label),
|
|
98
|
+
type: "button",
|
|
99
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
100
|
+
className: cn("flex size-4 shrink-0 items-center justify-center rounded border transition-colors", isSelected ? "border-sf-brand bg-sf-brand text-sf-inverse" : "border-sf-line"),
|
|
101
|
+
children: isSelected && /* @__PURE__ */ jsx(CheckIcon, {
|
|
102
|
+
className: "size-3",
|
|
103
|
+
weight: "bold"
|
|
104
|
+
})
|
|
105
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
106
|
+
className: "flex min-w-0 flex-col",
|
|
107
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
108
|
+
className: "font-medium",
|
|
109
|
+
children: opt.label
|
|
110
|
+
}), opt.description && /* @__PURE__ */ jsx("span", {
|
|
111
|
+
className: "text-sm text-sf-subtle",
|
|
112
|
+
children: opt.description
|
|
113
|
+
})]
|
|
114
|
+
})]
|
|
115
|
+
}, opt.label);
|
|
116
|
+
})
|
|
117
|
+
}),
|
|
118
|
+
isPending && allowCustom && /* @__PURE__ */ jsx("textarea", {
|
|
119
|
+
className: "min-h-[48px] resize-none rounded-md border border-sf-line/50 bg-sf-base px-2.5 py-1.5 text-sm text-sf-default outline-none placeholder:text-sf-inactive focus:border-sf-ring",
|
|
120
|
+
onChange: (e) => setCustomText(e.target.value),
|
|
121
|
+
placeholder: "Type your answer…",
|
|
122
|
+
value: customText
|
|
123
|
+
}),
|
|
124
|
+
isPending && /* @__PURE__ */ jsx("div", {
|
|
125
|
+
className: "flex justify-end",
|
|
126
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
127
|
+
disabled: !hasAnswer,
|
|
128
|
+
onClick: handleSubmit,
|
|
129
|
+
size: "sm",
|
|
130
|
+
type: "button",
|
|
131
|
+
variant: "primary",
|
|
132
|
+
children: "Submit answer"
|
|
133
|
+
})
|
|
134
|
+
}),
|
|
135
|
+
!isPending && answeredWith && /* @__PURE__ */ jsxs("div", {
|
|
136
|
+
className: "flex items-center gap-2 pl-8 text-sm text-sf-subtle",
|
|
137
|
+
children: [/* @__PURE__ */ jsx(CheckIcon, {
|
|
138
|
+
className: "size-3.5 text-sf-success",
|
|
139
|
+
weight: "bold"
|
|
140
|
+
}), /* @__PURE__ */ jsxs("span", { children: ["Answered: ", answeredWith] })]
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
AiQuestion.displayName = "AiQuestion";
|
|
146
|
+
//#endregion
|
|
147
|
+
export { SF_AI_QUESTION_DEFAULT_VARIANTS as n, SF_AI_QUESTION_VARIANTS as r, AiQuestion as t };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=ai-question-Dp1g9k2o.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-question-Dp1g9k2o.js","names":[],"sources":["../src/components/ai-question/ai-question.tsx"],"sourcesContent":["\"use client\";\n\nimport { ChatCircleDotsIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { useCallback, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_QUESTION_VARIANTS = {\n status: {\n pending: { classes: \"\", description: \"Waiting for answer\" },\n answered: { classes: \"\", description: \"User has answered\" },\n },\n} as const;\n\nexport const SF_AI_QUESTION_DEFAULT_VARIANTS = {\n status: \"pending\",\n} as const;\n\nexport type SFAiQuestionStatus = keyof typeof SF_AI_QUESTION_VARIANTS.status;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiQuestionOption = {\n label: string;\n description?: string;\n};\n\nexport type AiQuestionProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\"> & {\n /** Unique identifier for this question (maps to harness `questionId`). */\n questionId: string;\n /** The question text. */\n question: string;\n /** Optional header/context label. */\n header?: string;\n /** Current status. */\n status?: SFAiQuestionStatus;\n /** Available choice options. */\n options?: AiQuestionOption[];\n /** Allow selecting multiple options. Default: `false`. */\n multiple?: boolean;\n /**\n * Allow freeform text input (custom answer). Default: `true`.\n * When options are provided, this adds a text field below them.\n */\n allowCustom?: boolean;\n /** Custom icon for the question header. */\n icon?: ElementType;\n /** Called when the user submits their answer. */\n onAnswer?: (questionId: string, answer: string) => void;\n /** The answer that was submitted (shown when `status=\"answered\"`). */\n answeredWith?: string;\n /** Content rendered below the question, above options. */\n children?: ReactNode;\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Agent question card. Renders when the agent uses the `ask_user` built-in\n * tool and needs a response before continuing.\n *\n * Maps to harness event: `ask_question`.\n *\n * @example\n * ```tsx\n * <AiQuestion\n * questionId=\"q-123\"\n * question=\"How should I handle the failing tests?\"\n * header=\"Decision needed\"\n * options={[\n * { label: \"Fix them\", description: \"Update the test expectations\" },\n * { label: \"Skip them\", description: \"Mark as skipped for now\" },\n * ]}\n * onAnswer={(id, answer) => harness.respondToQuestion({ questionId: id, answer })}\n * />\n * ```\n */\nexport function AiQuestion({\n questionId,\n question,\n header,\n status = \"pending\",\n options,\n multiple = false,\n allowCustom = true,\n icon,\n onAnswer,\n answeredWith,\n children,\n className,\n ...props\n}: AiQuestionProps) {\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [customText, setCustomText] = useState(\"\");\n const isPending = status === \"pending\";\n\n const IconComponent = icon ?? ChatCircleDotsIcon;\n\n const toggleOption = useCallback(\n (label: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (multiple) {\n if (next.has(label)) next.delete(label);\n else next.add(label);\n } else if (next.has(label)) {\n next.clear();\n } else {\n next.clear();\n next.add(label);\n }\n return next;\n });\n },\n [multiple]\n );\n\n const handleSubmit = useCallback(() => {\n // Custom text takes priority; otherwise join selected option labels\n const answer = customText.trim() || [...selected].join(\", \");\n if (answer) {\n onAnswer?.(questionId, answer);\n }\n }, [customText, selected, questionId, onAnswer]);\n\n const hasAnswer = customText.trim() || selected.size > 0;\n\n return (\n <div\n className={cn(\n \"flex flex-col gap-2.5 rounded-lg bg-sf-tint/50 p-3\",\n !isPending && \"opacity-75\",\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-md bg-sf-brand/10 text-sf-brand\">\n <IconComponent className=\"size-4\" weight=\"bold\" />\n </div>\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n {header && (\n <span className=\"text-sm font-medium text-sf-subtle uppercase tracking-wide\">\n {header}\n </span>\n )}\n <span className=\"text-sm font-medium text-sf-default\">\n {question}\n </span>\n </div>\n </div>\n\n {children}\n\n {/* Options */}\n {isPending && options && options.length > 0 && (\n <div className=\"flex flex-col gap-1 pl-0.5\">\n {options.map((opt) => {\n const isSelected = selected.has(opt.label);\n return (\n <button\n className={cn(\n \"flex items-center gap-2.5 rounded-md border px-2.5 py-2 text-left text-sm transition-colors\",\n isSelected\n ? \"border-sf-line/50 bg-sf-tint text-sf-default\"\n : \"border-transparent bg-transparent text-sf-default hover:bg-sf-tint/50\"\n )}\n key={opt.label}\n onClick={() => toggleOption(opt.label)}\n type=\"button\"\n >\n <div\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded border transition-colors\",\n isSelected\n ? \"border-sf-brand bg-sf-brand text-sf-inverse\"\n : \"border-sf-line\"\n )}\n >\n {isSelected && <CheckIcon className=\"size-3\" weight=\"bold\" />}\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"font-medium\">{opt.label}</span>\n {opt.description && (\n <span className=\"text-sm text-sf-subtle\">\n {opt.description}\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n )}\n\n {/* Custom text input */}\n {isPending && allowCustom && (\n <textarea\n className=\"min-h-[48px] resize-none rounded-md border border-sf-line/50 bg-sf-base px-2.5 py-1.5 text-sm text-sf-default outline-none placeholder:text-sf-inactive focus:border-sf-ring\"\n onChange={(e) => setCustomText(e.target.value)}\n placeholder=\"Type your answer…\"\n value={customText}\n />\n )}\n\n {/* Submit */}\n {isPending && (\n <div className=\"flex justify-end\">\n <Button\n disabled={!hasAnswer}\n onClick={handleSubmit}\n size=\"sm\"\n type=\"button\"\n variant=\"primary\"\n >\n Submit answer\n </Button>\n </div>\n )}\n\n {/* Answered state */}\n {!isPending && answeredWith && (\n <div className=\"flex items-center gap-2 pl-8 text-sm text-sf-subtle\">\n <CheckIcon className=\"size-3.5 text-sf-success\" weight=\"bold\" />\n <span>Answered: {answeredWith}</span>\n </div>\n )}\n </div>\n );\n}\n\nAiQuestion.displayName = \"AiQuestion\";\n"],"mappings":";;;;;;;AAWA,IAAa,0BAA0B,EACrC,QAAQ;CACN,SAAS;EAAE,SAAS;EAAI,aAAa;EAAsB;CAC3D,UAAU;EAAE,SAAS;EAAI,aAAa;EAAqB;CAC5D,EACF;AAED,IAAa,kCAAkC,EAC7C,QAAQ,WACT;;;;;;;;;;;;;;;;;;;;;AA6DD,SAAgB,WAAW,EACzB,YACA,UACA,QACA,SAAS,WACT,SACA,WAAW,OACX,cAAc,MACd,MACA,UACA,cACA,UACA,WACA,GAAG,SACe;CAClB,MAAM,CAAC,UAAU,eAAe,yBAAsB,IAAI,KAAK,CAAC;CAChE,MAAM,CAAC,YAAY,iBAAiB,SAAS,GAAG;CAChD,MAAM,YAAY,WAAW;CAE7B,MAAM,gBAAgB,QAAQ;CAE9B,MAAM,eAAe,aAClB,UAAkB;AACjB,eAAa,SAAS;GACpB,MAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,OAAI,SACF,KAAI,KAAK,IAAI,MAAM,CAAE,MAAK,OAAO,MAAM;OAClC,MAAK,IAAI,MAAM;YACX,KAAK,IAAI,MAAM,CACxB,MAAK,OAAO;QACP;AACL,SAAK,OAAO;AACZ,SAAK,IAAI,MAAM;;AAEjB,UAAO;IACP;IAEJ,CAAC,SAAS,CACX;CAED,MAAM,eAAe,kBAAkB;EAErC,MAAM,SAAS,WAAW,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,KAAK;AAC5D,MAAI,OACF,YAAW,YAAY,OAAO;IAE/B;EAAC;EAAY;EAAU;EAAY;EAAS,CAAC;CAEhD,MAAM,YAAY,WAAW,MAAM,IAAI,SAAS,OAAO;AAEvD,QACE,qBAAC,OAAD;EACE,WAAW,GACT,sDACA,CAAC,aAAa,cACd,UACD;EACD,GAAI;YANN;GASE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,eAAD;MAAe,WAAU;MAAS,QAAO;MAAS,CAAA;KAC9C,CAAA,EACN,qBAAC,OAAD;KAAK,WAAU;eAAf,CACG,UACC,oBAAC,QAAD;MAAM,WAAU;gBACb;MACI,CAAA,EAET,oBAAC,QAAD;MAAM,WAAU;gBACb;MACI,CAAA,CACH;OACF;;GAEL;GAGA,aAAa,WAAW,QAAQ,SAAS,KACxC,oBAAC,OAAD;IAAK,WAAU;cACZ,QAAQ,KAAK,QAAQ;KACpB,MAAM,aAAa,SAAS,IAAI,IAAI,MAAM;AAC1C,YACE,qBAAC,UAAD;MACE,WAAW,GACT,+FACA,aACI,iDACA,wEACL;MAED,eAAe,aAAa,IAAI,MAAM;MACtC,MAAK;gBATP,CAWE,oBAAC,OAAD;OACE,WAAW,GACT,qFACA,aACI,gDACA,iBACL;iBAEA,cAAc,oBAAC,WAAD;QAAW,WAAU;QAAS,QAAO;QAAS,CAAA;OACzD,CAAA,EACN,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,oBAAC,QAAD;QAAM,WAAU;kBAAe,IAAI;QAAa,CAAA,EAC/C,IAAI,eACH,oBAAC,QAAD;QAAM,WAAU;kBACb,IAAI;QACA,CAAA,CAEL;SACC;QAtBF,IAAI,MAsBF;MAEX;IACE,CAAA;GAIP,aAAa,eACZ,oBAAC,YAAD;IACE,WAAU;IACV,WAAW,MAAM,cAAc,EAAE,OAAO,MAAM;IAC9C,aAAY;IACZ,OAAO;IACP,CAAA;GAIH,aACC,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,QAAD;KACE,UAAU,CAAC;KACX,SAAS;KACT,MAAK;KACL,MAAK;KACL,SAAQ;eACT;KAEQ,CAAA;IACL,CAAA;GAIP,CAAC,aAAa,gBACb,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,WAAD;KAAW,WAAU;KAA2B,QAAO;KAAS,CAAA,EAChE,qBAAC,QAAD,EAAA,UAAA,CAAM,cAAW,aAAoB,EAAA,CAAA,CACjC;;GAEJ;;;AAIV,WAAW,cAAc"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as cn } from "./cn-YROP2_ox.js";
|
|
3
|
+
import { t as AiStatusBadge } from "./ai-status-badge-WhbKVeqn.js";
|
|
4
|
+
import { Suspense, lazy, memo, useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { BrainIcon, CaretDownIcon, CaretRightIcon, SparkleIcon, SpinnerGapIcon } from "@phosphor-icons/react";
|
|
7
|
+
import { Collapsible } from "@base-ui/react/collapsible";
|
|
8
|
+
//#region src/components/ai-reasoning/ai-reasoning.tsx
|
|
9
|
+
var Streamdown = lazy(() => {
|
|
10
|
+
if (typeof window === "undefined") return Promise.resolve({ default: ({ children }) => /* @__PURE__ */ jsx("span", { children }) });
|
|
11
|
+
return import("streamdown").then((sd) => ({ default: (props) => /* @__PURE__ */ jsx(sd.Streamdown, { ...props }) }));
|
|
12
|
+
});
|
|
13
|
+
var SF_AI_REASONING_VARIANTS = { variant: {
|
|
14
|
+
default: {
|
|
15
|
+
classes: "",
|
|
16
|
+
description: "Expandable card with collapsible reasoning text and duration"
|
|
17
|
+
},
|
|
18
|
+
inline: {
|
|
19
|
+
classes: "",
|
|
20
|
+
description: "Compact single-line display with left accent border"
|
|
21
|
+
},
|
|
22
|
+
minimal: {
|
|
23
|
+
classes: "",
|
|
24
|
+
description: "Pill-shaped status badge"
|
|
25
|
+
}
|
|
26
|
+
} };
|
|
27
|
+
var SF_AI_REASONING_DEFAULT_VARIANTS = { variant: "default" };
|
|
28
|
+
/** Format seconds into a human-friendly duration string. */
|
|
29
|
+
function formatDuration(seconds) {
|
|
30
|
+
if (seconds < 60) return `${seconds}s`;
|
|
31
|
+
const mins = Math.floor(seconds / 60);
|
|
32
|
+
const secs = seconds % 60;
|
|
33
|
+
return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
|
|
34
|
+
}
|
|
35
|
+
/** Truncate reasoning text with an ellipsis. */
|
|
36
|
+
function truncateReasoning(text, maxLength = 100) {
|
|
37
|
+
if (text.length <= maxLength) return text;
|
|
38
|
+
return `${text.slice(0, maxLength).trim()}...`;
|
|
39
|
+
}
|
|
40
|
+
/** Extract the first **bold** text from markdown-style reasoning. */
|
|
41
|
+
function extractFirstBoldText(text) {
|
|
42
|
+
return text.match(/\*\*([^*]+)\*\*/)?.[1]?.trim() ?? null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Collapsible reasoning block. Supports three display variants:
|
|
46
|
+
* - `"default"` — expandable card with auto-open on stream start
|
|
47
|
+
* - `"inline"` — compact single-line with left accent border
|
|
48
|
+
* - `"minimal"` — pill-shaped status badge
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <AiReasoning
|
|
53
|
+
* part={{ text: "First I considered the user's intent..." }}
|
|
54
|
+
* isStreaming={false}
|
|
55
|
+
* duration={3}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
var AiReasoning = memo(({ part, variant = "default", isStreaming = false, duration: durationProp, defaultExpanded = false, open: openProp, onOpenChange, autoCloseDelay = 1e3, icon: iconProp, label: labelProp, streamingLabel: streamingLabelProp, className, ...props }) => {
|
|
60
|
+
const [internalOpen, setInternalOpen] = useState(defaultExpanded);
|
|
61
|
+
const [hasAutoClosed, setHasAutoClosed] = useState(false);
|
|
62
|
+
const [userOpened, setUserOpened] = useState(false);
|
|
63
|
+
const [internalDuration, setInternalDuration] = useState(0);
|
|
64
|
+
const startTimeRef = useRef(null);
|
|
65
|
+
const isControlled = openProp !== void 0;
|
|
66
|
+
const isOpen = isControlled ? openProp : internalOpen;
|
|
67
|
+
const rawSetIsOpen = isControlled ? onOpenChange : setInternalOpen;
|
|
68
|
+
const setIsOpen = useCallback((value) => {
|
|
69
|
+
rawSetIsOpen?.(value);
|
|
70
|
+
}, [rawSetIsOpen]);
|
|
71
|
+
const handleUserToggle = useCallback((value) => {
|
|
72
|
+
if (value) setUserOpened(true);
|
|
73
|
+
setIsOpen(value);
|
|
74
|
+
}, [setIsOpen]);
|
|
75
|
+
const displayDuration = durationProp ?? internalDuration;
|
|
76
|
+
const reasoningText = part.text || "";
|
|
77
|
+
const extractedBoldTitle = !isStreaming ? extractFirstBoldText(reasoningText) : null;
|
|
78
|
+
const dynamicLabel = extractedBoldTitle ? truncateReasoning(extractedBoldTitle, 40) : null;
|
|
79
|
+
const displayLabel = isStreaming ? streamingLabelProp ?? labelProp ?? "Thinking..." : labelProp ?? dynamicLabel ?? "Reasoning";
|
|
80
|
+
const ActiveIcon = iconProp ?? (isStreaming ? SparkleIcon : BrainIcon);
|
|
81
|
+
const StreamIcon = iconProp ?? SparkleIcon;
|
|
82
|
+
const DoneIcon = iconProp ?? BrainIcon;
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (isStreaming) {
|
|
85
|
+
if (startTimeRef.current === null) startTimeRef.current = Date.now();
|
|
86
|
+
const interval = setInterval(() => {
|
|
87
|
+
if (startTimeRef.current) setInternalDuration(Math.round((Date.now() - startTimeRef.current) / 1e3));
|
|
88
|
+
}, 1e3);
|
|
89
|
+
return () => clearInterval(interval);
|
|
90
|
+
}
|
|
91
|
+
if (startTimeRef.current !== null) {
|
|
92
|
+
setInternalDuration(Math.round((Date.now() - startTimeRef.current) / 1e3));
|
|
93
|
+
startTimeRef.current = null;
|
|
94
|
+
}
|
|
95
|
+
}, [isStreaming]);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (isStreaming && !isOpen) {
|
|
98
|
+
setUserOpened(false);
|
|
99
|
+
setIsOpen(true);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!isStreaming && isOpen && !defaultExpanded && !hasAutoClosed && !userOpened && autoCloseDelay > 0) {
|
|
103
|
+
const timer = setTimeout(() => {
|
|
104
|
+
setIsOpen(false);
|
|
105
|
+
setHasAutoClosed(true);
|
|
106
|
+
}, autoCloseDelay);
|
|
107
|
+
return () => clearTimeout(timer);
|
|
108
|
+
}
|
|
109
|
+
}, [
|
|
110
|
+
isStreaming,
|
|
111
|
+
isOpen,
|
|
112
|
+
defaultExpanded,
|
|
113
|
+
hasAutoClosed,
|
|
114
|
+
userOpened,
|
|
115
|
+
autoCloseDelay,
|
|
116
|
+
setIsOpen
|
|
117
|
+
]);
|
|
118
|
+
if (variant === "minimal") return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
119
|
+
open: isOpen,
|
|
120
|
+
onOpenChange: handleUserToggle,
|
|
121
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
122
|
+
className: cn("my-1.5", className),
|
|
123
|
+
...props,
|
|
124
|
+
children: [/* @__PURE__ */ jsx(Collapsible.Trigger, {
|
|
125
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
126
|
+
type: "button",
|
|
127
|
+
className: "cursor-pointer"
|
|
128
|
+
}),
|
|
129
|
+
children: /* @__PURE__ */ jsx(AiStatusBadge, {
|
|
130
|
+
className: "py-1",
|
|
131
|
+
icon: DoneIcon,
|
|
132
|
+
label: displayLabel,
|
|
133
|
+
status: isStreaming ? "running" : "success"
|
|
134
|
+
})
|
|
135
|
+
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
136
|
+
className: "overflow-hidden",
|
|
137
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
138
|
+
className: "mx-2 mt-1 rounded-lg bg-sf-tint/50 px-3 py-2",
|
|
139
|
+
children: /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Streamdown, {
|
|
140
|
+
className: "text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
141
|
+
children: reasoningText
|
|
142
|
+
}) })
|
|
143
|
+
})
|
|
144
|
+
})]
|
|
145
|
+
})
|
|
146
|
+
});
|
|
147
|
+
if (variant === "inline") return /* @__PURE__ */ jsxs("div", {
|
|
148
|
+
className: cn("my-1.5 flex items-center gap-2 border-l-2 border-sf-line py-1 pl-2", "animate-in fade-in-0 slide-in-from-bottom-1 duration-200", className),
|
|
149
|
+
...props,
|
|
150
|
+
children: [
|
|
151
|
+
/* @__PURE__ */ jsx(ActiveIcon, { className: "size-3.5 shrink-0 text-sf-subtle" }),
|
|
152
|
+
/* @__PURE__ */ jsx("span", {
|
|
153
|
+
className: "text-sm text-sf-subtle",
|
|
154
|
+
children: displayLabel
|
|
155
|
+
}),
|
|
156
|
+
isStreaming ? /* @__PURE__ */ jsx(SpinnerGapIcon, { className: "size-3.5 animate-spin text-sf-subtle" }) : null,
|
|
157
|
+
!isStreaming && reasoningText ? /* @__PURE__ */ jsxs("span", {
|
|
158
|
+
className: "max-w-[300px] truncate text-xs text-sf-subtle/60",
|
|
159
|
+
children: ["— ", truncateReasoning(reasoningText)]
|
|
160
|
+
}) : null
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
164
|
+
open: isOpen,
|
|
165
|
+
onOpenChange: handleUserToggle,
|
|
166
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
167
|
+
className: cn("my-0.5 flex w-full flex-col", "animate-in fade-in-0 duration-150", className),
|
|
168
|
+
...props,
|
|
169
|
+
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
170
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
171
|
+
type: "button",
|
|
172
|
+
className: "flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint"
|
|
173
|
+
}),
|
|
174
|
+
children: [
|
|
175
|
+
isStreaming ? /* @__PURE__ */ jsx(StreamIcon, { className: "size-3.5 shrink-0 animate-pulse text-sf-subtle" }) : /* @__PURE__ */ jsx(DoneIcon, { className: "size-3.5 shrink-0 text-sf-subtle" }),
|
|
176
|
+
/* @__PURE__ */ jsx("span", {
|
|
177
|
+
className: "text-sm text-sf-subtle",
|
|
178
|
+
children: displayLabel
|
|
179
|
+
}),
|
|
180
|
+
isStreaming ? /* @__PURE__ */ jsx(SpinnerGapIcon, { className: "size-3 shrink-0 animate-spin text-sf-subtle" }) : null,
|
|
181
|
+
displayDuration > 0 && !isStreaming ? /* @__PURE__ */ jsx("span", {
|
|
182
|
+
className: "text-xs tabular-nums text-sf-subtle/60",
|
|
183
|
+
children: formatDuration(displayDuration)
|
|
184
|
+
}) : null,
|
|
185
|
+
isOpen ? /* @__PURE__ */ jsx(CaretDownIcon, { className: "size-3 shrink-0 text-sf-subtle/60" }) : /* @__PURE__ */ jsx(CaretRightIcon, { className: "size-3 shrink-0 text-sf-subtle/60" })
|
|
186
|
+
]
|
|
187
|
+
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
188
|
+
className: "overflow-hidden",
|
|
189
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
190
|
+
className: "mt-1 rounded-lg bg-sf-tint/50 px-3 py-2",
|
|
191
|
+
children: /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Streamdown, {
|
|
192
|
+
className: "text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
193
|
+
children: reasoningText || "*No reasoning content*"
|
|
194
|
+
}) })
|
|
195
|
+
})
|
|
196
|
+
})]
|
|
197
|
+
})
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
AiReasoning.displayName = "AiReasoning";
|
|
201
|
+
/**
|
|
202
|
+
* Renders multiple reasoning steps. Shows a single `<AiReasoning>` directly
|
|
203
|
+
* when only one part is provided. When multiple parts exist, renders a
|
|
204
|
+
* collapsible group with step labels.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```tsx
|
|
208
|
+
* <AiReasoningGroup parts={reasoningParts} isStreaming={false} totalDuration={5} />
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
function AiReasoningGroup({ parts, isStreaming = false, totalDuration, defaultExpanded = false, className, ...props }) {
|
|
212
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
213
|
+
if (parts.length === 1 && parts[0]) {
|
|
214
|
+
const singlePart = parts[0];
|
|
215
|
+
const { part: _part, ...restProps } = props;
|
|
216
|
+
return /* @__PURE__ */ jsx(AiReasoning, {
|
|
217
|
+
part: singlePart,
|
|
218
|
+
isStreaming,
|
|
219
|
+
duration: totalDuration,
|
|
220
|
+
className,
|
|
221
|
+
...restProps
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
225
|
+
open: isExpanded,
|
|
226
|
+
onOpenChange: setIsExpanded,
|
|
227
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
228
|
+
className: cn("my-0.5 flex w-full flex-col", "animate-in fade-in-0 duration-150", className),
|
|
229
|
+
...props,
|
|
230
|
+
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
231
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
232
|
+
type: "button",
|
|
233
|
+
className: "flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint"
|
|
234
|
+
}),
|
|
235
|
+
children: [
|
|
236
|
+
isStreaming ? /* @__PURE__ */ jsx(SparkleIcon, { className: "size-3.5 shrink-0 animate-pulse text-sf-subtle" }) : /* @__PURE__ */ jsx(BrainIcon, { className: "size-3.5 shrink-0 text-sf-subtle" }),
|
|
237
|
+
/* @__PURE__ */ jsx("span", {
|
|
238
|
+
className: "text-sm text-sf-subtle",
|
|
239
|
+
children: isStreaming ? "Thinking..." : `${parts.length} reasoning steps`
|
|
240
|
+
}),
|
|
241
|
+
isStreaming ? /* @__PURE__ */ jsx(SpinnerGapIcon, { className: "size-3 shrink-0 animate-spin text-sf-subtle" }) : null,
|
|
242
|
+
totalDuration && totalDuration > 0 && !isStreaming ? /* @__PURE__ */ jsx("span", {
|
|
243
|
+
className: "text-xs tabular-nums text-sf-subtle/60",
|
|
244
|
+
children: formatDuration(totalDuration)
|
|
245
|
+
}) : null,
|
|
246
|
+
isExpanded ? /* @__PURE__ */ jsx(CaretDownIcon, { className: "size-3 shrink-0 text-sf-subtle/60" }) : /* @__PURE__ */ jsx(CaretRightIcon, { className: "size-3 shrink-0 text-sf-subtle/60" })
|
|
247
|
+
]
|
|
248
|
+
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
249
|
+
className: "overflow-hidden",
|
|
250
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
251
|
+
className: "mt-1 space-y-2 rounded-lg bg-sf-tint/50 px-3 py-2",
|
|
252
|
+
children: parts.map((partItem, index) => /* @__PURE__ */ jsxs("div", {
|
|
253
|
+
className: "text-sm text-sf-subtle",
|
|
254
|
+
children: [parts.length > 1 ? /* @__PURE__ */ jsxs("p", {
|
|
255
|
+
className: "mb-0.5 text-[10px] uppercase tracking-wider text-sf-subtle/50",
|
|
256
|
+
children: ["Step ", index + 1]
|
|
257
|
+
}) : null, /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(Streamdown, {
|
|
258
|
+
className: "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
259
|
+
children: partItem.text || "*No content*"
|
|
260
|
+
}) })]
|
|
261
|
+
}, index))
|
|
262
|
+
})
|
|
263
|
+
})]
|
|
264
|
+
})
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
268
|
+
export { extractFirstBoldText as a, SF_AI_REASONING_VARIANTS as i, AiReasoningGroup as n, formatDuration as o, SF_AI_REASONING_DEFAULT_VARIANTS as r, truncateReasoning as s, AiReasoning as t };
|
|
269
|
+
|
|
270
|
+
//# sourceMappingURL=ai-reasoning-UAmNx_LD.js.map
|