basalt-ui 1.28.0 → 1.29.1
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/AGENTS.md +12 -19
- package/CHANGELOG.md +23 -0
- package/MIGRATING.md +171 -7
- package/README.md +66 -105
- package/agent/rules/basalt-batteries.md +60 -183
- package/agent/rules/basalt-charts.md +56 -75
- package/agent/rules/basalt-controls.md +38 -69
- package/agent/rules/basalt-mantine.md +58 -103
- package/agent/rules/basalt-state.md +42 -60
- package/agent/rules/basalt-tokens.md +46 -67
- package/agent/skills/basalt-app/SKILL.md +2 -0
- package/agent/templates/CLAUDE-block.md.tpl +14 -14
- package/agent/templates/query-client.ts.tpl +1 -1
- package/configs/oxlint-plugin.js +84 -254
- package/configs/oxlint-plugin.test.ts +23 -266
- package/configs/oxlint.json +0 -2
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +7 -4
- package/dist/agent/coalesce.js +1 -1
- package/dist/agent/merge.js +1 -1
- package/dist/agent/transport.d.ts +13 -2
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.d.ts +12 -1
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.js +20 -6
- package/dist/agent-chat/index.d.ts +1 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/relative-time.js +1 -1
- package/dist/agent-chat/thread-detail-panel.js +1 -1
- package/dist/agent-chat/thread-feed-row.d.ts +32 -7
- package/dist/agent-chat/thread-feed-row.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed-row.js +121 -86
- package/dist/agent-chat/thread-feed.d.ts +11 -1
- package/dist/agent-chat/thread-feed.d.ts.map +1 -1
- package/dist/agent-chat/thread-feed.js +10 -6
- package/dist/agent-chat/thread-message.js +1 -1
- package/dist/agent-chat/virtualize.d.ts +39 -0
- package/dist/agent-chat/virtualize.d.ts.map +1 -1
- package/dist/agent-chat/virtualize.js +15 -0
- package/dist/charts/index.d.ts +3 -3
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/index.js +8 -4
- package/dist/charts/kinds/BandStrip.js +1 -1
- package/dist/charts/kinds/Bars.d.ts +1 -3
- package/dist/charts/kinds/Bars.d.ts.map +1 -1
- package/dist/charts/kinds/Bars.js +1 -1
- package/dist/charts/kinds/DualPanel.d.ts +3 -1
- package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
- package/dist/charts/kinds/DualPanel.js +1 -1
- package/dist/charts/kinds/StackedArea.js +1 -1
- package/dist/charts/kinds/ZonedLine.d.ts +1 -3
- package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.d.ts +21 -2
- package/dist/charts/primitives/Axes.d.ts.map +1 -1
- package/dist/charts/primitives/Axes.js +34 -2
- package/dist/charts/primitives/ChartCard.d.ts +20 -4
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +62 -33
- package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
- package/dist/charts/primitives/ChartFrame.js +8 -1
- package/dist/charts/primitives/ChartPending.d.ts +12 -6
- package/dist/charts/primitives/ChartPending.d.ts.map +1 -1
- package/dist/charts/primitives/ChartPending.js +1 -1
- package/dist/charts/utils/format.d.ts +5 -92
- package/dist/charts/utils/format.d.ts.map +1 -1
- package/dist/charts/utils/format.js +10 -80
- package/dist/cli/audit-allows.d.ts +24 -0
- package/dist/cli/audit-allows.d.ts.map +1 -0
- package/dist/cli/audit-allows.js +240 -0
- package/dist/cli/check-theme.d.ts +10 -0
- package/dist/cli/check-theme.d.ts.map +1 -0
- package/dist/cli/check-theme.js +139 -0
- package/dist/cli/doctor.d.ts +47 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +197 -0
- package/dist/cli/guard-hook.d.ts +9 -0
- package/dist/cli/guard-hook.d.ts.map +1 -0
- package/dist/cli/guard-hook.js +93 -0
- package/dist/cli/help.d.ts +9 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +53 -0
- package/dist/cli/index.d.ts +360 -270
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +85 -1901
- package/dist/cli/init.d.ts +4 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +165 -0
- package/dist/cli/sync.d.ts +43 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +206 -0
- package/dist/cli/tokens-css.d.ts +51 -0
- package/dist/cli/tokens-css.d.ts.map +1 -0
- package/dist/cli/tokens-css.js +165 -0
- package/dist/commands/define-commands.js +1 -1
- package/dist/commands/define-overlays.js +1 -1
- package/dist/commands/index.d.ts +2 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -0
- package/dist/commands/overlays-mount.d.ts +7 -9
- package/dist/commands/overlays-mount.d.ts.map +1 -1
- package/dist/commands/shell-bridge.d.ts +57 -0
- package/dist/commands/shell-bridge.d.ts.map +1 -0
- package/dist/commands/shell-bridge.js +32 -0
- package/dist/common/errors.d.ts +35 -0
- package/dist/common/errors.d.ts.map +1 -1
- package/dist/common/errors.js +29 -1
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/common/index.js +6 -0
- package/dist/common/is-dev.d.ts.map +1 -0
- package/dist/{motion/index.d.ts → common/motion.d.ts} +1 -1
- package/dist/common/motion.d.ts.map +1 -0
- package/dist/common/props.d.ts +1 -1
- package/dist/common/props.d.ts.map +1 -1
- package/dist/common/validate.js +1 -1
- package/dist/content/markdown.d.ts +3 -4
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +1 -4
- package/dist/controls/actions.d.ts +1 -1
- package/dist/controls/actions.d.ts.map +1 -1
- package/dist/controls/panel-row.js +1 -1
- package/dist/controls/range-filter.js +1 -1
- package/dist/dashboard/delta-badge.d.ts +18 -10
- package/dist/dashboard/delta-badge.d.ts.map +1 -1
- package/dist/dashboard/delta-badge.js +33 -1
- package/dist/dashboard/empty-state.d.ts +1 -4
- package/dist/dashboard/empty-state.d.ts.map +1 -1
- package/dist/dashboard/empty-state.js +1 -2
- package/dist/dashboard/index.d.ts +4 -2
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +7 -1
- package/dist/dashboard/query-state.d.ts +4 -13
- package/dist/dashboard/query-state.d.ts.map +1 -1
- package/dist/dashboard/query-state.js +4 -7
- package/dist/{section → dashboard}/section.d.ts +2 -2
- package/dist/{section → dashboard}/section.d.ts.map +1 -1
- package/dist/{section → dashboard}/section.js +2 -2
- package/dist/dashboard/settings-section.d.ts +1 -1
- package/dist/dashboard/settings-section.d.ts.map +1 -1
- package/dist/dashboard/settings-section.js +1 -1
- package/dist/dashboard/stat-card.d.ts +1 -1
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +1 -1
- package/dist/dashboard/widget-header.d.ts.map +1 -0
- package/dist/data/data-table.js +2 -2
- package/dist/data/table.d.ts +1 -1
- package/dist/data/table.d.ts.map +1 -1
- package/dist/data/table.js +2 -16
- package/dist/data/virtual.d.ts +3 -3
- package/dist/dev-dock.d.ts +26 -0
- package/dist/dev-dock.d.ts.map +1 -0
- package/dist/dev-dock.js +85 -0
- package/dist/format/date.d.ts +62 -0
- package/dist/format/date.d.ts.map +1 -0
- package/dist/format/date.js +106 -0
- package/dist/format/index.d.ts +39 -0
- package/dist/format/index.d.ts.map +1 -0
- package/dist/format/index.js +54 -0
- package/dist/format/measure.d.ts +15 -0
- package/dist/format/measure.d.ts.map +1 -0
- package/dist/format/measure.js +16 -0
- package/dist/format/number.d.ts +69 -0
- package/dist/format/number.d.ts.map +1 -0
- package/dist/format/number.js +62 -0
- package/dist/format/shared.d.ts +27 -0
- package/dist/format/shared.d.ts.map +1 -0
- package/dist/format/shared.js +29 -0
- package/dist/forms/field.d.ts +4 -20
- package/dist/forms/field.d.ts.map +1 -1
- package/dist/forms/field.js +0 -4
- package/dist/forms/form-layout.d.ts +1 -1
- package/dist/forms/form-layout.d.ts.map +1 -1
- package/dist/forms/form-layout.js +1 -1
- package/dist/forms/index.d.ts +1 -1
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +1 -2
- package/dist/forms/use-form-submit.d.ts +1 -1
- package/dist/forms/use-form-submit.js +1 -1
- package/dist/guard/index.d.ts +2 -9
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +53 -32
- package/dist/guard/types.d.ts +8 -10
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +16 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -29
- package/dist/notifications/index.d.ts +5 -5
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +0 -2
- package/dist/notifications/mount-guard.d.ts.map +1 -1
- package/dist/notifications/mount-guard.js +2 -2
- package/dist/provider/connectivity-indicator.d.ts.map +1 -0
- package/dist/{connectivity → provider}/connectivity-provider.d.ts +1 -1
- package/dist/provider/connectivity-provider.d.ts.map +1 -0
- package/dist/{connectivity/types.d.ts → provider/connectivity-types.d.ts} +1 -1
- package/dist/provider/connectivity-types.d.ts.map +1 -0
- package/dist/provider/error-fallback.module.css +21 -0
- package/dist/provider/error-fallback.module.css.d.ts +9 -0
- package/dist/provider/index.d.ts +20 -36
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +42 -32
- package/dist/provider/lab-theme.js +1 -1
- package/dist/provider/use-connectivity.d.ts +3 -0
- package/dist/provider/use-connectivity.d.ts.map +1 -0
- package/dist/query-client.d.ts +67 -0
- package/dist/query-client.d.ts.map +1 -0
- package/dist/query-client.js +35 -0
- package/dist/{query/devtools.d.ts → query-devtools.d.ts} +2 -2
- package/dist/query-devtools.d.ts.map +1 -0
- package/dist/register.d.ts +17 -3
- package/dist/register.d.ts.map +1 -1
- package/dist/router-tanstack/index.d.ts +4 -7
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +1 -9
- package/dist/router-tanstack/nav.d.ts +1 -1
- package/dist/router-tanstack/nav.d.ts.map +1 -1
- package/dist/router-tanstack/search-store.d.ts +3 -6
- package/dist/router-tanstack/search-store.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.d.ts +1 -1
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.d.ts +1 -1
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-main.module.css +11 -0
- package/dist/shell/app-mobile-nav.d.ts +1 -1
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +24 -2
- package/dist/shell/app-sidebar.d.ts +1 -1
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +31 -2
- package/dist/shell/app-sidebar.module.css +10 -0
- package/dist/shell/index.d.ts +10 -4
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +13 -17
- package/dist/shell/mobile-nav-model.d.ts +1 -1
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/{nav/types.d.ts → shell/nav-types.d.ts} +1 -1
- package/dist/shell/nav-types.d.ts.map +1 -0
- package/dist/shell/page-aside.d.ts.map +1 -1
- package/dist/shell/page-aside.js +2 -29
- package/dist/shell/page-title.d.ts +14 -0
- package/dist/shell/page-title.d.ts.map +1 -0
- package/dist/shell/page-title.js +25 -0
- package/dist/shell/page-title.module.css +33 -0
- package/dist/shell/page-title.module.css.d.ts +11 -0
- package/dist/shell/sidebar-block-model.d.ts +1 -1
- package/dist/shell/sidebar-block-model.d.ts.map +1 -1
- package/dist/shell/sidebar-blocks.d.ts +1 -1
- package/dist/shell/sidebar-blocks.d.ts.map +1 -1
- package/dist/shell/use-breakpoint.d.ts +11 -0
- package/dist/shell/use-breakpoint.d.ts.map +1 -0
- package/dist/shell/use-breakpoint.js +33 -0
- package/dist/state/fields.d.ts +3 -19
- package/dist/state/fields.d.ts.map +1 -1
- package/dist/state/fields.js +6 -16
- package/dist/styles.css +36 -0
- package/dist/surfaces.d.ts +18 -41
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +48 -60
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/{theme-toggle/index.d.ts → theme/theme-toggle.d.ts} +1 -1
- package/dist/theme/theme-toggle.d.ts.map +1 -0
- package/dist/{theme-toggle/index.js → theme/theme-toggle.js} +1 -1
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +10 -0
- package/dist/tokens/palette.d.ts +12 -0
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +13 -1
- package/dist/tokens.css +1 -0
- package/llms.txt +9 -24
- package/package.json +12 -16
- package/src/agent/ai-sdk-transport.ts +11 -4
- package/src/agent/coalesce.ts +1 -1
- package/src/agent/merge.ts +1 -1
- package/src/agent/transport.ts +15 -2
- package/src/agent/use-agent-thread-runs.ts +65 -15
- package/src/agent-chat/index.ts +6 -4
- package/src/agent-chat/relative-time.ts +1 -1
- package/src/agent-chat/thread-detail-panel.tsx +1 -1
- package/src/agent-chat/thread-feed-row.tsx +105 -30
- package/src/agent-chat/thread-feed.tsx +51 -25
- package/src/agent-chat/thread-message.tsx +1 -1
- package/src/agent-chat/virtualize.ts +48 -0
- package/src/charts/index.ts +7 -10
- package/src/charts/kinds/BandStrip.tsx +1 -1
- package/src/charts/kinds/Bars.tsx +2 -5
- package/src/charts/kinds/DualPanel.tsx +4 -3
- package/src/charts/kinds/StackedArea.tsx +1 -1
- package/src/charts/kinds/ZonedLine.tsx +1 -4
- package/src/charts/primitives/Axes.tsx +49 -0
- package/src/charts/primitives/ChartCard.tsx +49 -6
- package/src/charts/primitives/ChartFrame.tsx +5 -1
- package/src/charts/primitives/ChartPending.tsx +14 -8
- package/src/charts/utils/format.ts +17 -186
- package/src/cli/audit-allows.ts +371 -0
- package/src/cli/check-theme.ts +197 -0
- package/src/cli/doctor.ts +331 -0
- package/src/cli/guard-hook.ts +115 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +269 -3439
- package/src/cli/init.ts +247 -0
- package/src/cli/sync.ts +324 -0
- package/src/cli/tokens-css.ts +252 -0
- package/src/commands/define-commands.ts +1 -1
- package/src/commands/define-overlays.ts +1 -1
- package/src/commands/index.ts +10 -1
- package/src/commands/overlays-mount.tsx +8 -10
- package/src/commands/shell-bridge.ts +86 -0
- package/src/common/errors.ts +70 -0
- package/src/common/index.ts +2 -0
- package/src/common/props.ts +1 -1
- package/src/common/validate.ts +1 -1
- package/src/content/markdown.tsx +4 -8
- package/src/controls/actions.tsx +1 -1
- package/src/controls/panel-row.tsx +1 -1
- package/src/controls/range-filter.tsx +1 -1
- package/src/dashboard/delta-badge.tsx +74 -7
- package/src/dashboard/empty-state.tsx +2 -6
- package/src/dashboard/index.ts +11 -2
- package/src/dashboard/query-state.tsx +5 -18
- package/src/{section → dashboard}/section.tsx +4 -4
- package/src/dashboard/settings-section.tsx +2 -2
- package/src/dashboard/stat-card.tsx +2 -2
- package/src/data/data-table.tsx +3 -3
- package/src/data/table.ts +6 -25
- package/src/data/virtual-list.tsx +1 -1
- package/src/data/virtual.ts +3 -3
- package/src/dev-dock.tsx +162 -0
- package/src/format/date.ts +184 -0
- package/src/format/index.ts +69 -0
- package/src/format/measure.ts +31 -0
- package/src/format/number.ts +129 -0
- package/src/format/shared.ts +63 -0
- package/src/forms/field.ts +4 -24
- package/src/forms/form-layout.tsx +2 -2
- package/src/forms/index.ts +1 -2
- package/src/forms/use-form-submit.ts +2 -2
- package/src/guard/index.ts +80 -69
- package/src/guard/types.ts +7 -10
- package/src/index.ts +38 -29
- package/src/notifications/index.ts +5 -7
- package/src/notifications/mount-guard.ts +7 -9
- package/src/{connectivity → provider}/connectivity-indicator.tsx +1 -1
- package/src/{connectivity → provider}/connectivity-provider.tsx +1 -1
- package/src/provider/error-fallback.module.css +21 -0
- package/src/provider/error-fallback.module.css.d.ts +9 -0
- package/src/provider/index.tsx +71 -71
- package/src/provider/lab-theme.ts +1 -1
- package/src/{connectivity → provider}/use-connectivity.ts +3 -3
- package/src/query-client.ts +105 -0
- package/src/{query/devtools.tsx → query-devtools.tsx} +5 -4
- package/src/register.ts +20 -4
- package/src/router-tanstack/index.ts +4 -15
- package/src/router-tanstack/nav.ts +1 -1
- package/src/router-tanstack/search-store.ts +3 -4
- package/src/router-tanstack/use-nav.ts +1 -1
- package/src/shell/app-breadcrumbs.tsx +1 -1
- package/src/shell/app-main.module.css +11 -0
- package/src/shell/app-mobile-nav.tsx +28 -1
- package/src/shell/app-sidebar.module.css +10 -0
- package/src/shell/app-sidebar.tsx +31 -2
- package/src/shell/index.tsx +23 -28
- package/src/shell/mobile-nav-model.ts +1 -1
- package/src/shell/page-aside.tsx +2 -52
- package/src/shell/page-title.module.css +33 -0
- package/src/shell/page-title.module.css.d.ts +11 -0
- package/src/shell/page-title.tsx +57 -0
- package/src/shell/sidebar-block-model.ts +1 -1
- package/src/shell/sidebar-blocks.tsx +1 -1
- package/src/shell/use-breakpoint.ts +73 -0
- package/src/state/fields.ts +7 -43
- package/src/styles.css +36 -0
- package/src/surfaces.ts +47 -61
- package/src/theme/index.ts +7 -0
- package/src/{theme-toggle/index.tsx → theme/theme-toggle.tsx} +1 -1
- package/src/tokens/index.ts +10 -0
- package/src/tokens/palette.ts +12 -0
- package/dist/connectivity/connectivity-indicator.d.ts.map +0 -1
- package/dist/connectivity/connectivity-provider.d.ts.map +0 -1
- package/dist/connectivity/index.d.ts +0 -14
- package/dist/connectivity/index.d.ts.map +0 -1
- package/dist/connectivity/index.js +0 -8
- package/dist/connectivity/types.d.ts.map +0 -1
- package/dist/connectivity/use-connectivity.d.ts +0 -3
- package/dist/connectivity/use-connectivity.d.ts.map +0 -1
- package/dist/data/index.d.ts +0 -38
- package/dist/data/index.d.ts.map +0 -1
- package/dist/data/index.js +0 -24
- package/dist/motion/index.d.ts.map +0 -1
- package/dist/nav/types.d.ts.map +0 -1
- package/dist/notifications/overlay.d.ts +0 -20
- package/dist/notifications/overlay.d.ts.map +0 -1
- package/dist/notifications/overlay.js +0 -14
- package/dist/query/devtools.d.ts.map +0 -1
- package/dist/query/error-message.d.ts +0 -41
- package/dist/query/error-message.d.ts.map +0 -1
- package/dist/query/error-message.js +0 -30
- package/dist/query/index.d.ts +0 -47
- package/dist/query/index.d.ts.map +0 -1
- package/dist/query/index.js +0 -56
- package/dist/router-tanstack/field.d.ts +0 -14
- package/dist/router-tanstack/field.d.ts.map +0 -1
- package/dist/router-tanstack/field.js +0 -4
- package/dist/router-tanstack/multi-search-param-store.d.ts +0 -43
- package/dist/router-tanstack/multi-search-param-store.d.ts.map +0 -1
- package/dist/router-tanstack/multi-search-param-store.js +0 -30
- package/dist/router-tanstack/search-param-store.d.ts +0 -42
- package/dist/router-tanstack/search-param-store.d.ts.map +0 -1
- package/dist/router-tanstack/search-param-store.js +0 -25
- package/dist/section/index.d.ts +0 -2
- package/dist/section/index.d.ts.map +0 -1
- package/dist/section/index.js +0 -4
- package/dist/theme-toggle/index.d.ts.map +0 -1
- package/dist/utils/is-dev.d.ts.map +0 -1
- package/dist/widget-header/delta-badge.d.ts +0 -19
- package/dist/widget-header/delta-badge.d.ts.map +0 -1
- package/dist/widget-header/delta-badge.js +0 -36
- package/dist/widget-header/index.d.ts +0 -3
- package/dist/widget-header/index.d.ts.map +0 -1
- package/dist/widget-header/index.js +0 -8
- package/dist/widget-header/widget-header.d.ts.map +0 -1
- package/src/connectivity/index.ts +0 -19
- package/src/data/index.ts +0 -69
- package/src/notifications/overlay.tsx +0 -66
- package/src/query/error-message.ts +0 -70
- package/src/query/index.ts +0 -97
- package/src/router-tanstack/field.ts +0 -36
- package/src/router-tanstack/multi-search-param-store.ts +0 -106
- package/src/router-tanstack/search-param-store.ts +0 -100
- package/src/section/index.ts +0 -1
- package/src/widget-header/delta-badge.tsx +0 -77
- package/src/widget-header/index.ts +0 -10
- /package/dist/{utils → common}/is-dev.d.ts +0 -0
- /package/dist/{utils → common}/is-dev.js +0 -0
- /package/dist/{motion/index.js → common/motion.js} +0 -0
- /package/dist/{section → dashboard}/section.module.css +0 -0
- /package/dist/{section → dashboard}/section.module.css.d.ts +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.d.ts +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.js +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.module.css +0 -0
- /package/dist/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
- /package/dist/{connectivity → provider}/connectivity-indicator.d.ts +0 -0
- /package/dist/{connectivity → provider}/connectivity-indicator.js +0 -0
- /package/dist/{connectivity → provider}/connectivity-provider.js +0 -0
- /package/dist/{connectivity/types.js → provider/connectivity-types.js} +0 -0
- /package/dist/{connectivity → provider}/use-connectivity.js +0 -0
- /package/dist/{query/devtools.js → query-devtools.js} +0 -0
- /package/dist/{nav/types.js → shell/nav-types.js} +0 -0
- /package/src/{utils → common}/is-dev.ts +0 -0
- /package/src/{motion/index.ts → common/motion.ts} +0 -0
- /package/src/{section → dashboard}/section.module.css +0 -0
- /package/src/{section → dashboard}/section.module.css.d.ts +0 -0
- /package/src/{widget-header → dashboard}/widget-header.module.css +0 -0
- /package/src/{widget-header → dashboard}/widget-header.module.css.d.ts +0 -0
- /package/src/{widget-header → dashboard}/widget-header.tsx +0 -0
- /package/src/{connectivity/types.ts → provider/connectivity-types.ts} +0 -0
- /package/src/{nav/types.ts → shell/nav-types.ts} +0 -0
|
@@ -18,6 +18,7 @@ import basaltPlugin, {
|
|
|
18
18
|
KNOWN_RULE_IDS,
|
|
19
19
|
PLUGIN_RULE_ADVISORY,
|
|
20
20
|
PLUGIN_RULE_GRACE,
|
|
21
|
+
RETIRED_RULE_IDS,
|
|
21
22
|
} from './oxlint-plugin.js'
|
|
22
23
|
import { CTL_THEME } from '../src/theme/ctl-theme'
|
|
23
24
|
import { GUARD_RULES, PLUGIN_RULE_IDS } from '../src/guard/index.ts'
|
|
@@ -37,8 +38,6 @@ beforeEach(() => {
|
|
|
37
38
|
jsPlugins: [PLUGIN_PATH],
|
|
38
39
|
rules: {
|
|
39
40
|
'basalt/provider-above-router': 'error',
|
|
40
|
-
'basalt/duplicate-notifications-mount': 'error',
|
|
41
|
-
'basalt/query-dual-import': 'error',
|
|
42
41
|
'basalt/query-fn-unwrap': 'error',
|
|
43
42
|
'basalt/deprecated-export': 'error',
|
|
44
43
|
'basalt/forms-field-key': 'error',
|
|
@@ -1511,9 +1510,15 @@ describe('KNOWN_RULE_IDS', () => {
|
|
|
1511
1510
|
// Deduped, because ONE id is deliberately in both registries: `in-body-page-title` is a plugin
|
|
1512
1511
|
// rule AND a guard kind (law C8 has an AST half and a text half), so one `theme-allow
|
|
1513
1512
|
// in-body-page-title — <why>` waives both lanes rather than needing a different word per lane.
|
|
1514
|
-
|
|
1513
|
+
// `RETIRED_RULE_IDS` adds a third component: an id that used to be a guard kind or a plugin
|
|
1514
|
+
// rule, is in neither live registry, and must still parse as a (dead) waiver rather than a typo.
|
|
1515
|
+
it('contains nothing else — it is exactly the union of the two registries plus retired ids', () => {
|
|
1515
1516
|
const expected = [
|
|
1516
|
-
...new Set([
|
|
1517
|
+
...new Set([
|
|
1518
|
+
...Object.keys(basaltPlugin.rules),
|
|
1519
|
+
...Object.keys(GUARD_RULES),
|
|
1520
|
+
...RETIRED_RULE_IDS,
|
|
1521
|
+
]),
|
|
1517
1522
|
].toSorted()
|
|
1518
1523
|
expect([...KNOWN_RULE_IDS].toSorted()).toEqual(expected)
|
|
1519
1524
|
})
|
|
@@ -1531,6 +1536,15 @@ describe('KNOWN_RULE_IDS', () => {
|
|
|
1531
1536
|
expect([id, PLUGIN_RULE_IDS.has(id) || Object.hasOwn(GUARD_RULES, id)]).toEqual([id, true])
|
|
1532
1537
|
}
|
|
1533
1538
|
})
|
|
1539
|
+
|
|
1540
|
+
// A retired id has to be classifiable too, on both sides — `RETIRED_RULE_IDS` is this plugin's
|
|
1541
|
+
// copy, `PLUGIN_RULE_IDS` (src/guard) is the guard's. Drift between them would mean
|
|
1542
|
+
// `--audit-allows` classifies a retired id one way from `check-theme` and another from oxlint.
|
|
1543
|
+
it('every retired id is in the guard’s PLUGIN_RULE_IDS too', () => {
|
|
1544
|
+
for (const id of RETIRED_RULE_IDS) {
|
|
1545
|
+
expect([id, PLUGIN_RULE_IDS.has(id)]).toEqual([id, true])
|
|
1546
|
+
}
|
|
1547
|
+
})
|
|
1534
1548
|
})
|
|
1535
1549
|
|
|
1536
1550
|
// ── theme-allow fails closed on a typo ─────────────────────────────────────────────────────────
|
|
@@ -3035,194 +3049,9 @@ describe('basalt/provider-above-router', () => {
|
|
|
3035
3049
|
})
|
|
3036
3050
|
})
|
|
3037
3051
|
|
|
3038
|
-
//
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
const IMPORTS =
|
|
3042
|
-
`import { BasaltOverlays } from 'basalt-ui/commands'\n` +
|
|
3043
|
-
`import { BasaltNotifications } from 'basalt-ui/notifications'\n`
|
|
3044
|
-
|
|
3045
|
-
it('flags both mounts in one file', () => {
|
|
3046
|
-
const { code, rules } = run(
|
|
3047
|
-
`${IMPORTS}export const App = () => (\n <BasaltOverlays notifications>\n` +
|
|
3048
|
-
` <BasaltNotifications />\n </BasaltOverlays>\n)\n`,
|
|
3049
|
-
)
|
|
3050
|
-
expect(code).toBe(1)
|
|
3051
|
-
expect(rules).toContain('duplicate-notifications-mount')
|
|
3052
|
-
})
|
|
3053
|
-
|
|
3054
|
-
// `notifications` defaults to TRUE, so the attribute being absent is the same defect.
|
|
3055
|
-
it('flags when BasaltOverlays writes no notifications prop at all', () => {
|
|
3056
|
-
const { code, rules } = run(
|
|
3057
|
-
`${IMPORTS}export const App = () => (\n <BasaltOverlays>\n` +
|
|
3058
|
-
` <BasaltNotifications />\n </BasaltOverlays>\n)\n`,
|
|
3059
|
-
)
|
|
3060
|
-
expect(code).toBe(1)
|
|
3061
|
-
expect(rules).toContain('duplicate-notifications-mount')
|
|
3062
|
-
})
|
|
3063
|
-
|
|
3064
|
-
it('does NOT flag when BasaltOverlays disables its notifications layer', () => {
|
|
3065
|
-
const { code, rules } = run(
|
|
3066
|
-
`${IMPORTS}export const App = () => (\n <BasaltOverlays notifications={false}>\n` +
|
|
3067
|
-
` <BasaltNotifications />\n </BasaltOverlays>\n)\n`,
|
|
3068
|
-
)
|
|
3069
|
-
expect(code).toBe(0)
|
|
3070
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3071
|
-
})
|
|
3072
|
-
|
|
3073
|
-
it('does NOT flag a standalone BasaltNotifications on its own', () => {
|
|
3074
|
-
const { code, rules } = run(
|
|
3075
|
-
`import { BasaltNotifications } from 'basalt-ui/notifications'\n` +
|
|
3076
|
-
`export const App = () => <BasaltNotifications />\n`,
|
|
3077
|
-
)
|
|
3078
|
-
expect(code).toBe(0)
|
|
3079
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3080
|
-
})
|
|
3081
|
-
|
|
3082
|
-
it("does NOT flag a consumer's own components of the same names", () => {
|
|
3083
|
-
const { code, rules } = run(
|
|
3084
|
-
`import { BasaltOverlays } from './overlays'\n` +
|
|
3085
|
-
`import { BasaltNotifications } from './notifications'\n` +
|
|
3086
|
-
`export const App = () => (\n <BasaltOverlays>\n <BasaltNotifications />\n` +
|
|
3087
|
-
` </BasaltOverlays>\n)\n`,
|
|
3088
|
-
)
|
|
3089
|
-
expect(code).toBe(0)
|
|
3090
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3091
|
-
})
|
|
3092
|
-
|
|
3093
|
-
it('honours a theme-allow naming the rule', () => {
|
|
3094
|
-
const { code, rules } = run(
|
|
3095
|
-
`${IMPORTS}export const App = () => (\n <BasaltOverlays notifications>\n` +
|
|
3096
|
-
` {/* theme-allow duplicate-notifications-mount — two roots, never both mounted */}\n` +
|
|
3097
|
-
` <BasaltNotifications />\n </BasaltOverlays>\n)\n`,
|
|
3098
|
-
)
|
|
3099
|
-
expect(code).toBe(0)
|
|
3100
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3101
|
-
})
|
|
3102
|
-
|
|
3103
|
-
// Two mounts WRITTEN, one mount RENDERED — the ternary is the shape a consumer reaches for while
|
|
3104
|
-
// migrating from the standalone layer to the composed one, and it was never a double mount.
|
|
3105
|
-
it('does NOT flag the two branches of one ternary', () => {
|
|
3106
|
-
const { code, rules } = run(
|
|
3107
|
-
`${IMPORTS}export const App = ({ composed }) => (\n` +
|
|
3108
|
-
` <div>{composed ? <BasaltOverlays /> : <BasaltNotifications />}</div>\n)\n`,
|
|
3109
|
-
)
|
|
3110
|
-
expect(code).toBe(0)
|
|
3111
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3112
|
-
})
|
|
3113
|
-
|
|
3114
|
-
it('does NOT flag the two operands of one logical expression', () => {
|
|
3115
|
-
const { code, rules } = run(
|
|
3116
|
-
`${IMPORTS}export const App = ({ composed }) => (\n` +
|
|
3117
|
-
` <div>{(composed && <BasaltOverlays />) || <BasaltNotifications />}</div>\n)\n`,
|
|
3118
|
-
)
|
|
3119
|
-
expect(code).toBe(0)
|
|
3120
|
-
expect(rules).not.toContain('duplicate-notifications-mount')
|
|
3121
|
-
})
|
|
3122
|
-
|
|
3123
|
-
// The exemption is the NEAREST common ancestor only. Two separate `&&` guards can both hold, so
|
|
3124
|
-
// this stays a finding — the pair is conditional, not exclusive.
|
|
3125
|
-
it('DOES flag two independently-guarded mounts under one parent', () => {
|
|
3126
|
-
const { code, rules } = run(
|
|
3127
|
-
`${IMPORTS}export const App = ({ a, b }) => (\n` +
|
|
3128
|
-
` <div>{a && <BasaltOverlays />}{b && <BasaltNotifications />}</div>\n)\n`,
|
|
3129
|
-
)
|
|
3130
|
-
expect(code).toBe(1)
|
|
3131
|
-
expect(rules).toContain('duplicate-notifications-mount')
|
|
3132
|
-
})
|
|
3133
|
-
|
|
3134
|
-
// One exclusive pair does not excuse a second, unconditional overlays mount.
|
|
3135
|
-
it('DOES flag when a NON-exclusive overlays mount also exists', () => {
|
|
3136
|
-
const { code, rules } = run(
|
|
3137
|
-
`${IMPORTS}export const App = ({ composed }) => (\n` +
|
|
3138
|
-
` <BasaltOverlays>\n` +
|
|
3139
|
-
` {composed ? <BasaltOverlays /> : <BasaltNotifications />}\n` +
|
|
3140
|
-
` </BasaltOverlays>\n)\n`,
|
|
3141
|
-
)
|
|
3142
|
-
expect(code).toBe(1)
|
|
3143
|
-
expect(rules).toContain('duplicate-notifications-mount')
|
|
3144
|
-
})
|
|
3145
|
-
})
|
|
3146
|
-
|
|
3147
|
-
// ── query-dual-import (F5) ───────────────────────────────────────────────────
|
|
3148
|
-
|
|
3149
|
-
describe('basalt/query-dual-import', () => {
|
|
3150
|
-
it('flags a file importing from both @tanstack/react-query and basalt-ui/query', () => {
|
|
3151
|
-
const { code, rules, output } = run(
|
|
3152
|
-
`import { useQuery } from '@tanstack/react-query'\n` +
|
|
3153
|
-
`import { unwrap } from 'basalt-ui/query'\n` +
|
|
3154
|
-
`export const useThing = () => useQuery({ queryKey: ['t'], queryFn: () => unwrap(get()) })\n`,
|
|
3155
|
-
)
|
|
3156
|
-
expect(code).toBe(1)
|
|
3157
|
-
expect(rules).toContain('query-dual-import')
|
|
3158
|
-
expect(output).toContain('Dual query import')
|
|
3159
|
-
})
|
|
3160
|
-
|
|
3161
|
-
// The softer half — the one that actually catches the drift, and why the rule is `warn`.
|
|
3162
|
-
it('flags a raw @tanstack/react-query import beside a basalt root import', () => {
|
|
3163
|
-
const { code, rules, output } = run(
|
|
3164
|
-
`import { useQuery } from '@tanstack/react-query'\n` +
|
|
3165
|
-
`import { QueryState } from 'basalt-ui'\n` +
|
|
3166
|
-
`export const useThing = () => useQuery({ queryKey: ['t'], queryFn: get })\n`,
|
|
3167
|
-
)
|
|
3168
|
-
expect(code).toBe(1)
|
|
3169
|
-
expect(rules).toContain('query-dual-import')
|
|
3170
|
-
expect(output).toContain('Raw @tanstack/react-query import')
|
|
3171
|
-
})
|
|
3172
|
-
|
|
3173
|
-
it('does NOT flag basalt-ui/query on its own', () => {
|
|
3174
|
-
const { code, rules } = run(
|
|
3175
|
-
`import { useQuery, unwrap } from 'basalt-ui/query'\n` +
|
|
3176
|
-
`export const useThing = () => useQuery({ queryKey: ['t'], queryFn: () => unwrap(get()) })\n`,
|
|
3177
|
-
)
|
|
3178
|
-
expect(code).toBe(0)
|
|
3179
|
-
expect(rules).not.toContain('query-dual-import')
|
|
3180
|
-
})
|
|
3181
|
-
|
|
3182
|
-
// `import type` is erased at compile time — there is no runtime import to route through the
|
|
3183
|
-
// seam, and typing against the library's own result type is what `QueryStateLike` documents as
|
|
3184
|
-
// legitimate. Same skip `agent-no-raw-usechat` and `ai-sdk-major` take.
|
|
3185
|
-
it('does NOT flag a type-only @tanstack/react-query import beside basalt-ui/query', () => {
|
|
3186
|
-
const { code, rules } = run(
|
|
3187
|
-
`import type { UseQueryResult } from '@tanstack/react-query'\n` +
|
|
3188
|
-
`import { unwrap } from 'basalt-ui/query'\n` +
|
|
3189
|
-
`export const pick = (q: UseQueryResult<number>) => unwrap(q.data)\n`,
|
|
3190
|
-
)
|
|
3191
|
-
expect(code).toBe(0)
|
|
3192
|
-
expect(rules).not.toContain('query-dual-import')
|
|
3193
|
-
})
|
|
3194
|
-
|
|
3195
|
-
it('does NOT flag @tanstack/react-query in a file with no basalt import', () => {
|
|
3196
|
-
const { code, rules } = run(
|
|
3197
|
-
`import { useQuery } from '@tanstack/react-query'\n` +
|
|
3198
|
-
`export const useThing = () => useQuery({ queryKey: ['t'], queryFn: get })\n`,
|
|
3199
|
-
)
|
|
3200
|
-
expect(code).toBe(0)
|
|
3201
|
-
expect(rules).not.toContain('query-dual-import')
|
|
3202
|
-
})
|
|
3203
|
-
|
|
3204
|
-
// The devtools package is a different package, not a subpath.
|
|
3205
|
-
it('does NOT flag @tanstack/react-query-devtools', () => {
|
|
3206
|
-
const { code, rules } = run(
|
|
3207
|
-
`import { ReactQueryDevtools } from '@tanstack/react-query-devtools'\n` +
|
|
3208
|
-
`import { unwrap } from 'basalt-ui/query'\n` +
|
|
3209
|
-
`export const D = () => <ReactQueryDevtools />\n`,
|
|
3210
|
-
)
|
|
3211
|
-
expect(code).toBe(0)
|
|
3212
|
-
expect(rules).not.toContain('query-dual-import')
|
|
3213
|
-
})
|
|
3214
|
-
|
|
3215
|
-
it('honours a theme-allow naming the rule', () => {
|
|
3216
|
-
const { code, rules } = run(
|
|
3217
|
-
`// theme-allow query-dual-import — the persister API has no basalt re-export yet\n` +
|
|
3218
|
-
`import { useQuery } from '@tanstack/react-query'\n` +
|
|
3219
|
-
`import { unwrap } from 'basalt-ui/query'\n` +
|
|
3220
|
-
`export const useThing = () => useQuery({ queryKey: ['t'], queryFn: () => unwrap(g()) })\n`,
|
|
3221
|
-
)
|
|
3222
|
-
expect(code).toBe(0)
|
|
3223
|
-
expect(rules).not.toContain('query-dual-import')
|
|
3224
|
-
})
|
|
3225
|
-
})
|
|
3052
|
+
// `basalt/query-dual-import` is RETIRED (`RETIRED_RULE_IDS`) — its own describe block was removed
|
|
3053
|
+
// along with the rule; see `KNOWN_RULE_IDS` below for the coverage that remains: it is still a
|
|
3054
|
+
// valid (dead) `theme-allow` id, never a typo.
|
|
3226
3055
|
|
|
3227
3056
|
// ── query-fn-unwrap (F5) ─────────────────────────────────────────────────────
|
|
3228
3057
|
|
|
@@ -3295,80 +3124,8 @@ describe('basalt/query-fn-unwrap', () => {
|
|
|
3295
3124
|
|
|
3296
3125
|
// ── deprecated-export (B4) ───────────────────────────────────────────────────
|
|
3297
3126
|
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
const { code, rules, output } = run(
|
|
3301
|
-
`import { field } from 'basalt-ui/forms'\nexport const f = field\n`,
|
|
3302
|
-
)
|
|
3303
|
-
expect(code).toBe(1)
|
|
3304
|
-
expect(rules).toContain('deprecated-export')
|
|
3305
|
-
expect(output).toContain('inputProps')
|
|
3306
|
-
})
|
|
3307
|
-
|
|
3308
|
-
it('does NOT flag the replacement', () => {
|
|
3309
|
-
const { code, rules } = run(
|
|
3310
|
-
`import { inputProps } from 'basalt-ui/forms'\nexport const f = inputProps\n`,
|
|
3311
|
-
)
|
|
3312
|
-
expect(code).toBe(0)
|
|
3313
|
-
expect(rules).not.toContain('deprecated-export')
|
|
3314
|
-
})
|
|
3315
|
-
|
|
3316
|
-
it('does NOT flag a same-named import from somewhere else', () => {
|
|
3317
|
-
const { code, rules } = run(`import { field } from 'basalt-ui/state'\nexport const f = field\n`)
|
|
3318
|
-
expect(code).toBe(0)
|
|
3319
|
-
expect(rules).not.toContain('deprecated-export')
|
|
3320
|
-
})
|
|
3321
|
-
|
|
3322
|
-
it('flags each deprecated BasaltProvider connectivity prop', () => {
|
|
3323
|
-
const { code, rules, output } = run(
|
|
3324
|
-
`import { BasaltProvider } from 'basalt-ui'\n` +
|
|
3325
|
-
`export const App = () => (\n` +
|
|
3326
|
-
` <BasaltProvider sseUrl="/e" healthUrl="/h" healthIntervalMs={5000}>{null}</BasaltProvider>\n)\n`,
|
|
3327
|
-
)
|
|
3328
|
-
expect(code).toBe(1)
|
|
3329
|
-
expect(rules).toContain('deprecated-export')
|
|
3330
|
-
expect(output).toContain('connectivity')
|
|
3331
|
-
})
|
|
3332
|
-
|
|
3333
|
-
it('does NOT flag the connectivity object prop', () => {
|
|
3334
|
-
const { code, rules } = run(
|
|
3335
|
-
`import { BasaltProvider } from 'basalt-ui'\n` +
|
|
3336
|
-
`export const App = () => <BasaltProvider connectivity={{ sseUrl: '/e' }}>{null}</BasaltProvider>\n`,
|
|
3337
|
-
)
|
|
3338
|
-
expect(code).toBe(0)
|
|
3339
|
-
expect(rules).not.toContain('deprecated-export')
|
|
3340
|
-
})
|
|
3341
|
-
|
|
3342
|
-
it("does NOT flag an sseUrl on a consumer's own component", () => {
|
|
3343
|
-
const { code, rules } = run(
|
|
3344
|
-
`import { BasaltProvider } from './provider'\n` +
|
|
3345
|
-
`export const App = () => <BasaltProvider sseUrl="/e">{null}</BasaltProvider>\n`,
|
|
3346
|
-
)
|
|
3347
|
-
expect(code).toBe(0)
|
|
3348
|
-
expect(rules).not.toContain('deprecated-export')
|
|
3349
|
-
})
|
|
3350
|
-
|
|
3351
|
-
it('honours a theme-allow naming the rule', () => {
|
|
3352
|
-
const { code, rules } = run(
|
|
3353
|
-
`// theme-allow deprecated-export — pinned to 1.27.0 until the forms port lands\n` +
|
|
3354
|
-
`import { field } from 'basalt-ui/forms'\nexport const f = field\n`,
|
|
3355
|
-
)
|
|
3356
|
-
expect(code).toBe(0)
|
|
3357
|
-
expect(rules).not.toContain('deprecated-export')
|
|
3358
|
-
})
|
|
3359
|
-
|
|
3360
|
-
// `field` → `inputProps` is NOT a drop-in rename any more (`inputProps` returns no `key`), so
|
|
3361
|
-
// the row carries `fix: false`: the diagnostic still fires, but `--fix` must leave the import
|
|
3362
|
-
// alone — the rewrite belongs to `basalt/forms-field-key`, which also inserts the key.
|
|
3363
|
-
it('leaves a row with `fix: false` untouched under --fix while still reporting it', () => {
|
|
3364
|
-
const source = `import { field } from 'basalt-ui/forms'\nexport const f = field\n`
|
|
3365
|
-
writeFileSync(resolve(dir, 'fixture.tsx'), source)
|
|
3366
|
-
Bun.spawnSync([OXLINT_BIN, '-c', '.oxlintrc.json', '--fix', 'fixture.tsx'], { cwd: dir })
|
|
3367
|
-
expect(readFileSync(resolve(dir, 'fixture.tsx'), 'utf8')).toBe(source)
|
|
3368
|
-
const { rules } = run(source)
|
|
3369
|
-
expect(rules).toContain('deprecated-export')
|
|
3370
|
-
})
|
|
3371
|
-
})
|
|
3127
|
+
// deprecated-export's behaviour tests were removed with the last ledger row in 1.29.0; the
|
|
3128
|
+
// ledger-shape and barrel-scan assertions below keep the mechanism honest until the next row.
|
|
3372
3129
|
|
|
3373
3130
|
// ── forms-field-key ──────────────────────────────────────────────────────────
|
|
3374
3131
|
|
package/configs/oxlint.json
CHANGED
|
@@ -42,8 +42,6 @@
|
|
|
42
42
|
"basalt/search-literal-link": "error",
|
|
43
43
|
"basalt/use-search-from-literal": "error",
|
|
44
44
|
"basalt/provider-above-router": "warn",
|
|
45
|
-
"basalt/duplicate-notifications-mount": "warn",
|
|
46
|
-
"basalt/query-dual-import": "warn",
|
|
47
45
|
"basalt/query-fn-unwrap": "warn",
|
|
48
46
|
"basalt/deprecated-export": "warn",
|
|
49
47
|
"basalt/forms-field-key": "warn",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-sdk-transport.d.ts","sourceRoot":"","sources":["../../src/agent/ai-sdk-transport.ts"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAmB1D,MAAM,MAAM,qBAAqB,GAAG;IAClC,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAA;IACnD,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAA;IACzC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CACzC,CAAA;AAID,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG;IACvF;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CAC/E,CAAA;AAwRD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,GAAG,SAAS,EAC9C,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ai-sdk-transport.d.ts","sourceRoot":"","sources":["../../src/agent/ai-sdk-transport.ts"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAmB1D,MAAM,MAAM,qBAAqB,GAAG;IAClC,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAA;IACnD,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAA;IACzC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CACzC,CAAA;AAID,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG;IACvF;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CAC/E,CAAA;AAwRD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,GAAG,SAAS,EAC9C,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CAAC,KAAK,CAAC,CAyDvB"}
|
|
@@ -158,14 +158,17 @@ function aiSdkTransport(options) {
|
|
|
158
158
|
// diffPart), so a replayed run rewrites in place instead of duplicating — the literal
|
|
159
159
|
// condition this assertion stands for.
|
|
160
160
|
idempotentReplay: true,
|
|
161
|
-
async *stream(input, signal) {
|
|
161
|
+
async *stream(input, signal, ctx) {
|
|
162
162
|
yield { id: `${chatId}#start`, type: "start", runId: chatId, resumeToken: chatId };
|
|
163
163
|
const { httpTransport, readUIMessageStream: readStream } = await resolveAiSdk();
|
|
164
164
|
const userMessage = {
|
|
165
165
|
// This id is what AI SDK's own backend persistence/dedup keys turns hang off — the same
|
|
166
|
-
// idempotency-key cost as basalt's own ChatMessage.id (see mintMessageId's doc)
|
|
167
|
-
//
|
|
168
|
-
|
|
166
|
+
// idempotency-key cost as basalt's own ChatMessage.id (see mintMessageId's doc). Prefer
|
|
167
|
+
// the caller's OWN idempotency key (ctx.messageId — the id useAgentThreadRuns.start()
|
|
168
|
+
// already minted for this turn's ChatMessage) so the two never diverge for one turn; only
|
|
169
|
+
// a caller that omits ctx (useAgentStream, a hand-rolled stream() call) falls back to
|
|
170
|
+
// minting a fresh one here.
|
|
171
|
+
id: ctx?.messageId ?? mintMessageId(),
|
|
169
172
|
role: "user",
|
|
170
173
|
parts: [{ type: "text", text: input }]
|
|
171
174
|
};
|
package/dist/agent/coalesce.js
CHANGED
package/dist/agent/merge.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
import type { AgentPart, AgentPartDraft } from './parts.js';
|
|
33
33
|
/**
|
|
34
|
-
* The injected transport seam. `stream(input, signal)` returns an async generator of parts.
|
|
34
|
+
* The injected transport seam. `stream(input, signal, ctx)` returns an async generator of parts.
|
|
35
35
|
* Implement this interface for any backend — Eden, fetch-based SSE, AI SDK, or a mock.
|
|
36
36
|
*
|
|
37
37
|
* The default `TPart` is `AgentPartDraft` (not `AgentPart`): transports yield DRAFTS — `id`
|
|
@@ -39,6 +39,15 @@ import type { AgentPart, AgentPartDraft } from './parts.js';
|
|
|
39
39
|
* part before it is ever accumulated. Pass an explicit `AgentPart` generic when a transport mints
|
|
40
40
|
* its own ids directly (as `aiSdkTransport` does).
|
|
41
41
|
*
|
|
42
|
+
* `ctx.messageId`, when present, is the id `useAgentThreadRuns.start()` already minted for this
|
|
43
|
+
* turn's user `ChatMessage` — the SAME idempotency key `appendMessage`/the backend's dedup keys off
|
|
44
|
+
* of (see `mintMessageId`'s doc). A transport that mints its OWN wire-level message id independent
|
|
45
|
+
* of that (as `aiSdkTransport` used to) forces the consumer to reconcile two ids for one turn; a
|
|
46
|
+
* transport MAY use `ctx.messageId` as its outbound message id instead of minting a fresh one. The
|
|
47
|
+
* param is optional and appended last so an existing two-arg transport keeps compiling unchanged —
|
|
48
|
+
* only `useAgentThreadRuns.start()`/`retry()` pass it; a bare `stream(input, signal)` call (e.g.
|
|
49
|
+
* `useAgentStream`, a hand-rolled caller) omits it and a transport falls back to minting its own.
|
|
50
|
+
*
|
|
42
51
|
* @example
|
|
43
52
|
* // Minimal mock transport for tests / playground:
|
|
44
53
|
* const mockTransport: AgentTransport = {
|
|
@@ -48,7 +57,9 @@ import type { AgentPart, AgentPartDraft } from './parts.js';
|
|
|
48
57
|
* }
|
|
49
58
|
*/
|
|
50
59
|
export type AgentTransport<TPart = AgentPartDraft, TInput = string> = {
|
|
51
|
-
stream: (input: TInput, signal?: AbortSignal
|
|
60
|
+
stream: (input: TInput, signal?: AbortSignal, ctx?: {
|
|
61
|
+
readonly messageId: string;
|
|
62
|
+
}) => AsyncGenerator<TPart>;
|
|
52
63
|
/** Optional: resume a previously-started run from its resumeToken (see StartPart). Transports that don't support resumption simply omit this. */
|
|
53
64
|
resume?: (resumeToken: string, signal?: AbortSignal) => AsyncGenerator<TPart>;
|
|
54
65
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/agent/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAIxD
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/agent/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAIxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,cAAc,EAAE,MAAM,GAAG,MAAM,IAAI;IACpE,MAAM,EAAE,CACN,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,EACpB,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KACjC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC1B,iJAAiJ;IACjJ,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,cAAc,CAAC,KAAK,CAAC,CAAA;CAC9E,CAAA;AAID;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,CAAC,KAAK,GAAG,cAAc,EAAE,MAAM,GAAG,MAAM,IAAI,cAAc,CAC3F,KAAK,EACL,MAAM,CACP,GAAG;IACF,QAAQ,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,cAAc,CAAC,KAAK,CAAC,CAAA;IACrF,QAAQ,CAAC,gBAAgB,EAAE,IAAI,CAAA;CAChC,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EACvC,CAAC,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC/B,CAAC,IAAI,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAK7C;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAG,SAAS,EAAE,MAAM,GAAG,MAAM,EAC9D,IAAI,EAAE,CACJ,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,EACpE,UAAU,CAAC,EAAE,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,EACpE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAA;CAAE,GAC7C,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAsBxE"}
|
|
@@ -42,6 +42,17 @@ export type UseAgentThreadRunsArgs<TPart = AgentPart> = {
|
|
|
42
42
|
* Required when TPart is not the default AgentPart union.
|
|
43
43
|
*/
|
|
44
44
|
readonly toUserParts?: (input: string) => TPart[];
|
|
45
|
+
/**
|
|
46
|
+
* Called when a turn's stream throws — never for an `AbortError` (an intentional stop()/
|
|
47
|
+
* supersede, not a failure worth surfacing). Fires from the SAME catch branch that sets
|
|
48
|
+
* `onFailureStatus` on the thread, so a caller wanting a toast/notification for a genuine
|
|
49
|
+
* transport error (a 409/503/401, argo's hermes-chat S19) no longer has to wrap every transport
|
|
50
|
+
* call in its own generator to intercept the throw — see `consumeAndFinalize`'s catch block.
|
|
51
|
+
*/
|
|
52
|
+
readonly onError?: (info: {
|
|
53
|
+
readonly threadId: string;
|
|
54
|
+
readonly error: unknown;
|
|
55
|
+
}) => void;
|
|
45
56
|
};
|
|
46
57
|
export type UseAgentThreadRunsReturn<TPart = AgentPart> = {
|
|
47
58
|
/** Live stream state per thread id, for threads with a run in progress or just completed. */
|
|
@@ -95,5 +106,5 @@ export type UseAgentThreadRunsReturn<TPart = AgentPart> = {
|
|
|
95
106
|
* start(threadB, 'What changed in the last release?')
|
|
96
107
|
* // both stream concurrently; runs.get(threadA) / runs.get(threadB) update independently
|
|
97
108
|
*/
|
|
98
|
-
export declare function useAgentThreadRuns<TPart extends PartLike = AgentPart>({ transport, store, resolveOutcome, toUserParts, }: UseAgentThreadRunsArgs<TPart>): UseAgentThreadRunsReturn<TPart>;
|
|
109
|
+
export declare function useAgentThreadRuns<TPart extends PartLike = AgentPart>({ transport, store, resolveOutcome, toUserParts, onError, }: UseAgentThreadRunsArgs<TPart>): UseAgentThreadRunsReturn<TPart>;
|
|
99
110
|
//# sourceMappingURL=use-agent-thread-runs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,SAAS,IAAI;IACtD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EACd,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC7B,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAC/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"use-agent-thread-runs.d.ts","sourceRoot":"","sources":["../../src/agent/use-agent-thread-runs.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACvC,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,GAAG,SAAS,IAAI;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,SAAS,IAAI;IACtD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EACd,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAC7B,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IAC/C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,EAAE,CAAA;IACjD;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;CAC1F,CAAA;AAID,MAAM,MAAM,wBAAwB,CAAC,KAAK,GAAG,SAAS,IAAI;IACxD,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACzD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAC7B,CAAA;AA0RD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,QAAQ,GAAG,SAAS,EAAE,EACrE,SAAS,EACT,KAAK,EACL,cAAc,EACd,WAAW,EACX,OAAO,GACR,EAAE,sBAAsB,CAAC,KAAK,CAAC,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAsUjE"}
|
|
@@ -37,7 +37,8 @@ async function consumeAndFinalize(args) {
|
|
|
37
37
|
storeRef,
|
|
38
38
|
resolveOutcome,
|
|
39
39
|
setRuns,
|
|
40
|
-
onFailureStatus
|
|
40
|
+
onFailureStatus,
|
|
41
|
+
onError
|
|
41
42
|
} = args;
|
|
42
43
|
let parts = [];
|
|
43
44
|
try {
|
|
@@ -99,6 +100,7 @@ async function consumeAndFinalize(args) {
|
|
|
99
100
|
next.delete(threadId);
|
|
100
101
|
return next;
|
|
101
102
|
});
|
|
103
|
+
onError?.({ threadId, error: err });
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
async function finalizeStop(args) {
|
|
@@ -149,11 +151,14 @@ function useAgentThreadRuns({
|
|
|
149
151
|
transport,
|
|
150
152
|
store,
|
|
151
153
|
resolveOutcome,
|
|
152
|
-
toUserParts
|
|
154
|
+
toUserParts,
|
|
155
|
+
onError
|
|
153
156
|
}) {
|
|
154
157
|
const [runs, setRuns] = useState(/* @__PURE__ */ new Map());
|
|
155
158
|
const runsRef = useRef(runs);
|
|
156
159
|
runsRef.current = runs;
|
|
160
|
+
const onErrorRef = useRef(onError);
|
|
161
|
+
onErrorRef.current = onError;
|
|
157
162
|
const controllersRef = useRef(/* @__PURE__ */ new Map());
|
|
158
163
|
const appendedRef = useRef(/* @__PURE__ */ new Map());
|
|
159
164
|
const lastInputRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -194,6 +199,7 @@ function useAgentThreadRuns({
|
|
|
194
199
|
[]
|
|
195
200
|
);
|
|
196
201
|
useEffect(() => {
|
|
202
|
+
if (!store.hydrated) return;
|
|
197
203
|
for (const thread of storeRef.current.threads) {
|
|
198
204
|
const orphaned = (thread.status === "pending" || thread.status === "streaming") && !controllersRef.current.has(thread.id);
|
|
199
205
|
if (!orphaned) continue;
|
|
@@ -229,10 +235,11 @@ function useAgentThreadRuns({
|
|
|
229
235
|
storeRef,
|
|
230
236
|
resolveOutcome,
|
|
231
237
|
setRuns,
|
|
232
|
-
onFailureStatus: "interrupted"
|
|
238
|
+
onFailureStatus: "interrupted",
|
|
239
|
+
onError: (info) => onErrorRef.current?.(info)
|
|
233
240
|
});
|
|
234
241
|
}
|
|
235
|
-
}, []);
|
|
242
|
+
}, [store.hydrated]);
|
|
236
243
|
const start = useCallback(
|
|
237
244
|
(threadId, input) => {
|
|
238
245
|
if (controllersRef.current.has(threadId)) return;
|
|
@@ -258,14 +265,21 @@ function useAgentThreadRuns({
|
|
|
258
265
|
threadId,
|
|
259
266
|
controller,
|
|
260
267
|
// Namespaced by threadId — same choice, same caveat, as the mount-time resume call above.
|
|
261
|
-
|
|
268
|
+
// ctx.messageId is this turn's OWN idempotency key (userMessage.id, just minted above) —
|
|
269
|
+
// a transport that accepts it (aiSdkTransport) mints its wire-level message with the SAME
|
|
270
|
+
// id instead of a second, unrelated one (R1 — see AgentTransport.stream's doc).
|
|
271
|
+
generator: withPartIds(
|
|
272
|
+
threadId,
|
|
273
|
+
resolvedTransport.stream(input, controller.signal, { messageId: userMessage.id })
|
|
274
|
+
),
|
|
262
275
|
userMessage,
|
|
263
276
|
controllersRef,
|
|
264
277
|
appendedRef,
|
|
265
278
|
storeRef,
|
|
266
279
|
resolveOutcome,
|
|
267
280
|
setRuns,
|
|
268
|
-
onFailureStatus: "error"
|
|
281
|
+
onFailureStatus: "error",
|
|
282
|
+
onError: (info) => onErrorRef.current?.(info)
|
|
269
283
|
});
|
|
270
284
|
},
|
|
271
285
|
[resolveOutcome]
|
|
@@ -17,7 +17,7 @@ export type { ThreadFeedProps } from './thread-feed.js';
|
|
|
17
17
|
export { ThreadFeedRow } from './thread-feed-row.js';
|
|
18
18
|
export type { ThreadFeedRowProps } from './thread-feed-row.js';
|
|
19
19
|
export type { MessageAffordances } from './message-affordances.js';
|
|
20
|
-
export type { VirtualizeOptions, VirtualizeProps } from './virtualize.js';
|
|
20
|
+
export type { RowHeightProps, VirtualizeOptions, VirtualizeProps } from './virtualize.js';
|
|
21
21
|
export { ThreadOutcomeCard } from './thread-outcome-card.js';
|
|
22
22
|
export type { ThreadOutcomeCardProps } from './thread-outcome-card.js';
|
|
23
23
|
export { ThreadDetailPanel } from './thread-detail-panel.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAS3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGnG,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAG7D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -4,7 +4,7 @@ import { useReducedMotion } from "@mantine/hooks";
|
|
|
4
4
|
import { motion } from "motion/react";
|
|
5
5
|
import { BasaltStickToBottom } from "../agent/index.js";
|
|
6
6
|
import { cx } from "../common/props.js";
|
|
7
|
-
import { MOTION_SPRING } from "../motion
|
|
7
|
+
import { MOTION_SPRING } from "../common/motion.js";
|
|
8
8
|
import { Composer } from "./composer.js";
|
|
9
9
|
import { ThreadTranscript } from "./thread-message.js";
|
|
10
10
|
import { VX } from "../tokens/index.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { JSX } from 'react';
|
|
2
|
-
import type { AgentThread, ForeignPart, PartRenderer, PartRenderers, StreamStatus, TranscriptPart } from '../agent/index.js';
|
|
3
|
-
import type { BasaltProps } from '../common/props.js';
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
import type { AgentThread, ChatMessage, ForeignPart, PartRenderer, PartRenderers, StreamStatus, TranscriptPart } from '../agent/index.js';
|
|
3
|
+
import type { BasaltProps, SlotStylesProps } from '../common/props.js';
|
|
4
4
|
import type { ComposerProps, ComposerSubmit } from './composer.js';
|
|
5
5
|
import type { MessageAffordances } from './message-affordances.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { RowHeightProps } from './virtualize.js';
|
|
7
7
|
type ThreadFeedRowBase = {
|
|
8
8
|
/**
|
|
9
9
|
* The thread this row projects. Typed against `AgentThread<TranscriptPart>` — not the plain,
|
|
@@ -19,6 +19,30 @@ type ThreadFeedRowBase = {
|
|
|
19
19
|
readonly expanded: boolean;
|
|
20
20
|
/** Called with the thread's id when the header is clicked/activated. */
|
|
21
21
|
readonly onToggle: (id: string) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Header title override. Falls back to `thread.outcome?.title ?? 'Untitled thread'` (today's
|
|
24
|
+
* behavior, unchanged) when omitted. For a server-titled thread whose title is never distilled
|
|
25
|
+
* into a basalt `AgentOutcome` (argo's hermes-chat S4 — title/summary/type/pin are server-owned
|
|
26
|
+
* and never guessed client-side), pass it directly instead of forcing an outcome shape onto data
|
|
27
|
+
* that never had one.
|
|
28
|
+
*/
|
|
29
|
+
readonly title?: string;
|
|
30
|
+
/** Header summary override, same fallback rule as `title` (`thread.outcome?.summary ?? ''`). */
|
|
31
|
+
readonly summary?: string;
|
|
32
|
+
/** Rendered at the START of the header row, before the title/summary stack — a pin icon, a type
|
|
33
|
+
* badge (argo's hermes-chat S5). Absent by default; renders nothing extra when omitted. */
|
|
34
|
+
readonly headerLeft?: ReactNode;
|
|
35
|
+
/** Rendered at the END of the header row, before the timestamp and chevron — a collapsed-only
|
|
36
|
+
* streaming indicator (argo's hermes-chat S5). Absent by default; renders nothing extra when
|
|
37
|
+
* omitted. */
|
|
38
|
+
readonly headerRight?: ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* Overrides the transcript source: when provided, the row renders THESE messages instead of
|
|
41
|
+
* reading `thread.messages` directly (argo's hermes-chat S6 — the confirmed transcript is an
|
|
42
|
+
* optimistic-overlay MERGE over the store's messages, not the store's messages verbatim).
|
|
43
|
+
* Defaults to `thread.messages`.
|
|
44
|
+
*/
|
|
45
|
+
readonly messages?: readonly ChatMessage<TranscriptPart>[];
|
|
22
46
|
/** The live (in-flight) assistant turn's parts, when a run is streaming for this thread. */
|
|
23
47
|
readonly liveParts?: readonly TranscriptPart[];
|
|
24
48
|
/** The live run's status — drives the in-progress indicator on the live block. */
|
|
@@ -49,10 +73,11 @@ type ThreadFeedRowBase = {
|
|
|
49
73
|
* `virtualize`/`height` are forwarded straight to the row's `ThreadTranscript`, carrying the same
|
|
50
74
|
* union guard: an inline row holding a very long thread can window it, and doing so REQUIRES a
|
|
51
75
|
* `height` (the transcript then owns a fixed-height scroll node inside the expanded body, instead
|
|
52
|
-
* of the body growing to the thread's full length).
|
|
53
|
-
*
|
|
76
|
+
* of the body growing to the thread's full length). `height` alone (no `virtualize`) is B3's
|
|
77
|
+
* bounded-but-not-virtualized mode — see `RowHeightProps`'s own doc. Omit both and the row's
|
|
78
|
+
* transcript is content-sized, as before.
|
|
54
79
|
*/
|
|
55
|
-
export type ThreadFeedRowProps = ThreadFeedRowBase &
|
|
80
|
+
export type ThreadFeedRowProps = ThreadFeedRowBase & RowHeightProps & SlotStylesProps<'root' | 'header' | 'body'> & BasaltProps;
|
|
56
81
|
/**
|
|
57
82
|
* One inline-expanding thread row: a header (title + relative timestamp) that toggles a lazily
|
|
58
83
|
* mounted, kept-mounted transcript + composer body. See the module doc for the mount lifecycle
|