basalt-ui 1.10.0 → 1.12.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/AGENTS.md +21 -21
- package/CHANGELOG.md +25 -0
- package/README.md +36 -27
- package/agent/rules/basalt-content.md +16 -3
- package/dist/agent/adapter.d.ts +146 -0
- package/dist/agent/adapter.d.ts.map +1 -0
- package/dist/agent/adapter.js +473 -0
- package/dist/agent/adapter.test.d.ts +2 -0
- package/dist/agent/adapter.test.d.ts.map +1 -0
- package/dist/agent/ai-sdk-transport.d.ts +3 -52
- package/dist/agent/ai-sdk-transport.d.ts.map +1 -1
- package/dist/agent/ai-sdk-transport.js +108 -24
- package/dist/agent/ai-sdk-transport.test.d.ts +2 -0
- package/dist/agent/ai-sdk-transport.test.d.ts.map +1 -0
- package/dist/agent/coalesce.d.ts +42 -0
- package/dist/agent/coalesce.d.ts.map +1 -0
- package/dist/agent/coalesce.js +137 -0
- package/dist/agent/coalesce.test.d.ts +2 -0
- package/dist/agent/coalesce.test.d.ts.map +1 -0
- package/dist/agent/foreign.d.ts +97 -0
- package/dist/agent/foreign.d.ts.map +1 -0
- package/dist/agent/foreign.js +18 -0
- package/dist/agent/foreign.test.d.ts +2 -0
- package/dist/agent/foreign.test.d.ts.map +1 -0
- package/dist/agent/history.d.ts +2 -0
- package/dist/agent/history.d.ts.map +1 -1
- package/dist/agent/id.d.ts +65 -0
- package/dist/agent/id.d.ts.map +1 -0
- package/dist/agent/id.js +30 -0
- package/dist/agent/id.test.d.ts +2 -0
- package/dist/agent/id.test.d.ts.map +1 -0
- package/dist/agent/index.d.ts +11 -4
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +18 -3
- package/dist/agent/merge.d.ts +8 -0
- package/dist/agent/merge.d.ts.map +1 -0
- package/dist/agent/merge.js +35 -0
- package/dist/agent/merge.test.d.ts +2 -0
- package/dist/agent/merge.test.d.ts.map +1 -0
- package/dist/agent/part-list.d.ts +49 -34
- package/dist/agent/part-list.d.ts.map +1 -1
- package/dist/agent/part-list.js +53 -7
- package/dist/agent/part-list.test.d.ts +2 -0
- package/dist/agent/part-list.test.d.ts.map +1 -0
- package/dist/agent/parts.d.ts +135 -20
- package/dist/agent/parts.d.ts.map +1 -1
- package/dist/agent/parts.js +138 -11
- package/dist/agent/parts.test.d.ts +2 -0
- package/dist/agent/parts.test.d.ts.map +1 -0
- package/dist/agent/thread.d.ts +14 -0
- package/dist/agent/thread.d.ts.map +1 -1
- package/dist/agent/thread.js +8 -2
- package/dist/agent/thread.test.d.ts +2 -0
- package/dist/agent/thread.test.d.ts.map +1 -0
- package/dist/agent/transport.d.ts +39 -3
- package/dist/agent/transport.d.ts.map +1 -1
- package/dist/agent/transport.js +20 -17
- package/dist/agent/transport.test.d.ts +2 -0
- package/dist/agent/transport.test.d.ts.map +1 -0
- package/dist/agent/use-agent-stream.d.ts +2 -1
- package/dist/agent/use-agent-stream.d.ts.map +1 -1
- package/dist/agent/use-agent-stream.js +5 -2
- package/dist/agent/use-agent-stream.test.d.ts +2 -0
- package/dist/agent/use-agent-stream.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.d.ts +9 -3
- package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.foreign.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.js +75 -23
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.resume.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.test.d.ts.map +1 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts +2 -0
- package/dist/agent/use-agent-thread-runs.wedge.test.d.ts.map +1 -0
- package/dist/agent-chat/composer.d.ts +130 -8
- package/dist/agent-chat/composer.d.ts.map +1 -1
- package/dist/agent-chat/composer.js +189 -23
- package/dist/agent-chat/composer.test.d.ts +2 -0
- package/dist/agent-chat/composer.test.d.ts.map +1 -0
- package/dist/agent-chat/index.d.ts +3 -1
- package/dist/agent-chat/index.d.ts.map +1 -1
- package/dist/agent-chat/index.js +2 -0
- package/dist/agent-chat/thread-detail-panel.d.ts.map +1 -1
- package/dist/agent-chat/thread-detail-panel.js +1 -1
- package/dist/agent-chat/thread-message.d.ts +24 -7
- package/dist/agent-chat/thread-message.d.ts.map +1 -1
- package/dist/agent-chat/thread-message.js +115 -45
- package/dist/agent-chat/thread-message.test.d.ts +2 -0
- package/dist/agent-chat/thread-message.test.d.ts.map +1 -0
- package/dist/agent-chat/thread-workspace.js +1 -1
- package/dist/agent-chat/tool-chip.d.ts +21 -0
- package/dist/agent-chat/tool-chip.d.ts.map +1 -0
- package/dist/agent-chat/tool-chip.js +120 -0
- package/dist/agent-chat/tool-chip.test.d.ts +2 -0
- package/dist/agent-chat/tool-chip.test.d.ts.map +1 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts +2 -0
- package/dist/charts/primitives/ChartFrame.test.d.ts.map +1 -0
- package/dist/charts/utils/domain.test.d.ts +2 -0
- package/dist/charts/utils/domain.test.d.ts.map +1 -0
- package/dist/cli/check-theme.test.d.ts +2 -0
- package/dist/cli/check-theme.test.d.ts.map +1 -0
- package/dist/cli/help.test.d.ts +2 -0
- package/dist/cli/help.test.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/init-sync.test.d.ts +2 -0
- package/dist/cli/init-sync.test.d.ts.map +1 -0
- package/dist/cli/placement-engine.test.d.ts +2 -0
- package/dist/cli/placement-engine.test.d.ts.map +1 -0
- package/dist/cli/tarball-parity.test.d.ts +2 -0
- package/dist/cli/tarball-parity.test.d.ts.map +1 -0
- package/dist/cli/template-format.test.d.ts +2 -0
- package/dist/cli/template-format.test.d.ts.map +1 -0
- package/dist/cli/template-ledger.test.d.ts +2 -0
- package/dist/cli/template-ledger.test.d.ts.map +1 -0
- package/dist/cli/tokens-css.test.d.ts +2 -0
- package/dist/cli/tokens-css.test.d.ts.map +1 -0
- package/dist/content/article-actions.test.d.ts +2 -0
- package/dist/content/article-actions.test.d.ts.map +1 -0
- package/dist/content/article-model.test.d.ts +2 -0
- package/dist/content/article-model.test.d.ts.map +1 -0
- package/dist/content/block-split.test.d.ts +2 -0
- package/dist/content/block-split.test.d.ts.map +1 -0
- package/dist/content/fence-block.d.ts +37 -10
- package/dist/content/fence-block.d.ts.map +1 -1
- package/dist/content/fence-block.js +80 -14
- package/dist/content/heading-components.d.ts.map +1 -1
- package/dist/content/heading-components.js +7 -4
- package/dist/content/heading-components.test.d.ts +2 -0
- package/dist/content/heading-components.test.d.ts.map +1 -0
- package/dist/content/index.d.ts +6 -3
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +5 -1
- package/dist/content/markdown.d.ts +101 -14
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +141 -28
- package/dist/content/markdown.test.d.ts +2 -0
- package/dist/content/markdown.test.d.ts.map +1 -0
- package/dist/content/prose.module.css.test.d.ts +2 -0
- package/dist/content/prose.module.css.test.d.ts.map +1 -0
- package/dist/content/sanitize.d.ts +170 -0
- package/dist/content/sanitize.d.ts.map +1 -0
- package/dist/content/sanitize.js +178 -0
- package/dist/content/sanitize.test.d.ts +2 -0
- package/dist/content/sanitize.test.d.ts.map +1 -0
- package/dist/content/slug.test.d.ts +2 -0
- package/dist/content/slug.test.d.ts.map +1 -0
- package/dist/dashboard/stat-card.test.d.ts +2 -0
- package/dist/dashboard/stat-card.test.d.ts.map +1 -0
- package/dist/guard/check-source.test.d.ts +2 -0
- package/dist/guard/check-source.test.d.ts.map +1 -0
- package/dist/guard/guard-hook.test.d.ts +2 -0
- package/dist/guard/guard-hook.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +1 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/provider/index.test.d.ts +2 -0
- package/dist/provider/index.test.d.ts.map +1 -0
- package/dist/provider/lab-theme.test.d.ts +2 -0
- package/dist/provider/lab-theme.test.d.ts.map +1 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts +2 -0
- package/dist/router-tanstack/multi-search-param-store.test.d.ts.map +1 -0
- package/dist/styles.floor.test.d.ts +2 -0
- package/dist/styles.floor.test.d.ts.map +1 -0
- package/dist/surfaces.d.ts +5 -5
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +13 -4
- package/dist/theme/border-coverage.test.d.ts +18 -0
- package/dist/theme/border-coverage.test.d.ts.map +1 -0
- package/dist/theme/contrast.test.d.ts +2 -0
- package/dist/theme/contrast.test.d.ts.map +1 -0
- package/dist/theme/density-option.test.d.ts +2 -0
- package/dist/theme/density-option.test.d.ts.map +1 -0
- package/dist/theme/density-relations.test.d.ts +2 -0
- package/dist/theme/density-relations.test.d.ts.map +1 -0
- package/dist/theme/derive-theme.test.d.ts +2 -0
- package/dist/theme/derive-theme.test.d.ts.map +1 -0
- package/dist/theme/fonts-option.test.d.ts +2 -0
- package/dist/theme/fonts-option.test.d.ts.map +1 -0
- package/dist/theme/radius-option.test.d.ts +2 -0
- package/dist/theme/radius-option.test.d.ts.map +1 -0
- package/dist/theme/radius.test.d.ts +2 -0
- package/dist/theme/radius.test.d.ts.map +1 -0
- package/dist/theme/shadow-surfaces.test.d.ts +26 -0
- package/dist/theme/shadow-surfaces.test.d.ts.map +1 -0
- package/dist/theme/spacing.test.d.ts +2 -0
- package/dist/theme/spacing.test.d.ts.map +1 -0
- package/dist/theme/use-basalt-spacing.test.d.ts +2 -0
- package/dist/theme/use-basalt-spacing.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-controls.test.d.ts +2 -0
- package/dist/theme-lab/derive-controls.test.d.ts.map +1 -0
- package/dist/theme-lab/derive-state.test.d.ts +2 -0
- package/dist/theme-lab/derive-state.test.d.ts.map +1 -0
- package/dist/theme-lab/theme-lab.test.d.ts +2 -0
- package/dist/theme-lab/theme-lab.test.d.ts.map +1 -0
- package/dist/tokens/build-fonts-css.test.d.ts +2 -0
- package/dist/tokens/build-fonts-css.test.d.ts.map +1 -0
- package/dist/tokens/build-radius-css.test.d.ts +2 -0
- package/dist/tokens/build-radius-css.test.d.ts.map +1 -0
- package/dist/tokens/density.test.d.ts +2 -0
- package/dist/tokens/density.test.d.ts.map +1 -0
- package/dist/tokens/derive-radius.test.d.ts +2 -0
- package/dist/tokens/derive-radius.test.d.ts.map +1 -0
- package/dist/tokens/derive.test.d.ts +2 -0
- package/dist/tokens/derive.test.d.ts.map +1 -0
- package/dist/tokens/palette.test.d.ts +2 -0
- package/dist/tokens/palette.test.d.ts.map +1 -0
- package/dist/vite-color-mix.test.d.ts +2 -0
- package/dist/vite-color-mix.test.d.ts.map +1 -0
- package/dist/vite.test.d.ts +2 -0
- package/dist/vite.test.d.ts.map +1 -0
- package/llms.txt +7 -7
- package/package.json +6 -1
- package/src/agent/adapter.test.ts +1403 -0
- package/src/agent/adapter.ts +887 -0
- package/src/agent/ai-sdk-transport.test.ts +380 -55
- package/src/agent/ai-sdk-transport.ts +206 -53
- package/src/agent/coalesce.test.ts +387 -0
- package/src/agent/coalesce.ts +229 -0
- package/src/agent/foreign.test.ts +51 -0
- package/src/agent/foreign.ts +140 -0
- package/src/agent/history.ts +2 -0
- package/src/agent/id.test.ts +75 -0
- package/src/agent/id.ts +91 -0
- package/src/agent/index.ts +34 -3
- package/src/agent/merge.test.ts +206 -0
- package/src/agent/merge.ts +114 -0
- package/src/agent/part-list.test.tsx +112 -0
- package/src/agent/part-list.tsx +108 -35
- package/src/agent/parts.test.ts +516 -57
- package/src/agent/parts.ts +323 -32
- package/src/agent/thread.test.ts +75 -2
- package/src/agent/thread.ts +21 -1
- package/src/agent/transport.test.ts +70 -0
- package/src/agent/transport.ts +72 -20
- package/src/agent/use-agent-stream.test.tsx +53 -19
- package/src/agent/use-agent-stream.ts +13 -3
- package/src/agent/use-agent-thread-runs.foreign.test.tsx +138 -0
- package/src/agent/use-agent-thread-runs.resume.test.tsx +44 -11
- package/src/agent/use-agent-thread-runs.test.tsx +418 -22
- package/src/agent/use-agent-thread-runs.ts +170 -26
- package/src/agent/use-agent-thread-runs.wedge.test.tsx +15 -7
- package/src/agent-chat/composer.test.tsx +924 -0
- package/src/agent-chat/composer.tsx +521 -52
- package/src/agent-chat/index.ts +5 -1
- package/src/agent-chat/thread-detail-panel.tsx +3 -1
- package/src/agent-chat/thread-message.test.tsx +351 -0
- package/src/agent-chat/thread-message.tsx +262 -64
- package/src/agent-chat/thread-workspace.tsx +1 -1
- package/src/agent-chat/tool-chip.test.tsx +139 -0
- package/src/agent-chat/tool-chip.tsx +219 -0
- package/src/cli/index.ts +0 -1
- package/src/cli/template-format.test.ts +2 -2
- package/src/content/fence-block.tsx +242 -15
- package/src/content/heading-components.test.tsx +65 -0
- package/src/content/heading-components.tsx +26 -5
- package/src/content/index.ts +19 -3
- package/src/content/markdown.test.tsx +603 -0
- package/src/content/markdown.tsx +355 -35
- package/src/content/sanitize.test.ts +659 -0
- package/src/content/sanitize.ts +510 -0
- package/src/dashboard/stat-card.test.tsx +6 -1
- package/src/guard/check-source.test.ts +8 -4
- package/src/guard/index.ts +1 -3
- package/src/index.ts +15 -1
- package/src/surfaces.ts +13 -4
- package/src/theme/contrast.test.ts +1 -4
- package/src/theme/density-relations.test.ts +4 -2
- package/src/theme/fonts-option.test.ts +7 -1
- package/src/theme/shadow-surfaces.test.ts +12 -6
- package/src/theme/use-basalt-spacing.test.tsx +2 -1
package/AGENTS.md
CHANGED
|
@@ -6,27 +6,27 @@ Toolchain: Bun runtime, oxlint + oxfmt, conventional commits (empty scope), `mas
|
|
|
6
6
|
|
|
7
7
|
## Subpath ownership
|
|
8
8
|
|
|
9
|
-
| Subpath | Layer | Purpose
|
|
10
|
-
| --------------------------- | --------------- |
|
|
11
|
-
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)
|
|
12
|
-
| `basalt-ui/charts` | headless | visx chart primitives, sparklines, hooks, and token re-exports (Mantine-free)
|
|
13
|
-
| `basalt-ui/tokens` | headless | VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free)
|
|
14
|
-
| `basalt-ui/theme-lab` | mantine-coupled | ThemeLabControls, applyOverrides, COLOR_GROUPS — a low-level inspector for the non-derived structural tokens; identity/color tuning lives in DeriveControls
|
|
15
|
-
| `basalt-ui/vite` | mantine-coupled | basaltViteConfig(opts) — Vite preset for basalt-ui consumer apps; basaltAppPlugin(opts) — PWA head, manifest, and icon metadata derived from the token palette
|
|
16
|
-
| `basalt-ui/guard` | headless | checkSource, GUARD_RULES, Finding types — the headless theme-guard core
|
|
17
|
-
| `basalt-ui/query` | headless | createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools
|
|
18
|
-
| `basalt-ui/router-tanstack` | headless | TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)
|
|
19
|
-
| `basalt-ui/forms` | mantine-coupled | Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema)
|
|
20
|
-
| `basalt-ui/notifications` | mantine-coupled | Mantine notifications: notify helpers, typed registry, persisted history, NotificationBell, NotificationCenter
|
|
21
|
-
| `basalt-ui/commands` | mantine-coupled | typed command bus + overlay controller, toSpotlightActions, ShortcutsHelp, BasaltOverlays
|
|
22
|
-
| `basalt-ui/data` | mantine-coupled | Convenience barrel pulling both TanStack Table + Virtual peer groups: BasaltDataTable, BasaltVirtualList (Mantine-rendered) — prefer ./data/table or ./data/virtual for per-feature opt-in
|
|
23
|
-
| `basalt-ui/data/table` | mantine-coupled | BasaltDataTable: a sortable data table over TanStack Table, rendered with Mantine (Mantine-rendered)
|
|
24
|
-
| `basalt-ui/data/virtual` | mantine-coupled | BasaltVirtualList: a windowed virtual list over TanStack Virtual, rendered with Mantine (Mantine-rendered)
|
|
25
|
-
| `basalt-ui/agent` | headless | Headless streaming-chat layer: useAgentStream, aiSdkTransport (recommended default) + edenTransport, PartList, plus the multi-thread createThreadsStore + useAgentThreadRuns + outcome-resolver seam (Mantine-free)
|
|
26
|
-
| `basalt-ui/agent-chat` | mantine-coupled | Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed, ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript, threadPartRenderers (Mantine-coupled).
|
|
27
|
-
| `basalt-ui/content` | mantine-coupled | Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers, streaming-
|
|
28
|
-
| `basalt-ui/state` | headless | createPersistedState (versioned localStorage) + useOnlineStatus — Mantine-free state primitives
|
|
29
|
-
| `basalt-ui/connectivity` | mantine-coupled | ConnectivityProvider (aggregates browser online/offline, React Query onlineManager, SSE, and health-check pings into one status), useConnectivity, and ConnectivityIndicator — auto-mounted by BasaltProvider
|
|
9
|
+
| Subpath | Layer | Purpose |
|
|
10
|
+
| --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
11
|
+
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone) |
|
|
12
|
+
| `basalt-ui/charts` | headless | visx chart primitives, sparklines, hooks, and token re-exports (Mantine-free) |
|
|
13
|
+
| `basalt-ui/tokens` | headless | VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free) |
|
|
14
|
+
| `basalt-ui/theme-lab` | mantine-coupled | ThemeLabControls, applyOverrides, COLOR_GROUPS — a low-level inspector for the non-derived structural tokens; identity/color tuning lives in DeriveControls |
|
|
15
|
+
| `basalt-ui/vite` | mantine-coupled | basaltViteConfig(opts) — Vite preset for basalt-ui consumer apps; basaltAppPlugin(opts) — PWA head, manifest, and icon metadata derived from the token palette |
|
|
16
|
+
| `basalt-ui/guard` | headless | checkSource, GUARD_RULES, Finding types — the headless theme-guard core |
|
|
17
|
+
| `basalt-ui/query` | headless | createBasaltQueryClient, transport-agnostic unwrap, lazy BasaltQueryDevtools |
|
|
18
|
+
| `basalt-ui/router-tanstack` | headless | TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store) |
|
|
19
|
+
| `basalt-ui/forms` | mantine-coupled | Mantine form adapter: useBasaltForm, field, FormErrorSummary, useFormDraft (Standard Schema) |
|
|
20
|
+
| `basalt-ui/notifications` | mantine-coupled | Mantine notifications: notify helpers, typed registry, persisted history, NotificationBell, NotificationCenter |
|
|
21
|
+
| `basalt-ui/commands` | mantine-coupled | typed command bus + overlay controller, toSpotlightActions, ShortcutsHelp, BasaltOverlays |
|
|
22
|
+
| `basalt-ui/data` | mantine-coupled | Convenience barrel pulling both TanStack Table + Virtual peer groups: BasaltDataTable, BasaltVirtualList (Mantine-rendered) — prefer ./data/table or ./data/virtual for per-feature opt-in |
|
|
23
|
+
| `basalt-ui/data/table` | mantine-coupled | BasaltDataTable: a sortable data table over TanStack Table, rendered with Mantine (Mantine-rendered) |
|
|
24
|
+
| `basalt-ui/data/virtual` | mantine-coupled | BasaltVirtualList: a windowed virtual list over TanStack Virtual, rendered with Mantine (Mantine-rendered) |
|
|
25
|
+
| `basalt-ui/agent` | headless | Headless streaming-chat layer: useAgentStream, aiSdkTransport (recommended default) + edenTransport, isResumable/ResumableAgentTransport (stream-resumption seam), PartList, coalesceParts, the ForeignPart/definePartRenderers/narrowAgentPart open part-registry seam, plus the multi-thread createThreadsStore + useAgentThreadRuns + outcome-resolver seam (Mantine-free) |
|
|
26
|
+
| `basalt-ui/agent-chat` | mantine-coupled | Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed, ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript (open part-renderer registry via its renderers/fallbackRenderer props), threadPartRenderers, ToolChip (Mantine-coupled). motion is required, not optional — ThreadFeed/ThreadDetailPanel import motion/react eagerly, so this subpath fails to resolve without it installed even though peerDependenciesMeta marks it optional (npm has no per-subpath optionality). remend is genuinely optional here — ThreadTranscript reaches it only through the lazy dynamic import() inside content/markdown.tsx. |
|
|
27
|
+
| `basalt-ui/content` | mantine-coupled | Prose (article/chat typography), CodeBlock (shiki, optional peer), Callout, TableOfContents, ReadingProgress, Markdown (react-markdown + remark-gfm, optional peers; `streaming` is a rendering mode ONLY — `contentTrust` is the independent security input, and any surface rendering agent/model output must pin `contentTrust="untrusted"`, the sole input to the image-origin allowlist; a `fenceRenderers` registry — settledOnly/FenceRenderer/FenceRenderers/FenceRenderContext; `sanitizeSchema`, an additions-only SanitizeSchemaExtension merged over BASALT_SANITIZE_SCHEMA via mergeSanitizeSchema; the remend streaming-repair pass is now a lazy optional peer), MermaidDiagram (beautiful-mermaid, optional peer), mdxComponents/createMdxComponents, ArticleLayout (docs-page frame), ArticleCard/ArticleGrid (overview cards), Article model (sortArticles/filterArticles/formatArticleDate), ArticleFilterBar (category/tags filter UI), toArticleActions (Spotlight projector, @mantine/spotlight type-only), GuideLink/GuideDrawer (contextual-help drawer) — the content/prose surface |
|
|
28
|
+
| `basalt-ui/state` | headless | createPersistedState (versioned localStorage) + useOnlineStatus — Mantine-free state primitives |
|
|
29
|
+
| `basalt-ui/connectivity` | mantine-coupled | ConnectivityProvider (aggregates browser online/offline, React Query onlineManager, SSE, and health-check pings into one status), useConnectivity, and ConnectivityIndicator — auto-mounted by BasaltProvider |
|
|
30
30
|
|
|
31
31
|
## Hard rules
|
|
32
32
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# [1.12.0](https://github.com/jkrumm/basalt-ui/compare/v1.11.0...v1.12.0) (2026-08-03)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* stop the tool-part fold carrying stale state and dropping parts ([d47a35f](https://github.com/jkrumm/basalt-ui/commit/d47a35f7d58d985037814b8771b0e426c5396403))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* give the composer its slots and a way to write into them ([e115b7e](https://github.com/jkrumm/basalt-ui/commit/e115b7efd428a09701307f9fe7448f72e69606bb))
|
|
12
|
+
* let a server-backed store stand behind the threads API ([dfdf9c5](https://github.com/jkrumm/basalt-ui/commit/dfdf9c543554167ff9d780dda2cb662238eff419))
|
|
13
|
+
* open the markdown seams and split trust from streaming ([90d406e](https://github.com/jkrumm/basalt-ui/commit/90d406e13311a107a6a160d8f66ff42e41085a75))
|
|
14
|
+
* prove the 1.12.0 seams from outside the package ([0231345](https://github.com/jkrumm/basalt-ui/commit/0231345f88f9d8f7191db6c733ac124d5fae85fd))
|
|
15
|
+
|
|
16
|
+
# [1.11.0](https://github.com/jkrumm/basalt-ui/compare/v1.10.0...v1.11.0) (2026-08-03)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* give every part a stable id and mirror v7's real tool lifecycle ([d63aac3](https://github.com/jkrumm/basalt-ui/commit/d63aac3267d2322dfd027ba9b78e730eeec95d30))
|
|
22
|
+
* make the transcript addressable, open, and honest about how a turn ended ([f153107](https://github.com/jkrumm/basalt-ui/commit/f1531077b411517226d2f349970677951d95bd59))
|
|
23
|
+
* promote the shade-index guard out of its grace period ([e6a7bf9](https://github.com/jkrumm/basalt-ui/commit/e6a7bf919a1c28246157f918b5462311b37bc192))
|
|
24
|
+
* prove the transcript layer from outside the package boundary ([52bd6d2](https://github.com/jkrumm/basalt-ui/commit/52bd6d2965e780d9d11008c6c449120285983c76))
|
|
25
|
+
|
|
1
26
|
# [1.10.0](https://github.com/jkrumm/basalt-ui/compare/v1.9.0...v1.10.0) (2026-08-02)
|
|
2
27
|
|
|
3
28
|
|
package/README.md
CHANGED
|
@@ -236,7 +236,7 @@ deleted rather than silently surviving into the next real skew.
|
|
|
236
236
|
| `./data/table` | coupled | `BasaltDataTable` — sortable data table over TanStack Table, rendered with Mantine |
|
|
237
237
|
| `./data/virtual` | coupled | `BasaltVirtualList` — windowed virtual list over TanStack Virtual, rendered with Mantine |
|
|
238
238
|
| `./agent` | **free** | Headless streaming layer (`useAgentStream`, `PartList`) + multi-thread `createThreadsStore` / `useAgentThreadRuns` / outcome seam |
|
|
239
|
-
| `./agent-chat` | coupled | Mantine-styled thread-chat components over `./agent`: `ThreadWorkspace`, `ThreadFeed`, `ThreadOutcomeCard`, `ThreadDetailPanel`, `Composer`, `ThreadTranscript`, `threadPartRenderers` — **requires `
|
|
239
|
+
| `./agent-chat` | coupled | Mantine-styled thread-chat components over `./agent`: `ThreadWorkspace`, `ThreadFeed`, `ThreadOutcomeCard`, `ThreadDetailPanel`, `Composer`, `ThreadTranscript`, `threadPartRenderers` — **requires `motion`**, not merely an optional peer; see [Requirements](#requirements) |
|
|
240
240
|
| `./state` | **free** | `createPersistedState` (versioned localStorage) + `useOnlineStatus` — Mantine-free state primitives |
|
|
241
241
|
| `./connectivity` | coupled | `ConnectivityProvider` (aggregates browser/React-Query/SSE/health-check status), `useConnectivity`, `ConnectivityIndicator` — auto-mounted by `BasaltProvider` |
|
|
242
242
|
| `./content` | coupled | `Prose`, `CodeBlock`, `Callout`, `TableOfContents`, `ReadingProgress`, `Markdown`, `MermaidDiagram`, `ArticleLayout`, `ArticleCard` / `ArticleGrid`, `GuideLink` / `GuideDrawer`, `mdxComponents` |
|
|
@@ -443,20 +443,19 @@ import { BasaltVirtualList } from 'basalt-ui/data/virtual'
|
|
|
443
443
|
### `./content` — prose + markdown
|
|
444
444
|
|
|
445
445
|
````bash
|
|
446
|
-
bun add
|
|
447
|
-
bun add
|
|
448
|
-
bun add
|
|
449
|
-
bun add
|
|
446
|
+
bun add react-markdown remark-gfm # Markdown
|
|
447
|
+
bun add remend # `Markdown`'s streaming-tail repair — optional, lazy dynamic import
|
|
448
|
+
bun add rehype-sanitize # `Markdown`'s sanitize pass — optional, lazy dynamic import
|
|
449
|
+
bun add shiki # CodeBlock / fenced-code highlighting (brings @shikijs/langs, @shikijs/themes as optional peers)
|
|
450
|
+
bun add beautiful-mermaid # MermaidDiagram / ```mermaid fences
|
|
450
451
|
````
|
|
451
452
|
|
|
452
|
-
|
|
453
|
-
`basalt-ui/content`
|
|
454
|
-
|
|
455
|
-
`
|
|
456
|
-
|
|
457
|
-
only
|
|
458
|
-
Everything else degrades gracefully when absent (markdown falls back to plain text, fences to
|
|
459
|
-
plain mono, mermaid renders nothing). `Markdown` is the package's **only** markdown
|
|
453
|
+
Every peer here is lazy: `Markdown` reaches all of them through a dynamic `import()`, so
|
|
454
|
+
`basalt-ui/content` resolves and renders with none of them installed. Absence degrades gracefully
|
|
455
|
+
— never a crash: without `react-markdown`/`remark-gfm`, markdown falls back to plain text; without
|
|
456
|
+
`remend`, the streaming tail renders unrepaired; without `rehype-sanitize`, the sanitize pass is
|
|
457
|
+
skipped (dev-warned once); without `shiki`, fences fall back to plain mono; without
|
|
458
|
+
`beautiful-mermaid`, mermaid fences render nothing. `Markdown` is the package's **only** markdown
|
|
460
459
|
renderer — it backs long-form content and AI chat alike:
|
|
461
460
|
|
|
462
461
|
```tsx
|
|
@@ -465,12 +464,16 @@ import { Markdown, Prose, CodeBlock, TableOfContents } from 'basalt-ui/content'
|
|
|
465
464
|
// Long-form: 72ch measure, article typography, heading anchors + slug dedup.
|
|
466
465
|
<Markdown>{article.body}</Markdown>
|
|
467
466
|
|
|
468
|
-
// AI output: chat density, block-split + memoized, `remend`-repaired in-flight tail.
|
|
469
|
-
|
|
467
|
+
// AI output: chat density, block-split + memoized, `remend`-repaired in-flight tail. Model-generated
|
|
468
|
+
// text is untrusted regardless of whether it has finished streaming — pin `contentTrust` explicitly.
|
|
469
|
+
<Markdown streaming density="chat" contentTrust="untrusted">{part.text}</Markdown>
|
|
470
470
|
```
|
|
471
471
|
|
|
472
|
-
`streaming`
|
|
473
|
-
|
|
472
|
+
`streaming` is a rendering mode only — it says the text is still arriving, not who wrote it. The
|
|
473
|
+
security input is the separate `contentTrust` prop (`'trusted' | 'untrusted'`), the sole driver of
|
|
474
|
+
the `allowedImagePrefixes` default: same-origin-only when untrusted, since LLM-authored markdown can
|
|
475
|
+
otherwise exfiltrate via a remote image URL. Any surface rendering agent/model output must pin
|
|
476
|
+
`contentTrust="untrusted"` explicitly. Full doctrine: `agent/rules/basalt-content.md`.
|
|
474
477
|
|
|
475
478
|
### `./agent` — streaming-chat layer
|
|
476
479
|
|
|
@@ -606,16 +609,22 @@ Wire the drift gate to catch doctrine falling behind after a basalt-ui upgrade:
|
|
|
606
609
|
|
|
607
610
|
## Requirements
|
|
608
611
|
|
|
609
|
-
| Peer | Version | Notes
|
|
610
|
-
| ----------------------- | --------- |
|
|
611
|
-
| `react` / `react-dom` | `^19` | required
|
|
612
|
-
| `@mantine/core` | `^9.3` | required
|
|
613
|
-
| `@mantine/hooks` | `^9.3` | required
|
|
614
|
-
| `@tanstack/react-query` | — | required for the root `.` entry — `BasaltProvider` hard-requires it at build time; NOT required by `./agent-chat`, which doesn't touch it
|
|
615
|
-
| `
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
`./agent-chat`'s `
|
|
612
|
+
| Peer | Version | Notes |
|
|
613
|
+
| ----------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
614
|
+
| `react` / `react-dom` | `^19` | required |
|
|
615
|
+
| `@mantine/core` | `^9.3` | required |
|
|
616
|
+
| `@mantine/hooks` | `^9.3` | required |
|
|
617
|
+
| `@tanstack/react-query` | — | required for the root `.` entry — `BasaltProvider` hard-requires it at build time; NOT required by `./agent-chat`, which doesn't touch it |
|
|
618
|
+
| `motion` | `12.42.0` | required for both the root `.` entry and `./agent-chat` — both export `ThreadFeed`/`ThreadDetailPanel` (`agent-chat/thread-feed.tsx` / `thread-detail-panel.tsx`), which import `motion/react` eagerly; the root's `ThemeToggle` also uses it |
|
|
619
|
+
|
|
620
|
+
`remend` was required through 1.10.x — `content/markdown.tsx` imported it at the top of the module,
|
|
621
|
+
so both the root `.` entry and `./agent-chat`'s `ThreadWorkspace`/`ThreadTranscript` hard-required it
|
|
622
|
+
transitively. It is now a genuinely optional, lazy peer (dynamic `import()`); see
|
|
623
|
+
[`./content`](#content--prose--markdown) below.
|
|
624
|
+
|
|
625
|
+
`./agent-chat`'s `optionalPeers` in `llms.txt`/`surfaces.ts` lists `remend` and `motion` (npm has no
|
|
626
|
+
per-subpath optionality in `peerDependenciesMeta`) — only `motion` needs to be treated as required
|
|
627
|
+
when installing just this subpath; `remend` is accurately optional there too now.
|
|
619
628
|
|
|
620
629
|
Optional peer batteries and their packages are listed per battery above.
|
|
621
630
|
|
|
@@ -76,10 +76,23 @@ token, no debouncing needed.
|
|
|
76
76
|
- The LAST (in-flight) block is repaired via `remend` before rendering — unclosed `**`/`` ` ``/
|
|
77
77
|
`~~`/`$$`, an incomplete `[text](url` link (remend rewrites it to
|
|
78
78
|
`streamdown:incomplete-link` — any `streamdown:` href is dropped by the link hardening below).
|
|
79
|
+
`remend` is a lazy optional peer (dynamic `import()`); the root `.` entry no longer hard-requires
|
|
80
|
+
it.
|
|
81
|
+
- **`streaming` is a RENDERING mode only** — it says the text is still arriving, not who wrote it.
|
|
82
|
+
Trust is a separate prop, `contentTrust: 'trusted' | 'untrusted'`, and it is the sole input to the
|
|
83
|
+
image allowlist below. Any surface rendering agent/model output must pin
|
|
84
|
+
`contentTrust="untrusted"` explicitly — a finished agent message is still model-generated, so
|
|
85
|
+
don't lean on `streaming` as a stand-in for trust.
|
|
79
86
|
- **Hardening is ALWAYS ON**, streaming or not: `allowedLinkPrefixes` (default `['https://',
|
|
80
|
-
'mailto:', '#', '/']`) / `
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
'mailto:', '#', '/']`) / `defaultOrigin` (resolves a relative URL before the allowlist check's
|
|
88
|
+
result is used) / a `rehype-sanitize` pass (optional peer; `sanitizeSchema` only ADDS to the
|
|
89
|
+
default schema, never removes from it). `allowedImagePrefixes` defaults off `contentTrust`, NOT
|
|
90
|
+
`streaming`: `['https://', '/']` when trusted, same-origin-only `['/']` when untrusted — an
|
|
91
|
+
auto-fetched image is the classic prompt-injection exfiltration channel. `contentTrust` itself
|
|
92
|
+
defaults to `'untrusted'` when `streaming` is set, `'trusted'` otherwise — a backward-compat
|
|
93
|
+
floor, not the policy (see the bullet above). An explicit `allowedImagePrefixes` always overrides
|
|
94
|
+
the `contentTrust` default. A disallowed `href`/`src` renders as an unlinked `<span>` / a dropped
|
|
95
|
+
image — never a raw unsafe URL.
|
|
83
96
|
- Fenced code highlights/upgrades per BLOCK on settle, not per token — the in-flight fence renders
|
|
84
97
|
plain mono (`CodeBlock showCopy={false}`) until its block settles.
|
|
85
98
|
- Heading ids: a document-wide `SlugTracker` in non-streaming mode gives correct cross-heading
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { ChatMessage } from './history.js';
|
|
2
|
+
import type { AgentOutcome } from './outcome.js';
|
|
3
|
+
import type { AgentPart } from './parts.js';
|
|
4
|
+
import type { AgentThread, ThreadStatus, ThreadsStore } from './thread.js';
|
|
5
|
+
/**
|
|
6
|
+
* The async persistence contract behind a `ThreadsStore`. Every method may reject; the wrapping
|
|
7
|
+
* store treats a rejection as "the optimistic edit did not happen" and rolls it back.
|
|
8
|
+
*
|
|
9
|
+
* Implement this against whatever owns the transcript (Postgres, an HTTP API, IndexedDB) and
|
|
10
|
+
* verify it with `threadsStoreAdapterContract` — the suite pins the parts of the contract that
|
|
11
|
+
* prose cannot enforce, chiefly `appendMessage`'s idempotency.
|
|
12
|
+
*
|
|
13
|
+
* ## What `createAdapterThreadsStore` guarantees you
|
|
14
|
+
*
|
|
15
|
+
* **Per-thread write ordering.** Writes carrying the same thread id reach this adapter strictly in
|
|
16
|
+
* issue order, each one awaiting the previous, so a write that depends on a row existing is never
|
|
17
|
+
* issued before that row's `createThread` has RESOLVED. This matters because the primary send path
|
|
18
|
+
* is one synchronous block — `create()`, `select()`, `markRead()`, `appendMessage()`,
|
|
19
|
+
* `setStatus()` — which without ordering would hand you three dependent writes against a row you
|
|
20
|
+
* have not created yet. You therefore never have to tolerate (or invent an upsert for) an
|
|
21
|
+
* out-of-order write. Writes for DIFFERENT thread ids stay concurrent and carry no ordering
|
|
22
|
+
* guarantee relative to each other.
|
|
23
|
+
*
|
|
24
|
+
* ## What it requires of you
|
|
25
|
+
*
|
|
26
|
+
* **Read-after-write consistency on `listThreads`.** A `listThreads` STARTED after a write has
|
|
27
|
+
* resolved must reflect that write. The store keeps a write's optimistic patch applied until such
|
|
28
|
+
* a list lands, then drops it; an eventually-consistent backend (a stale read replica, a cached
|
|
29
|
+
* list) will therefore flash the pre-write state back into the UI. `threadsStoreAdapterContract`
|
|
30
|
+
* pins this.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const postgresThreadsAdapter = (api: Api): ThreadsStoreAdapter => ({
|
|
34
|
+
* listThreads: (signal) => api.threads.get({ fetch: { signal } }),
|
|
35
|
+
* loadThread: (id, signal) => api.threads({ id }).get({ fetch: { signal } }),
|
|
36
|
+
* createThread: ({ id, meta }) => api.threads.post({ id, meta }),
|
|
37
|
+
* // ...
|
|
38
|
+
* })
|
|
39
|
+
*/
|
|
40
|
+
export type ThreadsStoreAdapter<TPart = AgentPart> = {
|
|
41
|
+
/** All threads, NEWEST-FIRST (same ordering contract as `ThreadsStore.threads`). */
|
|
42
|
+
readonly listThreads: (signal?: AbortSignal) => Promise<readonly AgentThread<TPart>[]>;
|
|
43
|
+
/** One thread by id, or `null` when it does not exist. Must not throw on an unknown id. */
|
|
44
|
+
readonly loadThread: (id: string, signal?: AbortSignal) => Promise<AgentThread<TPart> | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Materialize a new thread under the CLIENT-MINTED `id`. The id is minted client-side because
|
|
47
|
+
* `ThreadsStore.create()` returns synchronously — there is no await to hand a server id back
|
|
48
|
+
* through. The created thread starts empty: `messages: []`, `outcome: null`,
|
|
49
|
+
* `status: 'pending'`, `read: false`, with `createdAt`/`updatedAt` set.
|
|
50
|
+
*/
|
|
51
|
+
readonly createThread: (i: {
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly meta?: Record<string, unknown>;
|
|
54
|
+
}) => Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* CONTRACT: idempotent on `message.id`. The id is client-minted and is the ONLY idempotency
|
|
57
|
+
* key — a retried or double-fired write with the same id must be a no-op, not a second row.
|
|
58
|
+
*/
|
|
59
|
+
readonly appendMessage: (i: {
|
|
60
|
+
readonly threadId: string;
|
|
61
|
+
readonly message: ChatMessage<TPart>;
|
|
62
|
+
}) => Promise<void>;
|
|
63
|
+
readonly setStatus: (i: {
|
|
64
|
+
readonly threadId: string;
|
|
65
|
+
readonly status: ThreadStatus;
|
|
66
|
+
}) => Promise<void>;
|
|
67
|
+
readonly setOutcome: (i: {
|
|
68
|
+
readonly threadId: string;
|
|
69
|
+
readonly outcome: AgentOutcome;
|
|
70
|
+
}) => Promise<void>;
|
|
71
|
+
/** `token: undefined` CLEARS the token — the stored thread must then read `resumeToken` as absent. */
|
|
72
|
+
readonly setResumeToken: (i: {
|
|
73
|
+
readonly threadId: string;
|
|
74
|
+
readonly token: string | undefined;
|
|
75
|
+
}) => Promise<void>;
|
|
76
|
+
readonly markRead: (threadId: string) => Promise<void>;
|
|
77
|
+
/** Removing an unknown id is a no-op, not an error. */
|
|
78
|
+
readonly removeThread: (threadId: string) => Promise<void>;
|
|
79
|
+
};
|
|
80
|
+
export type AdapterThreadsStoreOptions = {
|
|
81
|
+
/**
|
|
82
|
+
* Re-list threads whenever the window regains focus. Off by default — a background tab that
|
|
83
|
+
* refocuses should not surprise a consumer with a network round-trip it did not ask for.
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
readonly revalidateOnFocus?: boolean;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Wraps an async `ThreadsStoreAdapter` into the synchronous `ThreadsStore` every component takes.
|
|
90
|
+
*
|
|
91
|
+
* Call this ONCE per module (not inside a component), exactly like `createThreadsStore`. All
|
|
92
|
+
* components calling the returned hook share one registry, backed by `useSyncExternalStore`.
|
|
93
|
+
*
|
|
94
|
+
* Semantics:
|
|
95
|
+
* - **Optimistic.** Every mutation applies locally first, so `create()` can return an id
|
|
96
|
+
* synchronously and the UI never waits on a round-trip.
|
|
97
|
+
* - **Ordered per thread.** Writes for one thread id reach the adapter in issue order, each
|
|
98
|
+
* awaiting the previous — so the dependent writes of a `create()`-then-send land after
|
|
99
|
+
* `createThread` has resolved. Different threads stay concurrent. See `ThreadsStoreAdapter`.
|
|
100
|
+
* - **Revalidate on success, coalesced.** When a write resolves the store re-lists; the patch is
|
|
101
|
+
* dropped only once a list has actually refreshed the confirmed base, so server-side derivations
|
|
102
|
+
* win over the local guess with no gap in between. Writes that resolve while a list is already in
|
|
103
|
+
* flight share ONE follow-up instead of each restarting it, so a burst of writes costs at most
|
|
104
|
+
* two round trips (the in-flight one, plus one follow-up), not one per write — see `revalidate`.
|
|
105
|
+
* - **Roll back on rejection.** A rejected write's patch is discarded, the rejection is surfaced
|
|
106
|
+
* on `error`, and the store re-lists to converge on whatever the server really did. Patches are
|
|
107
|
+
* tracked individually, so a failing write rolls back only itself and not whatever else was in
|
|
108
|
+
* flight beside it.
|
|
109
|
+
* - **`hydrated` means "a `listThreads` has succeeded"**, not "a load has been attempted". A
|
|
110
|
+
* store that is `!hydrated` with a non-undefined `error` failed to load; check both.
|
|
111
|
+
* - **`error` latches the most recent failure until something disproves it.** A successful
|
|
112
|
+
* `listThreads` clears a LOAD failure; it leaves a WRITE failure alone, since a working list is
|
|
113
|
+
* no evidence the rejected write landed. A write clears a latched write failure only if it was
|
|
114
|
+
* issued after that failure (a retry) — never the writes that were already queued behind it.
|
|
115
|
+
*
|
|
116
|
+
* `select` is local-only — which thread is active is UI state, not something the adapter owns.
|
|
117
|
+
* `clear()` maps onto `removeThread` for each known thread, since the adapter has no bulk delete.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* export const useThreads = createAdapterThreadsStore(myAdapter, { revalidateOnFocus: true })
|
|
121
|
+
*/
|
|
122
|
+
export declare function createAdapterThreadsStore<TPart = AgentPart>(adapter: ThreadsStoreAdapter<TPart>, opts?: AdapterThreadsStoreOptions): () => ThreadsStore<TPart>;
|
|
123
|
+
/** One conformance case. `run` rejects with a plain Error describing the violation. */
|
|
124
|
+
export type ThreadsStoreAdapterContractCase = {
|
|
125
|
+
readonly name: string;
|
|
126
|
+
readonly run: () => Promise<void>;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* A test-runner-agnostic conformance suite for a `ThreadsStoreAdapter` implementation.
|
|
130
|
+
*
|
|
131
|
+
* This ships in the published package, so it deliberately imports NO test framework and depends
|
|
132
|
+
* on no assertion library — each case throws a plain `Error`. Drive it from whatever runner the
|
|
133
|
+
* consumer uses.
|
|
134
|
+
*
|
|
135
|
+
* `makeAdapter` is called ONCE PER CASE and must hand back a fresh, empty backend: the cases are
|
|
136
|
+
* independent and none of them cleans up after itself.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* import { threadsStoreAdapterContract } from 'basalt-ui/agent'
|
|
140
|
+
*
|
|
141
|
+
* for (const c of threadsStoreAdapterContract(() => postgresThreadsAdapter(freshDb()))) {
|
|
142
|
+
* test(c.name, () => c.run())
|
|
143
|
+
* }
|
|
144
|
+
*/
|
|
145
|
+
export declare function threadsStoreAdapterContract<TPart>(makeAdapter: () => ThreadsStoreAdapter<TPart> | Promise<ThreadsStoreAdapter<TPart>>): readonly ThreadsStoreAdapterContractCase[];
|
|
146
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/agent/adapter.ts"],"names":[],"mappings":"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"}
|