@truefoundry/agent-ui-sdk 0.0.1 → 0.0.2

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.
Files changed (79) hide show
  1. package/README.md +192 -80
  2. package/dist/index.d.ts +228 -281
  3. package/dist/index.js +1823 -1791
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +2 -0
  6. package/package.json +36 -19
  7. package/src/atoms/AskUserPrompt.tsx +0 -102
  8. package/src/atoms/AttachmentCard.tsx +0 -92
  9. package/src/atoms/AttachmentPickerButton.tsx +0 -19
  10. package/src/atoms/AttachmentPreviewDialog.tsx +0 -34
  11. package/src/atoms/BranchIndicator.tsx +0 -41
  12. package/src/atoms/CodeBlockHeader.tsx +0 -44
  13. package/src/atoms/ComposerShell.tsx +0 -112
  14. package/src/atoms/Markdown.test.tsx +0 -28
  15. package/src/atoms/Markdown.tsx +0 -288
  16. package/src/atoms/McpAuthPrompt.tsx +0 -60
  17. package/src/atoms/MessageActionBar.tsx +0 -60
  18. package/src/atoms/MessageBubble.tsx +0 -80
  19. package/src/atoms/MessageErrorBanner.tsx +0 -26
  20. package/src/atoms/MessageIndicator.tsx +0 -23
  21. package/src/atoms/OpenUIBlock.test.tsx +0 -37
  22. package/src/atoms/OpenUIBlock.tsx +0 -50
  23. package/src/atoms/ReasoningCard.tsx +0 -52
  24. package/src/atoms/SandboxArtifactList.tsx +0 -63
  25. package/src/atoms/ScrollToBottomButton.tsx +0 -34
  26. package/src/atoms/Skeletons.tsx +0 -32
  27. package/src/atoms/ThreadListMisc.tsx +0 -76
  28. package/src/atoms/ThreadListRow.tsx +0 -81
  29. package/src/atoms/ThreadShell.tsx +0 -93
  30. package/src/atoms/Toast.tsx +0 -60
  31. package/src/atoms/ToolApprovalBar.tsx +0 -92
  32. package/src/atoms/ToolCallCard.tsx +0 -186
  33. package/src/atoms/ToolGroupCard.tsx +0 -52
  34. package/src/atoms/UserMessageActionBar.tsx +0 -62
  35. package/src/atoms/WelcomeScreen.tsx +0 -22
  36. package/src/atoms/lib/cn.ts +0 -6
  37. package/src/atoms/primitives/Avatar.tsx +0 -57
  38. package/src/atoms/primitives/Button.tsx +0 -73
  39. package/src/atoms/primitives/Collapsible.tsx +0 -32
  40. package/src/atoms/primitives/Dialog.tsx +0 -152
  41. package/src/atoms/primitives/IconButton.tsx +0 -43
  42. package/src/atoms/primitives/Skeleton.tsx +0 -17
  43. package/src/atoms/primitives/Tooltip.tsx +0 -58
  44. package/src/containers/AskUserContainer.tsx +0 -49
  45. package/src/containers/AssistantMessageContainer.test.tsx +0 -56
  46. package/src/containers/AssistantMessageContainer.tsx +0 -128
  47. package/src/containers/AssistantTextContainer.test.tsx +0 -111
  48. package/src/containers/AssistantTextContainer.tsx +0 -54
  49. package/src/containers/AttachmentsContainer.tsx +0 -83
  50. package/src/containers/ComposerContainer.tsx +0 -66
  51. package/src/containers/ErrorToasterContainer.tsx +0 -76
  52. package/src/containers/McpAuthContainer.test.tsx +0 -100
  53. package/src/containers/McpAuthContainer.tsx +0 -22
  54. package/src/containers/MessageImageContainer.tsx +0 -37
  55. package/src/containers/ReasoningContainer.tsx +0 -32
  56. package/src/containers/RuntimeHarness.tsx +0 -39
  57. package/src/containers/Thread.tsx +0 -9
  58. package/src/containers/ThreadContainer.test.tsx +0 -52
  59. package/src/containers/ThreadContainer.tsx +0 -87
  60. package/src/containers/ThreadListContainer.tsx +0 -63
  61. package/src/containers/ToolCallContainer.test.tsx +0 -135
  62. package/src/containers/ToolCallContainer.tsx +0 -167
  63. package/src/containers/ToolGroupContainer.test.tsx +0 -56
  64. package/src/containers/ToolGroupContainer.tsx +0 -24
  65. package/src/containers/UserEditComposerContainer.test.tsx +0 -52
  66. package/src/containers/UserEditComposerContainer.tsx +0 -86
  67. package/src/containers/UserMessageContainer.test.tsx +0 -99
  68. package/src/containers/UserMessageContainer.tsx +0 -26
  69. package/src/containers/nestedApprovalBridge.ts +0 -20
  70. package/src/containers/useAttachmentPreviewSrc.ts +0 -42
  71. package/src/hooks/useComposerBusyState.test.ts +0 -78
  72. package/src/hooks/useComposerBusyState.ts +0 -69
  73. package/src/index.ts +0 -193
  74. package/src/testSetup.ts +0 -42
  75. package/src/theme/SlotsProvider.test.tsx +0 -64
  76. package/src/theme/SlotsProvider.tsx +0 -41
  77. package/src/theme/defaultSlots.ts +0 -131
  78. package/src/theme/tokens.ts +0 -98
  79. package/src/theme/useClassDarkMode.ts +0 -24
package/README.md CHANGED
@@ -34,9 +34,18 @@ logic. You bring the runtime; the SDK renders it.
34
34
  yarn add @truefoundry/agent-ui-sdk \
35
35
  @assistant-ui/react @assistant-ui/core \
36
36
  @truefoundry/assistant-ui-runtime truefoundry-gateway-sdk \
37
+ tfy-web-components monaco-editor \
37
38
  react react-dom
38
39
  ```
39
40
 
41
+ `tfy-web-components` is a peer dependency — the default `Button`/`IconButton`/
42
+ `UserMessage` slots (see [`defaultSlots.ts`](./src/theme/defaultSlots.ts))
43
+ import it directly, and it needs to resolve from your app's own
44
+ `node_modules` for Tailwind to scan its compiled components.
45
+ `monaco-editor` is also required: `tfy-web-components`' agent-chat code editor
46
+ imports it as a peer, and Next.js will fail with `Can't resolve 'monaco-editor'`
47
+ if it is missing.
48
+
40
49
  Every one of these peers must resolve to a **single instance** across your app.
41
50
  Two copies of `react` or `@assistant-ui/core` are the most likely source of a
42
51
  `"requires an AuiProvider"` error — see
@@ -48,26 +57,79 @@ Two copies of `react` or `@assistant-ui/core` are the most likely source of a
48
57
 
49
58
  ## Styling
50
59
 
51
- SDK components use Tailwind utility classes. Import the SDK stylesheet in your
52
- **Tailwind entry CSS file** (for example `globals.css`) with a CSS `@import` so
53
- the SDK's own `@source` directive participates in the same Tailwind build:
60
+ SDK components use Tailwind utility classes. Everything OpenUI's styles,
61
+ `tfy-web-components`' palette, and default color tokens for this SDK's own
62
+ atoms ships as a precompiled stylesheet: `@truefoundry/agent-ui-sdk/styles.css`.
63
+
64
+ Import it once from your application's global stylesheet. It works with
65
+ Tailwind v3, Tailwind v4, and applications that do not use Tailwind. The SDK
66
+ ships every utility class it needs, so consumers do not need `@source`
67
+ directives or a Tailwind preset.
68
+
69
+ ```css
70
+ @import "@truefoundry/agent-ui-sdk/styles.css";
71
+ ```
72
+
73
+ Place application-level theme variables after the SDK import so they win in
74
+ the normal CSS cascade. The SDK intentionally excludes Tailwind preflight, so
75
+ it does not reset your application's global styles.
76
+
77
+ ### Dark mode
78
+
79
+ SDK `dark:*` utilities are activated only when a `.dark` ancestor is present;
80
+ they do not follow the operating-system color preference. Toggle `.dark` on
81
+ your document root (for example, `<html class="dark">`) to switch the SDK and
82
+ your token overrides together. Pass the same resolved value to
83
+ `<SlotsProvider theme={theme}>`; this keeps React-only integrations, such as
84
+ OpenUI code blocks, in sync with your CSS theme and forwards it to the default
85
+ tfy-web-components `ThemeProvider`.
86
+
87
+ ### Overriding tokens
88
+
89
+ The default color tokens this SDK's atoms use — bridged from
90
+ `tfy-web-components`'s palette so they render correctly out of the box — are
91
+ plain CSS variables declared in `@layer base`, so any of your own `:root`/
92
+ `.dark` declarations for the same variable automatically win (no specificity
93
+ tricks needed):
94
+
95
+ | Variable | Used for |
96
+ | --- | --- |
97
+ | `--background` / `--foreground` | Page/thread background and default text |
98
+ | `--card` / `--card-foreground` | Dialogs, popovers, cards |
99
+ | `--popover` / `--popover-foreground` | Tooltips, dropdowns |
100
+ | `--primary` / `--primary-foreground` | Primary actions |
101
+ | `--secondary` / `--secondary-foreground` | Secondary actions |
102
+ | `--muted` / `--muted-foreground` | Composer, subdued surfaces/text |
103
+ | `--accent` / `--accent-foreground` | Hover/selected states |
104
+ | `--destructive` / `--destructive-foreground` | Errors, delete actions |
105
+ | `--border` / `--input` / `--ring` | Borders, inputs, focus rings |
106
+ | `--radius` | Base corner radius (`--radius-sm/md/lg/xl` derive from it) |
54
107
 
55
108
  ```css
56
- @import "tailwindcss";
57
- @import "@truefoundry/agent-ui-sdk/openui.css";
109
+ :root {
110
+ --primary: #4f46e5;
111
+ --radius: 0.75rem;
112
+ }
113
+ .dark {
114
+ --primary: #818cf8;
115
+ }
58
116
  ```
59
117
 
60
- No manual `@source` pointing into `node_modules` is needed the SDK stylesheet
61
- declares `@source "."` relative to its install location, so Tailwind scans the
62
- SDK's components automatically.
118
+ `tfy-web-components` utility classes use the same public palette variables.
119
+ For example, redefine `--color-indigo-500` to rebrand every default component
120
+ that uses Tailwind's `indigo-500` color:
63
121
 
64
- **Use a CSS `@import`, not a JS import** (`import "@truefoundry/agent-ui-sdk/openui.css"`).
65
- A JS import may load OpenUI styles but will not activate Tailwind's content
66
- scanning for SDK utilities.
122
+ ```css
123
+ :root {
124
+ --color-indigo-500: #4f46e5;
125
+ }
126
+ .dark {
127
+ --color-indigo-500: #818cf8;
128
+ }
129
+ ```
67
130
 
68
- Provide your own design tokens as CSS variables (`--primary`, `--background`,
69
- `--muted`, `--border`, …) in the consumer app — the SDK stays
70
- design-system-agnostic and references those variables rather than hardcoded
131
+ Provide your own values for any of these the SDK stays
132
+ design-system-agnostic and references CSS variables rather than hardcoded
71
133
  colors or spacing.
72
134
 
73
135
  ## Quick start
@@ -83,7 +145,7 @@ import {
83
145
  Thread,
84
146
  ThreadListContainer,
85
147
  ErrorToasterProvider,
86
- TooltipProvider,
148
+ SlotsProvider,
87
149
  } from "@truefoundry/agent-ui-sdk";
88
150
 
89
151
  const client = new AgentSessionClient({
@@ -100,18 +162,18 @@ export function App() {
100
162
 
101
163
  return (
102
164
  <AssistantRuntimeProvider runtime={runtime}>
103
- <ErrorToasterProvider>
104
- <TooltipProvider>
105
- <main style={{ display: "flex", height: "100dvh" }}>
106
- <aside style={{ width: 256 }}>
107
- <ThreadListContainer />
108
- </aside>
109
- <div style={{ flex: 1 }}>
110
- <Thread />
111
- </div>
112
- </main>
113
- </TooltipProvider>
114
- </ErrorToasterProvider>
165
+ <SlotsProvider theme="light">
166
+ <ErrorToasterProvider>
167
+ <main style={{ display: "flex", height: "100dvh" }}>
168
+ <aside style={{ width: 256 }}>
169
+ <ThreadListContainer />
170
+ </aside>
171
+ <div style={{ flex: 1 }}>
172
+ <Thread />
173
+ </div>
174
+ </main>
175
+ </ErrorToasterProvider>
176
+ </SlotsProvider>
115
177
  </AssistantRuntimeProvider>
116
178
  );
117
179
  }
@@ -124,19 +186,26 @@ the welcome screen, loading skeleton, streaming, tool calls, reasoning
124
186
  blocks, attachments, and the ask-user / MCP-auth prompts automatically.
125
187
  - `**<ThreadListContainer />**` is the session sidebar (new / select / archive
126
188
  / delete).
127
- - `**<ErrorToasterProvider>` / `<TooltipProvider>**` are required wrappers:
128
- gateway/runtime errors surface through the toaster, and tooltips on built-in
129
- buttons need the provider.
189
+ - `**<ErrorToasterProvider>**` is a required wrapper: gateway/runtime errors surface
190
+ through the toaster. Tooltips on default buttons use tfy `LightTooltip` and do not
191
+ require a separate provider.
130
192
 
131
193
  Need a custom layout around the input? Compose the pieces yourself instead of
132
194
  `<Thread />`:
133
195
 
134
196
  ```tsx
135
- import { ThreadContainer, ComposerContainer } from "@truefoundry/agent-ui-sdk";
197
+ import {
198
+ ThreadContainer,
199
+ ComposerContainer,
200
+ useComposerPauseView,
201
+ } from "@truefoundry/agent-ui-sdk";
136
202
 
137
203
  <ThreadContainer composer={<ComposerContainer />} />;
138
204
  ```
139
205
 
206
+ For a fully custom composer shell, reuse `useComposerPauseView()` so MCP-auth and
207
+ ask-user pauses match the default `ComposerContainer` branching.
208
+
140
209
  ## OpenUI blocks
141
210
 
142
211
  Assistant messages that include an OpenUI Lang fenced block render
@@ -151,17 +220,19 @@ Card() {
151
220
  ```
152
221
  ```
153
222
 
154
- `<Thread />` routes assistant text through the SDK `Markdown` atom, which
155
- dispatches `language-openui` fences to `OpenUIBlock`. Streaming state is passed
156
- through while the message is still running.
223
+ `<Thread />` routes assistant text through the SDK `Markdown` atom, a thin wrapper
224
+ around tfy-web-components' `MarkdownWithOpenUI`. OpenUI (` ```openui `) and
225
+ `sandbox_artifacts` fenced blocks render via tfy's fence components. Streaming
226
+ state is passed through while the message is still running.
157
227
 
158
- `OpenUIBlock` wraps output in OpenUI's `ThemeProvider` and syncs `mode` with a
159
- `.dark` class on `<html>` by default. Pass an explicit `mode` prop to override,
160
- or wrap a larger subtree in OpenUI's `ThemeProvider` yourself for custom token
161
- overrides (`lightTheme` / `darkTheme`).
228
+ OpenUI theme mode follows the `theme` prop passed to its nearest
229
+ `SlotsProvider`.
230
+ Optional `fileDownloadBaseUrl` on `Markdown` resolves sandbox artifact downloads
231
+ when wired by the host app.
162
232
 
163
- Make sure the SDK stylesheet is imported as CSS (see [Styling](#styling)) — the
164
- `@import` form is required for OpenUI's Tailwind utilities.
233
+ Make sure the SDK stylesheet is imported as CSS (see [Styling](#styling)) —
234
+ tfy `MarkdownWithOpenUI` loads OpenUI styles internally; `openui.css` remains
235
+ available for standalone OpenUI `@source` scanning.
165
236
 
166
237
  ## Customizing the UI (examples)
167
238
 
@@ -193,51 +264,59 @@ the rest of this section applies it to harder cases.
193
264
 
194
265
  Not every name declared on `AtomSlots` is resolved via `useSlot` today.
195
266
 
196
- - **Feature-level atoms are** — `MessageBubble`, `ComposerShell`,
197
- `ToolCallCard`, `WelcomeScreen`, `ThreadListRow`, `Toast`, `ToastStack`,
198
- `AskUserPrompt`, `ScrollToBottomButton`, etc. Overriding these works exactly
199
- as documented here.
200
- - **Shared low-level primitives are not** — `Button`, `IconButton`, `Tooltip`*,
201
- `Dialog*`, `Avatar*`, `Collapsible*`, `Skeleton`, `CodeBlockHeader` are
202
- declared in `AtomSlots` and populated in `defaultSlots`, but the atoms that
203
- render them currently `import` them directly instead of going through
204
- `useSlot`. Overriding just `Button` will **not** change the Submit button
205
- inside `AskUserPrompt`.
267
+ - **Feature-level atoms are** — `AssistantMessageBubble`, `UserMessageBubble`,
268
+ `ComposerShell`, `ToolCallCard`, `WelcomeScreen`, `ThreadListRow`, `Toast`,
269
+ `ToastStack`, `AskUserPrompt`, `ScrollToBottomButton`, etc. Overriding these
270
+ works exactly as documented here.
271
+ - **Shared low-level primitives are partially resolved via `useSlot`** — `Button`, `IconButton`, `Tooltip*`,
272
+ `Dialog*`, `Avatar*`, `Collapsible*`, `Skeleton`, `CodeBlockHeader` are declared in `AtomSlots` and
273
+ populated in `defaultSlots`. `ComposerShell`, `AttachmentCard`, `MessageActionBar`, and
274
+ `AttachmentPreviewDialog` resolve `Button`/`IconButton` (and related primitives) through `useSlot`, so
275
+ overriding those slots affects the default composer and attachment UI. Other atoms may still import
276
+ primitives directly.
206
277
 
207
278
  If you need to change a primitive everywhere, override the higher-level atom
208
279
  that embeds it (examples 4 and 6 do exactly this).
209
280
 
210
281
  ### Restyling
211
282
 
212
- **1. Restyle the chat bubbles.** `MessageBubble` is a discriminated union on
213
- `variant`, so user and assistant messages can have completely different shells
214
- while still receiving the same slots (`children`, `error`, `branchIndicator`,
283
+ **1. Restyle the chat bubbles.** Override `AssistantMessageBubble` and
284
+ `UserMessageBubble` separately for role-specific shells (`children`, `error`,
215
285
  `actionBar`/`attachments`):
216
286
 
217
287
  ```tsx
218
- import { SlotsProvider, Thread, type MessageBubbleProps } from "@truefoundry/agent-ui-sdk";
288
+ import {
289
+ SlotsProvider,
290
+ Thread,
291
+ type AssistantMessageBubbleProps,
292
+ type UserMessageBubbleProps,
293
+ } from "@truefoundry/agent-ui-sdk";
219
294
 
220
- function BubbleV2(props: MessageBubbleProps) {
221
- if (props.variant === "user") {
222
- return (
223
- <div className="ml-auto max-w-[75%] rounded-2xl bg-indigo-600 px-4 py-2 text-white">
224
- {props.children}
225
- </div>
226
- );
227
- }
295
+ function AssistantBubbleV2({ children, error, actionBar }: AssistantMessageBubbleProps) {
228
296
  return (
229
297
  <div className="mr-auto max-w-[75%] rounded-2xl bg-neutral-100 px-4 py-2 dark:bg-neutral-800">
230
- {props.children}
231
- {props.error}
232
- <div className="mt-1 flex gap-1 text-xs text-neutral-500">
233
- {props.branchIndicator}
234
- {props.actionBar}
235
- </div>
298
+ {children}
299
+ {error}
300
+ <div className="mt-1 flex gap-1 text-xs text-neutral-500">{actionBar}</div>
301
+ </div>
302
+ );
303
+ }
304
+
305
+ function UserBubbleV2({ text, editAction }: UserMessageBubbleProps) {
306
+ return (
307
+ <div className="ml-auto max-w-[75%] rounded-2xl bg-indigo-600 px-4 py-2 text-white">
308
+ {text}
309
+ {editAction}
236
310
  </div>
237
311
  );
238
312
  }
239
313
 
240
- <SlotsProvider overrides={{ MessageBubble: BubbleV2 }}>
314
+ <SlotsProvider
315
+ overrides={{
316
+ AssistantMessageBubble: AssistantBubbleV2,
317
+ UserMessageBubble: UserBubbleV2,
318
+ }}
319
+ >
241
320
  <Thread />
242
321
  </SlotsProvider>;
243
322
  ```
@@ -321,6 +400,33 @@ function CustomToolCallCard(props: ToolCallCardProps) {
321
400
  </SlotsProvider>;
322
401
  ```
323
402
 
403
+ ### Compose the input actions independently
404
+
405
+ `ComposerShell` resolves three slots for its bottom action bar:
406
+ `ComposerLeftSection` (file attachment by default), `ComposerRightSection`
407
+ (empty by default), and `ComposerSendButton` (send/cancel by default). Override
408
+ only the area you need while retaining the SDK's input, attachments, and other
409
+ actions:
410
+
411
+ ```tsx
412
+ import {
413
+ SlotsProvider,
414
+ Thread,
415
+ type ComposerRightSectionProps,
416
+ } from "@truefoundry/agent-ui-sdk";
417
+
418
+ function ModelPicker(_: ComposerRightSectionProps) {
419
+ return <button type="button">Select model</button>;
420
+ }
421
+
422
+ <SlotsProvider overrides={{ ComposerRightSection: ModelPicker }}>
423
+ <Thread />
424
+ </SlotsProvider>;
425
+ ```
426
+
427
+ For per-page behavior, nest this provider around that page's `Thread`. You can
428
+ still replace `ComposerShell` completely when the layout itself must change.
429
+
324
430
  ### Changing behavior, not just looks
325
431
 
326
432
  **5. Turn ask-user into instant click-to-answer.** The shipped `AskUserPrompt`
@@ -533,9 +639,15 @@ implementation for every slot; `useSlot` falls back through nested
533
639
 
534
640
  ```tsx
535
641
  import { SlotsProvider, Thread } from "@truefoundry/agent-ui-sdk";
536
- import { MyBubble } from "./my-design-system/MessageBubble";
537
-
538
- <SlotsProvider overrides={{ MessageBubble: MyBubble }}>
642
+ import { MyAssistantBubble } from "./my-design-system/AssistantMessageBubble";
643
+ import { MyUserBubble } from "./my-design-system/UserMessageBubble";
644
+
645
+ <SlotsProvider
646
+ overrides={{
647
+ AssistantMessageBubble: MyAssistantBubble,
648
+ UserMessageBubble: MyUserBubble,
649
+ }}
650
+ >
539
651
  <Thread />
540
652
  </SlotsProvider>;
541
653
  ```
@@ -572,11 +684,10 @@ dropped:
572
684
 
573
685
  - `**AskUserPrompt**` uses a select-then-submit radio flow, not the reference
574
686
  app's immediate click-to-answer buttons. See example 5 to change this.
575
- - `**ToolCallCard**` ships an `mcp-listing` variant (type + atom) that no
576
- container currently selects the runtime has no signal distinguishing
577
- "listing MCP tools" from any other tool call. Its `tool` variant also carries
578
- an `approvalSlot`/`durationText` beyond the originally-sketched contract,
579
- needed to keep the tool-approval flow working.
687
+ - `**ToolCallCard**` ships an `mcp-listing` variant used when `ToolCallContainer`
688
+ handles MCP `list_tools` calls. Its `tool` variant also carries an
689
+ `approvalSlot`/`durationText` beyond the originally-sketched contract,
690
+ needed to keep the tool-approval flow working.
580
691
  - **Attachments**: image previews use a `contentType` fallback because the
581
692
  TrueFoundry attachment adapter tags all uploads as `type: "file"`.
582
693
  - `**ThreadListContainer`** renders one flat list, not grouped by
@@ -586,9 +697,10 @@ Today/Yesterday/Earlier.
586
697
  auth is all-or-nothing: one shared Continue button.
587
698
  - Several `AtomSlots` entries (`Button`, `IconButton`, `Tooltip*`, `Dialog*`,
588
699
  `Avatar*`, `Collapsible*`, `Skeleton`, `CodeBlockHeader`) are declared and
589
- populated in `defaultSlots`, but no shipped atom resolves them via `useSlot`
590
- yetthe atoms import them directly. Override the higher-level atom instead
591
- (see "Which names are actually resolved via `useSlot`?").
700
+ populated in `defaultSlots`. Only some shipped atoms resolve them via `useSlot`
701
+ todaystart with `ComposerShell`, `AttachmentCard`, `MessageActionBar`, and
702
+ `AttachmentPreviewDialog`. Override the higher-level atom when a primitive slot
703
+ is not wired yet (see "Which names are actually resolved via `useSlot`?").
592
704
 
593
705
  ## Troubleshooting: "requires an AuiProvider"
594
706