@actioneer/ads 0.1.0 → 0.2.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/bin/ads-init.mjs CHANGED
@@ -17,13 +17,15 @@
17
17
  * • drop a consumer-mode `ads-lint.config.mjs`
18
18
  * (`libraryPackage: "@actioneer/ads"`, `libraryRoot: null`)
19
19
  *
20
- * Per the DES-13 testing decision, the write-plan is exercised end-to-end by a
21
- * manual run rather than dedicated unit tests this pass.
20
+ * The pure write-plan (`planInit`) and the package-manager detection are covered
21
+ * by unit tests in ads-init.test.mjs; the applier's IO is exercised end-to-end by
22
+ * a manual run and the release rehearsal.
22
23
  */
23
24
 
24
25
  import fs from "node:fs";
25
26
  import path from "node:path";
26
27
  import { execFileSync } from "node:child_process";
28
+ import { fileURLToPath } from "node:url";
27
29
 
28
30
  const PKG = "@actioneer/ads";
29
31
  const STYLE_IMPORT = `@import "${PKG}/styles.css";`;
@@ -38,6 +40,7 @@ const STYLE_IMPORT = `@import "${PKG}/styles.css";`;
38
40
  * @property {string|null} layoutPath repo-relative path to the root layout (or null)
39
41
  * @property {string|null} layoutContent
40
42
  * @property {boolean} hasAdsLintConfig
43
+ * @property {"npm"|"pnpm"|"yarn"|"bun"} [packageManager] detected consumer PM (default npm)
41
44
  *
42
45
  * @typedef {Object} Edit
43
46
  * @property {"install"|"write-file"|"edit-file"|"manual"} type
@@ -49,8 +52,45 @@ const STYLE_IMPORT = `@import "${PKG}/styles.css";`;
49
52
  * @property {number} [findIndex] edit-file: positional replace offset (disambiguates repeated tokens)
50
53
  * @property {string} [addImport] edit-file: import line to prepend if absent
51
54
  * @property {string[]} [packages] install: package specifiers
55
+ * @property {"npm"|"pnpm"|"yarn"|"bun"} [manager] install: package manager to shell out to
52
56
  */
53
57
 
58
+ /**
59
+ * Detect the consumer's package manager so `init` installs with THEIR tool
60
+ * rather than always shelling out to `npm` (which strands pnpm/yarn/bun users
61
+ * with a stray package-lock.json + a mixed lockfile). Precedence, most→least
62
+ * authoritative: the corepack `packageManager` field, the invoking PM's user
63
+ * agent (set when run via `pnpm dlx` / `yarn dlx` / `bunx`), then a lockfile on
64
+ * disk. Defaults to npm.
65
+ * @param {{packageManagerField?:string|null, userAgent?:string|null, lockfiles?:string[]}} [signals]
66
+ * @returns {"npm"|"pnpm"|"yarn"|"bun"}
67
+ */
68
+ export function detectPackageManager({ packageManagerField, userAgent, lockfiles } = {}) {
69
+ const field = /^(pnpm|yarn|bun|npm)(@|$)/.exec(packageManagerField ?? "");
70
+ if (field) return field[1];
71
+ const ua = /^(pnpm|yarn|bun)\//.exec(userAgent ?? "");
72
+ if (ua) return ua[1];
73
+ const locks = new Set(lockfiles ?? []);
74
+ if (locks.has("pnpm-lock.yaml")) return "pnpm";
75
+ if (locks.has("yarn.lock")) return "yarn";
76
+ if (locks.has("bun.lockb") || locks.has("bun.lock")) return "bun";
77
+ return "npm";
78
+ }
79
+
80
+ /**
81
+ * The install invocation for a given manager: npm uses `install`, the rest use
82
+ * `add`.
83
+ * @param {"npm"|"pnpm"|"yarn"|"bun"} manager
84
+ * @param {string[]} packages
85
+ * @returns {[string, string[]]} [command, args]
86
+ */
87
+ export function installCommand(manager, packages) {
88
+ const verb = manager === "npm" ? "install" : "add";
89
+ return [manager, [verb, ...packages]];
90
+ }
91
+
92
+ const LOCKFILES = ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"];
93
+
54
94
  /** @param {RepoState} state @returns {Edit[]} */
55
95
  export function planInit(state) {
56
96
  const edits = [];
@@ -58,7 +98,8 @@ export function planInit(state) {
58
98
  // 1. Install the package (+ motion peer for the reduced-motion provider).
59
99
  const missing = ["@actioneer/ads", "motion"].filter((p) => !state.dependencies?.[p]);
60
100
  if (missing.length) {
61
- edits.push({ type: "install", title: `install ${missing.join(", ")}`, packages: missing });
101
+ const manager = state.packageManager ?? "npm";
102
+ edits.push({ type: "install", title: `install ${missing.join(", ")}`, packages: missing, manager });
62
103
  }
63
104
 
64
105
  // 2. Inject the styles.css import IMMEDIATELY AFTER `@import "tailwindcss"`.
@@ -229,6 +270,12 @@ function readRepoState(cwd) {
229
270
  const pkg = pkgRaw ? JSON.parse(pkgRaw) : {};
230
271
  const dependencies = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
231
272
 
273
+ const packageManager = detectPackageManager({
274
+ packageManagerField: pkg.packageManager ?? null,
275
+ userAgent: process.env.npm_config_user_agent ?? null,
276
+ lockfiles: LOCKFILES.filter((f) => fs.existsSync(path.join(cwd, f))),
277
+ });
278
+
232
279
  const globalCssPath = CANDIDATE_CSS.find((p) => fs.existsSync(path.join(cwd, p))) ?? null;
233
280
  const layoutPath = CANDIDATE_LAYOUT.find((p) => fs.existsSync(path.join(cwd, p))) ?? null;
234
281
 
@@ -245,6 +292,7 @@ function readRepoState(cwd) {
245
292
  layoutContent: layoutPath ? read(layoutPath) : null,
246
293
  hasAdsLintConfig:
247
294
  fs.existsSync(path.join(cwd, "ads-lint.config.mjs")) || fs.existsSync(path.join(cwd, "ads-lint.config.js")),
295
+ packageManager,
248
296
  _existing,
249
297
  };
250
298
  }
@@ -253,8 +301,9 @@ function applyEdit(cwd, edit) {
253
301
  const abs = edit.path ? path.join(cwd, edit.path) : null;
254
302
  switch (edit.type) {
255
303
  case "install": {
256
- console.log(` → npm install ${edit.packages.join(" ")}`);
257
- execFileSync("npm", ["install", ...edit.packages], { cwd, stdio: "inherit" });
304
+ const [cmd, args] = installCommand(edit.manager ?? "npm", edit.packages);
305
+ console.log(` → ${cmd} ${args.join(" ")}`);
306
+ execFileSync(cmd, args, { cwd, stdio: "inherit" });
258
307
  return;
259
308
  }
260
309
  case "write-file": {
@@ -308,7 +357,25 @@ function main() {
308
357
  console.log(`\n${PKG} init: done. Import components with \`import { Button } from "${PKG}";\``);
309
358
  }
310
359
 
311
- // Only run the applier when invoked as a CLI (keeps planInit importable/pure).
312
- if (import.meta.url === `file://${process.argv[1]}`) {
360
+ /**
361
+ * True when this file is the process entry point (keeps planInit importable
362
+ * without triggering the applier). Compares REAL filesystem paths on both sides:
363
+ * npm installs the bin as a symlink (node_modules/.bin/ads -> …/ads-init.mjs),
364
+ * so process.argv[1] is the symlink while import.meta.url is realpath-resolved —
365
+ * a raw URL/string compare mismatches and `npx @actioneer/ads init` silently
366
+ * no-ops for every consumer. realpath'ing both sides also makes install paths
367
+ * with spaces or non-ASCII compare correctly.
368
+ */
369
+ function invokedAsCli() {
370
+ const entry = process.argv[1];
371
+ if (!entry) return false;
372
+ try {
373
+ return fs.realpathSync(entry) === fs.realpathSync(fileURLToPath(import.meta.url));
374
+ } catch {
375
+ return false;
376
+ }
377
+ }
378
+
379
+ if (invokedAsCli()) {
313
380
  main();
314
381
  }
package/llms.txt CHANGED
@@ -48,6 +48,95 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
48
48
  - `ring`
49
49
  - `overlay`
50
50
 
51
+ ## Design principles
52
+
53
+ The house rules for every ADS UI. `[lint]` = `@actioneer/ads-lint` auto-checks it (pair with `lint_snippet`); `[judgment]` = you must self-apply it — the linter can't.
54
+
55
+ ### 1. Prefer fills & elevation over strokes — but keep a balance (~75/25) [judgment]
56
+
57
+ Delineate SURFACES (cards, panels, sidebars, page regions) with color contrast, elevation, and spacing — not borders. Aim for ~75% shadow/fill, 25% strokes: form controls and floating menus keep a subtle border so they read as interactive; surfaces do not.
58
+
59
+ - Do: Separate regions by fill color first: bg-background → bg-surface → bg-card/bg-elevated → bg-muted.
60
+ - Do: Keep a subtle border-input/border-border on form controls (input, select, textarea, checkbox, radio, segmented-control track) and floating menus (dropdown, popover, listboxes).
61
+ - Do: Keep strokes on focus rings, the outline Button/Badge/Chip variants, Kbd, Divider, the Tree connector rail, and functional color swatches.
62
+ - Don't: Add a border to a surface to separate or group it — use fill/elevation/spacing instead.
63
+ - Don't: Give a filled control no stroke on the tinted canvas — it disappears; it needs a crisp edge.
64
+
65
+ ### 2. Elevation = actionability [judgment]
66
+
67
+ The single shadow-elevation token is an affordance: it goes ONLY on surfaces the user can act on. Never elevate something that can't be clicked. There is no shadow scale.
68
+
69
+ - Do: Elevate actionable surfaces: pressable/hoverable cards, primary CTAs, control thumbs (Switch, Slider, active pills), and interactive floating layers (Modal, Drawer, Popover, Dropdown, listboxes, Toast).
70
+ - Do: Keep static surfaces flat: Panel, plain Card, Kbd, Navbar, headers, rails, docs boxes, Tooltip, InlineDrawer — they read by fill/color.
71
+ - Do: Ask 'can the user click this surface?' — if no, it's flat.
72
+ - Don't: Reintroduce a shadow scale (shadow-xs/sm/md/lg/xl) — there is one token only, shadow-elevation.
73
+ - Don't: Put a shadow on a non-interactive surface for decoration.
74
+
75
+ ### 3. Motion follows the design-engineering guide [lint: unbounded-transition, sluggish-easing, zero-scale-entrance, undersized-zoom-entrance]
76
+
77
+ Every easing/duration/scale flows from a token (--ease-*, --duration-*, --scale-press), mirrored for Motion in src/lib/motion.ts. UI animations stay under 300ms, exits run faster than enters, and reduced motion is respected everywhere.
78
+
79
+ - Do: Use strong curves only — the ease-out utility is the right default; overlays scale in origin-aware from their trigger.
80
+ - Do: Give pressable elements a --scale-press on :active (text/link exempt); start entrances ≥ scale 0.95 with opacity.
81
+ - Do: Respect reduced motion: keep opacity/color fades, drop movement.
82
+ - Don't: Use a slow-starting (accelerating) easing on UI, an unbounded all-property transition, a scale-from-zero entrance, or a UI duration at or over 300ms.
83
+ - Don't: Animate keyboard-initiated or 100×/day actions (e.g. a command-palette toggle).
84
+
85
+ ### 4. Icons: Hugeicons, stroke only [lint: icon-package-import]
86
+
87
+ All icons come from Hugeicons in the Stroke Rounded style only. Components import named icons from the @/lib/icons registry — never from an icon package directly — so a free→Pro swap or a restyle touches one file.
88
+
89
+ - Do: Import icons from the @/lib/icons registry; add a new one there (stroke variant) before using it.
90
+ - Do: Let icons default to size='1em' so they scale with text; size with a size prop or size-* class.
91
+ - Do: Keep stroke weight at the drawn 1.5; strokeWidth={2} is the one sanctioned emphasis step.
92
+ - Don't: Import from an icon package directly, or use solid/duotone/twotone/fill variants.
93
+ - Don't: Use a stroke weight thinner than 1.5.
94
+
95
+ ### 5. Demo screens: the shell owns the frame [judgment]
96
+
97
+ The demo shell applies the screen frame (inset on top/right/bottom, flush-left against the sidebar). Screens never add their own outer padding — a screen's root is flex h-full flex-col and fills the frame with Panel(s).
98
+
99
+ - Do: Make a screen root flex h-full flex-col and fill the frame with Panel(s).
100
+ - Do: Let one place (the shell) own the inset so every screen aligns to the rail.
101
+ - Don't: Add outer padding on a screen, leaving a tinted-canvas gap on the left.
102
+
103
+ ### 6. Status dots are square [judgment]
104
+
105
+ Indicator/status dots (Badge & Chip dot variants, ConnectionStatus, chart legend swatches, presence/pulse dots) are square — rounded-dot (2px), echoing the growth-mark's square cells — never round.
106
+
107
+ - Do: Use rounded-dot for every indicator/status dot.
108
+ - Don't: Use rounded-full on an indicator dot (the one exception is a Radio control's inner dot).
109
+
110
+ ### 7. ADS-first UI: use the library; extend only when asked [lint: deep-import, barrel-aliased-import, barrel-default-import, barrel-namespace-import, external-ui-import]
111
+
112
+ Every UI decision stays synchronized with ADS. Before making a new screen/control/pattern, check the ADS component suite first and use the exact exported name from the public barrel. Do not hand-roll, alias, deep-import, or import external UI libraries.
113
+
114
+ - Do: Use an existing ADS component by its exact exported name from the package barrel; compose existing components for layout-only patterns.
115
+ - Do: Ask the user before extending ADS; only an explicit request authorizes new library work.
116
+ - Do: When authorized, add the component to the right family, export its exact name through the barrel, and document it.
117
+ - Don't: Deep-import, alias, default/namespace-import, or hand-roll a local copy of a component.
118
+ - Don't: Import a visual component directly from the web or an npm UI library.
119
+
120
+ ### 8. Minimal information per screen [judgment]
121
+
122
+ A screen carries ONLY what the user needs to move forward: one title, at most one short supporting line, the inputs, one primary action. Never maximalist. Promote the one message that matters typographically instead of appending muted fine print.
123
+
124
+ - Do: Prefer more, smaller steps over dense ones; ask one thing at a time.
125
+ - Do: Derive instead of asking whenever possible (a name from a work email, the company from its domain).
126
+ - Do: Render multi-step flows full-screen — a single content container that holds the inputs and its own Back/Continue is fine.
127
+ - Don't: Add section eyebrows above a title that already names the screen, or helper text that restates the obvious / duplicates a disabled button's meaning.
128
+ - Don't: Nest panel/step-rail chrome inside a multi-step flow.
129
+
130
+ ### 9. Responsive = container-fluid components, shells own the width [judgment]
131
+
132
+ ADS targets landscape tablet (1024) → laptop (1440) → wide display (1920+); phone/portrait is out of scope. Components adapt to their CONTAINER via container queries; shells and pages decide pane widths through width tokens. Design against under-utilization, not cramping.
133
+
134
+ - Do: Use @container on the pane and @lg:/@xl: variants on children inside components.
135
+ - Do: Set pane widths in shells/pages through width tokens (--thread-max-width, --sidebar-width, --aside-width, --connector-card-min/-max).
136
+ - Do: Cap prose at its measure; let tables/charts/tool cards break out wider. Use auto-fill + minmax(min, 1fr) for grids.
137
+ - Don't: Use sm:/md: viewport variants inside src/components, or hardcode a pane width there.
138
+ - Don't: Cap a grid at a hard column count so it stops growing on wide displays.
139
+
51
140
  ## Components
52
141
 
53
142
  ### Primitives / utilities
@@ -300,6 +389,7 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
300
389
  - [Alert] — Use for persistent inline status messaging on a page (not toasts) — a neutral surface where only the icon and title carry variant color. (variants: variant: default|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/alert)
301
390
  - [AlertDescription] — component (variants: variant: default|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/alert)
302
391
  - [AlertTitle] — component (variants: variant: default|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/alert)
392
+ - [BrandLoader] — Use for a branded loading/generating indicator (inline in a text row or as a standalone full-screen moment) instead of a generic spinner. [docs](https://ads.actioneer.dev/#/brand-loader)
303
393
  - [BrandMark] — component [docs](https://ads.actioneer.dev/#/brand-loader)
304
394
  - [EmptyState] — Use as the centered placeholder inside a list, table, or panel that currently has nothing to show. [docs](https://ads.actioneer.dev/#/empty-state)
305
395
  - [PixelBlastSVG] — component [docs](https://ads.actioneer.dev/#/pixel-blast-svg)
@@ -307,6 +397,7 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
307
397
  - [ProgressCircle] — Use for a compact circular loading/progress indicator (determinate or indeterminate) where a linear bar doesn't fit, e.g. inline with a caption or a small avatar-sized control. [docs](https://ads.actioneer.dev/#/progress-circle)
308
398
  - [Skeleton] — Placeholder the shape of content that's still loading — size it via className and pair with circle for avatars. [docs](https://ads.actioneer.dev/#/skeleton)
309
399
  - [AlertProps] — TypeScript type
400
+ - [BrandLoaderProps] — TypeScript type
310
401
  - [BrandMarkProps] — TypeScript type
311
402
  - [EmptyStateProps] — TypeScript type
312
403
  - [PixelBlastSVGProps] — TypeScript type
@@ -349,7 +440,6 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
349
440
  - [SidebarProps] — TypeScript type
350
441
  - [SidebarSectionProps] — TypeScript type
351
442
  - [useSidebar] — React hook
352
- - [href] — utility
353
443
 
354
444
  ### Layout
355
445
 
@@ -531,7 +621,133 @@ Reference semantic roles, never raw color/dimension literals (ads-lint rejects l
531
621
  - [VoiceStatusDotProps] — TypeScript type
532
622
  - [VoiceVariant] — TypeScript type
533
623
  - [useReasoning] — React hook
534
- - [className] — utility
535
- - [defaultOpen] — utility
536
- - [safeVariant] — utility
537
624
  - [Tool] — utility
625
+
626
+ ### Chat
627
+
628
+ - [ACTIONEER_FILE_ACCEPT] — component [docs](https://ads.actioneer.dev/#/demo/ask)
629
+ - [AssistantActionBar] — component [docs](https://ads.actioneer.dev/#/demo/ask)
630
+ - [AssistantMessage] — component [docs](https://ads.actioneer.dev/#/demo/ask)
631
+ - [AssistantRuntimeProvider] — component [docs](https://ads.actioneer.dev/#/demo/ask)
632
+ - [AttachmentPrimitive] — component [docs](https://ads.actioneer.dev/#/demo/ask)
633
+ - [BranchPicker] — component [docs](https://ads.actioneer.dev/#/demo/ask)
634
+ - [Composer] — component [docs](https://ads.actioneer.dev/#/demo/ask)
635
+ - [ComposerAddAttachment] — component [docs](https://ads.actioneer.dev/#/demo/ask)
636
+ - [ComposerAddDocument] — component [docs](https://ads.actioneer.dev/#/demo/ask)
637
+ - [ComposerAddImage] — component [docs](https://ads.actioneer.dev/#/demo/ask)
638
+ - [ComposerAttachments] — component [docs](https://ads.actioneer.dev/#/demo/ask)
639
+ - [ComposerContextProvider] — component [docs](https://ads.actioneer.dev/#/demo/ask)
640
+ - [ComposerDeepResearch] — component [docs](https://ads.actioneer.dev/#/demo/ask)
641
+ - [ComposerHarness] — component [docs](https://ads.actioneer.dev/#/demo/ask)
642
+ - [ComposerPlaceholdersProvider] — component [docs](https://ads.actioneer.dev/#/demo/ask)
643
+ - [ComposerPrimitive] — component [docs](https://ads.actioneer.dev/#/demo/ask)
644
+ - [ComposerQuotePreview] — component [docs](https://ads.actioneer.dev/#/demo/ask)
645
+ - [ComposerQuotePreviewDismiss] — component [docs](https://ads.actioneer.dev/#/demo/ask)
646
+ - [ComposerQuotePreviewIcon] — component [docs](https://ads.actioneer.dev/#/demo/ask)
647
+ - [ComposerQuotePreviewRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
648
+ - [ComposerQuotePreviewText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
649
+ - [ComposerTriggerPopover] — component [docs](https://ads.actioneer.dev/#/demo/ask)
650
+ - [CONTEXT_MIME] — component [docs](https://ads.actioneer.dev/#/demo/ask)
651
+ - [DeepResearchProvider] — component [docs](https://ads.actioneer.dev/#/demo/ask)
652
+ - [DirectiveText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
653
+ - [EditComposer] — component [docs](https://ads.actioneer.dev/#/demo/ask)
654
+ - [EMPTY_COMPONENTS] — component [docs](https://ads.actioneer.dev/#/demo/ask)
655
+ - [ErrorRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
656
+ - [ErrorText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
657
+ - [File] — component [docs](https://ads.actioneer.dev/#/demo/ask)
658
+ - [FileDownload] — component [docs](https://ads.actioneer.dev/#/demo/ask)
659
+ - [FileIconDisplay] — component [docs](https://ads.actioneer.dev/#/demo/ask)
660
+ - [FileName] — component [docs](https://ads.actioneer.dev/#/demo/ask)
661
+ - [FileRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
662
+ - [FileSize] — component [docs](https://ads.actioneer.dev/#/demo/ask)
663
+ - [FollowUpSuggestion] — component [docs](https://ads.actioneer.dev/#/demo/ask)
664
+ - [HARNESS_MIME] — component [docs](https://ads.actioneer.dev/#/demo/ask)
665
+ - [Image] — component [docs](https://ads.actioneer.dev/#/demo/ask)
666
+ - [ImageActions] — component [docs](https://ads.actioneer.dev/#/demo/ask)
667
+ - [ImageContentFilterError] — component [docs](https://ads.actioneer.dev/#/demo/ask)
668
+ - [ImageFilename] — component [docs](https://ads.actioneer.dev/#/demo/ask)
669
+ - [ImageGenerating] — component [docs](https://ads.actioneer.dev/#/demo/ask)
670
+ - [ImagePreview] — component [docs](https://ads.actioneer.dev/#/demo/ask)
671
+ - [ImageRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
672
+ - [ImageZoom] — component [docs](https://ads.actioneer.dev/#/demo/ask)
673
+ - [MarkdownText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
674
+ - [MessageError] — component [docs](https://ads.actioneer.dev/#/demo/ask)
675
+ - [MessagePrimitive] — component [docs](https://ads.actioneer.dev/#/demo/ask)
676
+ - [MessageTiming] — component [docs](https://ads.actioneer.dev/#/demo/ask)
677
+ - [OpenUiLibraryProvider] — component [docs](https://ads.actioneer.dev/#/demo/ask)
678
+ - [QuoteBlock] — component [docs](https://ads.actioneer.dev/#/demo/ask)
679
+ - [QuoteBlockIcon] — component [docs](https://ads.actioneer.dev/#/demo/ask)
680
+ - [QuoteBlockRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
681
+ - [QuoteBlockText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
682
+ - [RenderAnswerToolUI] — component [docs](https://ads.actioneer.dev/#/demo/ask)
683
+ - [SelectionToolbar] — component [docs](https://ads.actioneer.dev/#/demo/ask)
684
+ - [SelectionToolbarCopy] — component [docs](https://ads.actioneer.dev/#/demo/ask)
685
+ - [SelectionToolbarPrimitive] — component [docs](https://ads.actioneer.dev/#/demo/ask)
686
+ - [SelectionToolbarQuote] — component [docs](https://ads.actioneer.dev/#/demo/ask)
687
+ - [SelectionToolbarRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
688
+ - [SmartMessageText] — component [docs](https://ads.actioneer.dev/#/demo/ask)
689
+ - [Source] — component [docs](https://ads.actioneer.dev/#/demo/ask)
690
+ - [SourceIcon] — component [docs](https://ads.actioneer.dev/#/demo/ask)
691
+ - [Sources] — component [docs](https://ads.actioneer.dev/#/demo/ask)
692
+ - [SourceTitle] — component [docs](https://ads.actioneer.dev/#/demo/ask)
693
+ - [Thread] — component [docs](https://ads.actioneer.dev/#/demo/ask)
694
+ - [ThreadFollowupSuggestions] — component [docs](https://ads.actioneer.dev/#/demo/ask)
695
+ - [ThreadMessage] — component [docs](https://ads.actioneer.dev/#/demo/ask)
696
+ - [ThreadPrimitive] — component [docs](https://ads.actioneer.dev/#/demo/ask)
697
+ - [ThreadSuggestionItem] — component [docs](https://ads.actioneer.dev/#/demo/ask)
698
+ - [ThreadSuggestions] — component [docs](https://ads.actioneer.dev/#/demo/ask)
699
+ - [ToolFallback] — component [docs](https://ads.actioneer.dev/#/demo/ask)
700
+ - [ToolFallbackApproval] — component [docs](https://ads.actioneer.dev/#/demo/ask)
701
+ - [ToolFallbackArgs] — component [docs](https://ads.actioneer.dev/#/demo/ask)
702
+ - [ToolFallbackContent] — component [docs](https://ads.actioneer.dev/#/demo/ask)
703
+ - [ToolFallbackError] — component [docs](https://ads.actioneer.dev/#/demo/ask)
704
+ - [ToolFallbackResult] — component [docs](https://ads.actioneer.dev/#/demo/ask)
705
+ - [ToolFallbackRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
706
+ - [ToolFallbackTrigger] — component [docs](https://ads.actioneer.dev/#/demo/ask)
707
+ - [ToolGroup] — component [docs](https://ads.actioneer.dev/#/demo/ask)
708
+ - [ToolGroupContent] — component [docs](https://ads.actioneer.dev/#/demo/ask)
709
+ - [ToolGroupRoot] — component [docs](https://ads.actioneer.dev/#/demo/ask)
710
+ - [ToolGroupTrigger] — component [docs](https://ads.actioneer.dev/#/demo/ask)
711
+ - [TooltipIconButton] — component [docs](https://ads.actioneer.dev/#/demo/ask)
712
+ - [UserActionBar] — component [docs](https://ads.actioneer.dev/#/demo/ask)
713
+ - [UserMessage] — component [docs](https://ads.actioneer.dev/#/demo/ask)
714
+ - [UserMessageAttachments] — component [docs](https://ads.actioneer.dev/#/demo/ask)
715
+ - [ChatModelAdapter] — TypeScript type
716
+ - [ContextNode] — TypeScript type
717
+ - [CreateDirectiveTextOptions] — TypeScript type
718
+ - [DeepResearchState] — TypeScript type
719
+ - [FileRootProps] — TypeScript type
720
+ - [FollowUpSuggestionProps] — TypeScript type
721
+ - [ImageActionsProps] — TypeScript type
722
+ - [ImageRootProps] — TypeScript type
723
+ - [LocalRuntimeOptions] — TypeScript type
724
+ - [SourceProps] — TypeScript type
725
+ - [StageUsageHandler] — TypeScript type
726
+ - [ThreadComponents] — TypeScript type
727
+ - [ThreadGroupPart] — TypeScript type
728
+ - [ThreadMessageLike] — TypeScript type
729
+ - [ThreadProps] — TypeScript type
730
+ - [ToolCallMessagePartProps] — TypeScript type
731
+ - [ToolFallbackRootProps] — TypeScript type
732
+ - [ToolGroupRootProps] — TypeScript type
733
+ - [TooltipIconButtonProps] — TypeScript type
734
+ - [useAssistantRuntime] — React hook
735
+ - [useAuiState] — React hook
736
+ - [useLocalRuntime] — React hook
737
+ - [ActioneerFileAttachmentAdapter] — utility
738
+ - [ComposerAddContext] — utility
739
+ - [CompositeAttachmentAdapter] — utility
740
+ - [ContextAttachmentAdapter] — utility
741
+ - [createDirectiveText] — utility
742
+ - [fileVariants] — utility
743
+ - [formatFileSize] — utility
744
+ - [getBase64Size] — utility
745
+ - [getMimeTypeIcon] — utility
746
+ - [HarnessAttachmentAdapter] — utility
747
+ - [imageVariants] — utility
748
+ - [isNewChatView] — utility
749
+ - [makeAssistantToolUI] — utility
750
+ - [SimpleImageAttachmentAdapter] — utility
751
+ - [sourceVariants] — utility
752
+ - [ThreadComponentsContext] — utility
753
+ - [toolGroupVariants] — utility