@dbx-tools/ui-mastra 0.9.129 → 0.9.132

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/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  # @dbx-tools/ui-mastra
2
2
 
3
- React chat UI for the AppKit-Mastra plugin.
3
+ Add a React chat surface to
4
+ [@dbx-tools/appkit-mastra](../../node/appkit-mastra). The package supports
5
+ streaming, model selection, AI/BI Genie progress, charts, tables, approvals,
6
+ history, threads, export, and MLflow feedback.
4
7
 
5
- Add a complete chat surface for
6
- [`@dbx-tools/appkit-mastra`](../../node/appkit-mastra), including streaming,
7
- model selection, Genie progress, charts, tables, approvals, history, threads,
8
- export, and MLflow feedback.
9
-
10
- ## Quick Start
8
+ ## Quick start
11
9
 
12
10
  ```tsx
13
11
  import { MastraChat } from "@dbx-tools/ui-mastra/react";
@@ -18,13 +16,16 @@ export function Assistant() {
18
16
  }
19
17
  ```
20
18
 
21
- Key features:
19
+ The stylesheet imports the shared [@dbx-tools/ui](../appkit) foundation. The
20
+ host application must also load Databricks AppKit UI styles.
21
+
22
+ Package contents:
22
23
 
23
- - Drop-in `MastraChat` component that discovers the plugin client config and
24
+ - Drop-in `MastraChat` component that reads the plugin client config and
24
25
  wires itself to the default agent.
25
- - Reload recovery for background turns: active run metadata is persisted per
26
- agent and thread, the cached stream reconnects after a page reload, and the
27
- final persisted history is refreshed when recovery completes.
26
+ - Reload recovery for agent-backed background turns: active run metadata is
27
+ persisted per agent and thread, the cached stream reconnects after a page
28
+ reload, and the final persisted history is refreshed when recovery completes.
28
29
  - Headless `useMastraChat()` driver for apps that want the same transport logic
29
30
  with custom layout.
30
31
  - Persistent `MastraAssistant` application shell with a floating launcher,
@@ -51,38 +52,53 @@ Key features:
51
52
  editor-style tab strip across the top, turn it off, or let `auto` pick between
52
53
  a side panel and tabs from the chat's own width.
53
54
  - Concurrent threads: run several conversations at once, switch between them
54
- while each keeps streaming, and cancel any one independently (per-thread abort
55
- - routing, no shared client state).
55
+ while each keeps streaming, and cancel any one independently. Abort routing
56
+ is per thread, with no shared client state.
56
57
  - Mid-turn steering queue: messages submitted while a turn streams stack up as
57
- pending steers (they drain oldest-first when the turn ends); each queued item
58
+ pending steers. They drain oldest-first when the turn ends. Each queued item
58
59
  can be sent now (interrupting the current turn), removed, or dragged to
59
60
  reorder the queue.
60
61
  - Export menu for PDF and Markdown, resolving charts and tables so
61
62
  exported conversations remain useful offline.
62
63
 
63
- ## Choose This UI Or AppKit UI
64
+ ## Choose a UI package
64
65
 
65
- Use native `@databricks/appkit-ui` when you need its general primitives, Genie
66
- chat component, or Model Serving hooks directly against native AppKit plugins.
66
+ Use native `@databricks/appkit-ui` for its general primitives, AI/BI Genie chat,
67
+ or Model Serving hooks with native AppKit plugins.
67
68
 
68
69
  Use this package when the server is
69
- [`@dbx-tools/appkit-mastra`](../../node/appkit-mastra) and the UI needs to
70
+ [@dbx-tools/appkit-mastra](../../node/appkit-mastra) and the UI needs to
70
71
  understand Mastra-specific behavior:
71
72
 
72
73
  - Mastra's official AI SDK chat stream, native resource-scoped memory APIs, and
73
74
  the plugin's model, suggestion, feedback, chart, and statement routes.
74
75
  - Suspended `requireApproval` tool calls resumed through native `resumeData`.
75
- - Genie writer events rendered as inline tool progress, not just a terminal
76
- answer.
76
+ - Genie writer events rendered as inline tool progress rather than only a
77
+ terminal answer.
77
78
  - `[chart:<id>]` and `[data:<id>]` assistant markers rendered as ECharts charts
78
79
  and sortable tables.
79
80
  - Concurrent multi-thread streaming, per-thread cancel, and a mid-turn steering
80
- queue (submit while running to enqueue; drain oldest-first, or send any item
81
- now to interrupt) - the native AppKit chat surface runs one turn at a time and
81
+ queue. Submit while running to enqueue, drain oldest-first, or send any item
82
+ immediately to interrupt. The native AppKit chat surface runs one turn at a time and
82
83
  has no steering.
83
84
  - Conversation export that resolves those embeds into Markdown or PDF.
84
85
 
85
- ## Stylesheet Setup
86
+ Import the AppKit UI stylesheet before this package's stylesheet. Mount the chat
87
+ inside the application's authentication boundary. Agent chat can use either
88
+ user identity or service-principal identity according to the server plugin's
89
+ configuration. Direct Genie chat requires the signed-in user's on-behalf-of
90
+ (OBO) context.
91
+
92
+ `MastraChat` reads the `mastra` plugin's published `clientConfig()` payload
93
+ through AppKit. The payload supplies the mount path, default agent, registered
94
+ agents, feedback availability, background-turn support, and chat identity
95
+ behavior. Don't hard-code plugin routes in browser code.
96
+
97
+ Use [@dbx-tools/ui](../appkit) for common AppKit, authentication, email, and
98
+ search components. Use [@dbx-tools/ui-teams](../teams) for Microsoft Teams
99
+ Adaptive Cards and conversation previews.
100
+
101
+ ## Configure styles
86
102
 
87
103
  ```css
88
104
  @import "@databricks/appkit-ui/styles.css";
@@ -90,10 +106,10 @@ understand Mastra-specific behavior:
90
106
  ```
91
107
 
92
108
  The stylesheet imports the shared `@dbx-tools/ui` foundation and registers
93
- this package's React files with Tailwind. It does not define design tokens; the
109
+ this package's React files with Tailwind. It does not define design tokens. The
94
110
  chat UI uses AppKit semantic tokens from the host app.
95
111
 
96
- ## Add A Persistent Assistant
112
+ ## Add a persistent assistant
97
113
 
98
114
  Mount `MastraAssistant` inside the app's existing authentication gate and above
99
115
  the route outlet. Closing the panel hides its presentation without unmounting
@@ -127,7 +143,7 @@ export function App() {
127
143
  }
128
144
  ```
129
145
 
130
- `mode="dock"` reflows the child application; `mode="overlay"` overlaps it.
146
+ `mode="dock"` reflows the child application. `mode="overlay"` overlaps it.
131
147
  `side` accepts `top`, `right`, `bottom`, or `left`. Set `resizable={false}` to
132
148
  lock size, `launcher={false}` when every launch comes from
133
149
  `useMastraAssistant()`, `header={false}` to place New, History, and Close beside
@@ -138,13 +154,10 @@ the conversation pills remain on their own second row. Replace `icon`, `closeIco
138
154
  dismissal while the covered application is inert. A `storageKey` retains
139
155
  horizontal and vertical sizes independently.
140
156
 
141
- This shell intentionally remains mounted instead of wrapping AppKit
142
- Sheet/Dialog/Resizable. Those overlays unmount their portal subtree when closed,
143
- and native resizable panels persist percentages rather than this component's
144
- independent horizontal/vertical pixel sizes; either change would lose drafts,
145
- scroll state, active streams, or sizing parity.
157
+ `MastraAssistant` remains mounted when closed, which preserves drafts, scroll
158
+ state, active streams, and independent horizontal and vertical sizes.
146
159
 
147
- ## Render A Drop-In Chat
160
+ ## Render a drop-in chat
148
161
 
149
162
  ```tsx
150
163
  import { MastraChat } from "@dbx-tools/ui-mastra/react";
@@ -162,16 +175,17 @@ export function App() {
162
175
  }
163
176
  ```
164
177
 
165
- `MastraChat` is the quickest client for the AppKit-Mastra plugin. It reads the
178
+ `MastraChat` provides the bundled client for the AppKit-Mastra plugin. It reads the
166
179
  plugin's published client config, creates a `MastraPluginClient`, streams turns
167
180
  through Mastra's official AI SDK chat route, hydrates native memory, and renders
168
181
  the controlled `ChatView`. When Mastra returns persisted `messages` without a
169
182
  precomputed `uiMessages` projection, history hydration uses Mastra's native
170
183
  `convertMessages(...).to("AIV5.UI")` conversion.
171
184
 
172
- Useful options:
185
+ Configure the client with these options:
173
186
 
174
- - `agentId` selects a registered agent; defaults to the plugin default agent.
187
+ - `agentId` selects a registered agent and defaults to the plugin default agent.
188
+ - `genieSpace` selects a configured Genie alias and bypasses the agent.
175
189
  - `showModelPicker` fetches `/models` and sends `X-Mastra-Model` overrides.
176
190
  - `composerActions` places host-owned per-turn controls beside the model
177
191
  selector without replacing the built-in composer.
@@ -179,21 +193,52 @@ Useful options:
179
193
  the endpoint choices. Supply it only when the active agent supports that
180
194
  option, such as a Genie transport toggle.
181
195
  - `composerLeadingActions` places attachment or app actions on the left side of
182
- the fixed composer footer. The textarea grows above it to a cap, then scrolls;
183
- model and Send/Stop stay pinned bottom-right.
184
- - `suggestions` overrides Genie starter questions; omit it to auto-fetch
196
+ the fixed composer footer. The textarea grows above it to a cap, then scrolls.
197
+ Model and Send/Stop stay pinned bottom-right.
198
+ - `suggestions` overrides Genie starter questions. Omit it to auto-fetch
185
199
  `/suggestions`, or pass `[]` to hide suggestions.
186
200
  - `threadPlacement` chooses where conversation management renders, or turns it
187
- off. See [Place The Conversation List](#place-the-conversation-list).
188
- - `enableThreads: false` is the older shorthand for
201
+ off. See [Place the conversation list](#place-the-conversation-list).
202
+ - `enableThreads: false` also sets
189
203
  `threadPlacement: "disabled"`.
204
+ - `threadId` and `onThreadIdChange` let a host bind the active conversation to
205
+ URL state or another external selector. Unknown external IDs are replaced by
206
+ a new thread and reported with the `missing` reason.
190
207
  - `enableExport` adds whole-conversation and per-message export affordances.
191
208
  - Feedback defaults to auto: thumbs, dislike, and comment controls appear when
192
209
  the server reports MLflow feedback is available and a turn produced a trace
193
210
  id. Set `enableFeedback={false}` to hide them. Viewers with `CAN_MANAGE` on
194
211
  the experiment also get an experiment debug link at the end of the action row.
195
212
 
196
- ## Place The Conversation List
213
+ ## Use direct Genie chat
214
+
215
+ Use `genieSpace` when the application needs the same chat shell without a
216
+ supervisor agent:
217
+
218
+ ```tsx
219
+ <MastraChat genieSpace="sales" threadPlacement="auto" enableExport />
220
+ ```
221
+
222
+ The alias comes from the server plugin's `genieSpaces`. The client still uses
223
+ AI SDK `UIMessage` streams and the same `ChatView`. Genie conversations replace
224
+ Mastra threads and Genie messages replace Mastra Memory history.
225
+
226
+ Turns and history require the Genie Agent API and never fall back to classic
227
+ Genie message polling. The sidebar filters the Genie conversation listing to
228
+ Agent Mode conversations. Genie decides whether a query should be visualized.
229
+ Visualization attachments render through AppKit UI's native
230
+ `GenieQueryVisualization`, with Chart and Table tabs. This does not invoke a
231
+ supervisor or the Mastra Model Serving chart planner. Queries without a
232
+ visualization attachment render through the existing sortable data table.
233
+
234
+ Direct mode requires the signed-in user's Databricks OBO context. It supports
235
+ new/select/delete conversations, history, suggestions, thoughts, exports, and
236
+ stream cancellation. It does not support conversation rename, file
237
+ attachments, MLflow feedback, approvals, background turns, or stream
238
+ reconnection. The newest 100 conversations are listed and each selected
239
+ conversation loads as one history page.
240
+
241
+ ## Place the conversation list
197
242
 
198
243
  Conversation management is on by default. Where it lives is one option:
199
244
 
@@ -206,33 +251,37 @@ Conversation management is on by default. Where it lives is one option:
206
251
  | `auto` (default) | `left` while the chat is wide, `top` once it is too narrow for a panel |
207
252
  | `left` / `right` | List docked to that edge, collapsing to an overlay drawer on a narrow chat |
208
253
  | `top` | Tab strip of open conversations, with a history menu for the rest |
209
- | `disabled` | No thread UI - the classic single-thread chat on the session cookie |
254
+ | `disabled` | No thread UI. Uses a single thread on the session cookie |
210
255
 
211
256
  The docked placements render the sidebar as an inline column with a persisted
212
257
  show/hide toggle. Below 768px of chat width the panel becomes an overlay drawer
213
- on the same edge, so the transcript never loses room; the drawer is
258
+ on the same edge, so the transcript never loses room. The drawer is
214
259
  session-scoped and starts closed, and closes itself after a selection.
215
260
 
261
+ The composer accepts images from the upload action, drag and drop, or clipboard
262
+ paste. Oversized images use the same client-side resize path before submission.
263
+
216
264
  The `top` placement is the editor-tab model: each open conversation is a tab with
217
265
  its title, a spinner while it streams in the background, and a close affordance
218
266
  that only takes the tab off the strip (the conversation stays in history). A `+`
219
- starts a fresh conversation and a history button opens the full list - the same
220
- sidebar, framed as a menu - so rename, delete, and cancel still work on anything
221
- not currently tabbed. Closing the active tab moves to a neighbouring one, or
267
+ starts a fresh conversation. The history button opens the full sidebar as a
268
+ menu, so rename, delete, and cancel still work on conversations that aren't on
269
+ the tab strip. Closing the active tab moves to a neighboring one, or
222
270
  starts a fresh conversation when it was the last tab open. The open set is
223
- session state; the strip reseeds from the most recent conversations on the next
271
+ session state. The strip reseeds from the most recent conversations on the next
224
272
  load.
225
273
 
226
- Selecting a conversation fetches only the newest 20 native memory messages.
227
- Scrolling upward requests the next page and prepends it without moving the
228
- reader's viewport. Agent turns still send only the new user message; Mastra
229
- loads the remembered transcript server-side.
274
+ For agent-backed chat, selecting a conversation fetches only the newest 20
275
+ native memory messages. Scrolling upward requests the next page and prepends it
276
+ without moving the reader's viewport. Agent turns still send only the new user
277
+ message. Mastra loads the remembered transcript server-side. Direct Genie mode
278
+ loads the selected Genie conversation in one page.
230
279
 
231
280
  `auto` measures the chat's own element rather than the viewport, so a chat
232
281
  embedded in a split view or side panel switches to tabs on the space it actually
233
282
  has instead of waiting for the window to shrink.
234
283
 
235
- ## Use The Headless Driver
284
+ ## Use the headless driver
236
285
 
237
286
  ```tsx
238
287
  import { ChatView, useMastraChat } from "@dbx-tools/ui-mastra/react";
@@ -248,11 +297,11 @@ export function CustomChat() {
248
297
  }
249
298
  ```
250
299
 
251
- Use `useMastraChat()` when the stock behavior is right but the surrounding layout
252
- belongs to your app. The hook owns streaming, aborts, history paging, thread
300
+ Use `useMastraChat()` when you want package transport behavior with your own
301
+ layout. The hook owns streaming, aborts, history paging, thread
253
302
  selection, model overrides, suggestions, exports, approvals, and feedback state.
254
303
 
255
- ## Pass Typed Application Context
304
+ ## Pass typed application context
256
305
 
257
306
  `requestContext` accepts a typed plain record, Mastra `RequestContext<T>`, or a
258
307
  per-turn resolver. The driver snapshots it when a message is submitted and
@@ -274,7 +323,7 @@ On the server, declare the same contract with Mastra's native
274
323
  cannot override the authenticated memory resource, thread, user, scopes, model,
275
324
  or trace fields stamped by AppKit-Mastra.
276
325
 
277
- ## Build A Controlled Chat Surface
326
+ ## Build a controlled chat surface
278
327
 
279
328
  ```tsx
280
329
  import { ChatView, type ChatViewProps } from "@dbx-tools/ui-mastra/react";
@@ -294,66 +343,45 @@ is being resolved. The picker groups endpoints into
294
343
  model-family submenus. Its compact first popup shows only the current
295
344
  model, host-owned actions such as Genie Agent Mode, and a reasoning slider when
296
345
  the selected endpoint supports it. The current model opens the family picker,
297
- so the long endpoint catalogue stays out of the primary control popup. Family
346
+ so the long endpoint catalog stays out of the primary control popup. Family
298
347
  and model menus use the same compact utility type as the composer actions,
299
348
  omit repeated headers, and omit the already-selected model. The model menu puts
300
349
  `Default (<resolved model>)` first, keeps `Other` last, and makes a one-model
301
350
  family directly selectable instead of opening another submenu.
302
351
 
303
- ## Call Plugin Routes Directly
352
+ ## Call plugin routes directly
304
353
 
305
354
  ```ts
306
- import {
307
- MastraPluginClient,
308
- useMastraClient,
309
- useMastraDefaultModel,
310
- useMastraModels,
311
- useMastraSuggestions,
312
- useMastraThreads,
313
- } from "@dbx-tools/ui-mastra/react";
314
-
315
- const client = new MastraPluginClient(clientConfig);
316
-
317
- // Routing (thread + model) is passed per call, so concurrent runs on
318
- // different threads never share state.
319
- const stream = await client.streamAgent({
320
- agentId: client.defaultAgent,
321
- messages: [
322
- {
323
- id: "user-1",
324
- role: "user",
325
- parts: [{ type: "text", text: "Hello" }],
326
- },
327
- ],
328
- runId,
329
- threadId: activeThreadId,
330
- model: "claude sonnet",
331
- signal: controller.signal,
332
- });
355
+ import type { MastraClientConfig } from "@dbx-tools/shared-mastra";
356
+ import { MastraPluginClient } from "@dbx-tools/ui-mastra/react";
333
357
 
334
- const models = await client.models();
335
- const history = await client.history({ threadId: activeThreadId, page: 0, perPage: 20 });
358
+ export async function listChatModels(clientConfig: MastraClientConfig) {
359
+ const client = new MastraPluginClient(clientConfig);
360
+ return client.models();
361
+ }
336
362
  ```
337
363
 
338
364
  Each conversation thread runs independently: start a turn on one thread, switch
339
- to another and start a second, and both stream concurrently. Cancel one via its
365
+ to another and start a second, and both stream concurrently. Cancel one using its
340
366
  `AbortSignal` (or the driver's `onCancelThread`) without touching the others.
341
367
 
342
368
  `MastraPluginClient` extends `@mastra/client-js` with the official AI SDK
343
369
  `chatRoute` transport and AppKit-Mastra additions. It uses
344
370
  `credentials: "include"` so session cookies travel with streaming and REST
345
- calls. The React hooks wrap native memory plus model catalogues, suggestions,
346
- chart fetches, and statement-data fetches.
371
+ calls. The React hooks wrap native memory plus model catalogs, suggestions,
372
+ chart fetches, and statement-data fetches. Use `useMastraClient()` to access the
373
+ configured client inside React. `useMastraModels()`, `useMastraDefaultModel()`,
374
+ `useMastraSuggestions()`, and `useMastraThreads()` expose route-specific state.
347
375
 
348
- ## Approvals, Embeds, And Feedback
376
+ ## Handle approvals, embeds, and feedback
349
377
 
350
378
  The UI understands the extra events produced by
351
- [`@dbx-tools/appkit-mastra`](../../node/appkit-mastra):
379
+ [@dbx-tools/appkit-mastra](../../node/appkit-mastra):
352
380
 
353
381
  - Approval chunks become inline approval cards and continue the official chat
354
382
  route with Mastra's native `{ approved, reason? }` resume data.
355
383
  - Native tool-call and tool-result payloads remain complete. Expanding a tool
356
- row reveals default-closed Request and Response viewers; large values scroll
384
+ row reveals default-closed Request and Response viewers. Large values scroll
357
385
  without string or collection truncation.
358
386
  - Genie `thinking` events stream into the assistant's collapsed Thoughts
359
387
  panel. Intermediate answer attachments and query-result tables stay on tool
@@ -363,45 +391,30 @@ The UI understands the extra events produced by
363
391
  - `[chart:<id>]` markers long-poll the chart cache and render ECharts inline.
364
392
  - `[data:<id>]` markers fetch statement rows and render a sortable table with
365
393
  column toggles and CSV export.
394
+ - `[visualization:<id>]` markers fetch the same statement under OBO identity and
395
+ render AppKit UI's native Genie Chart/Table component.
366
396
  - MLflow trace headers enable per-message feedback controls when the server
367
397
  reports feedback is available.
368
398
 
369
- ## Chart Theming
370
-
371
- An ECharts chart draws to a canvas, so it inherits nothing from CSS the way its
372
- frame does: a dark theme re-skins the border around the chart while the axis
373
- labels, grid lines, and tooltip inside keep whatever colors the spec was born
374
- with. And the spec is born on the server, in
375
- [`@dbx-tools/appkit-mastra`](../../node/appkit-mastra), which cannot know the
376
- reader's theme.
377
-
378
- So the two halves are split. The planner inlines only what is
379
- theme-independent - the brand's series palette and font stack. Everything
380
- theme-dependent is resolved here at render time by `src/support/chart-theme.ts`,
381
- which reads AppKit's `--chart-axis-label`, `--chart-axis-title`, `--chart-grid`,
382
- and `--chart-tooltip-bg` (plus `--popover-foreground` and `--border` for the
383
- tooltip) into a `ChartChrome`, and `normalizeChartOption` paints it onto the
384
- axes, title, legend, and tooltip. Nothing to configure: a chart follows the
385
- theme wherever it renders.
386
-
387
- Two details worth knowing if you embed the chat:
388
-
389
- - Tokens are read off the **chart's own element**, not `:root`, so a theme
390
- scoped to a subtree - a chat panel inside an otherwise-light app - wins. The
391
- value re-resolves when a `.dark` / `.light` class lands on the document root
392
- and when the OS `prefers-color-scheme` flips, so a live theme switch recolors
393
- charts in place.
399
+ ## Configure chart themes
400
+
401
+ ECharts draws to a canvas and doesn't inherit CSS colors from its frame. The
402
+ server planner provides the series palette and font stack. The browser resolves
403
+ axis, grid, title, legend, and tooltip colors from AppKit semantic tokens at
404
+ render time.
405
+
406
+ - Theme tokens are read from the chart element, so a theme scoped to a chat
407
+ subtree takes precedence over the document theme. Charts update when the
408
+ document's `.dark` or `.light` class changes or when the operating-system
409
+ color preference changes.
394
410
  - AppKit darkens its tokens under `@media (prefers-color-scheme: dark)` for any
395
411
  `:root` that is not explicitly `.light`. If your host renders its own light
396
412
  chrome, pin `.light` (or `.dark`) on `:root` rather than leaving AppKit on the
397
- OS preference, or the chat will read as half-dark while everything around it
398
- stays light.
413
+ operating-system preference.
399
414
 
400
- The PDF export is the one caller that does not follow the page: it pins
401
- `LIGHT_CHART_CHROME`, because its document forces `color-scheme: light` on a
402
- white body for printing.
415
+ PDF export uses a light chart theme on a white print document.
403
416
 
404
- ## Export Conversations
417
+ ## Export conversations
405
418
 
406
419
  ```tsx
407
420
  <MastraChat enableExport />
@@ -412,65 +425,41 @@ resolved during export: charts are rendered to inline SVG with ECharts' server
412
425
  renderer, and data markers become real tables. Expired or missing embeds are
413
426
  skipped so old transcripts still export cleanly.
414
427
 
415
- ## Copying And Downloading
428
+ ## Copy and download content
416
429
 
417
- Copy and download affordances appear in several places - message bubbles, code
418
- blocks, conversation export, and the data-grid CSV button - and they behave the
419
- same everywhere because each is backed by one internal module rather than
420
- per-component code.
430
+ Copy and download controls appear in message bubbles, code blocks, conversation
431
+ exports, and the data-grid CSV menu.
421
432
 
422
433
  Copying works on hosts served over plain HTTP. An insecure context has no
423
434
  Clipboard API, so a bare `navigator.clipboard.writeText` silently does nothing on
424
- a local or intranet deployment; the shared helper falls back to a hidden
435
+ a local or intranet deployment. The package falls back to a hidden
425
436
  `<textarea>` plus `document.execCommand("copy")` and reports whether the copy
426
437
  actually succeeded. Downloads revoke their object URL after the temporary anchor
427
438
  fires, so a long session does not accumulate blobs.
428
439
 
429
- If you build a controlled surface with `ChatView`, you get both without wiring
430
- anything. Adding a new copy or download button anywhere in this package should
431
- reuse `src/support/clipboard.ts` and `src/support/download.ts` instead of
432
- touching `navigator.clipboard` or `URL.createObjectURL` again.
433
-
434
- ## Modules
440
+ ## Package exports
435
441
 
436
- - `MastraChat` - self-contained drop-in chat component.
437
- - `MastraAssistant` / `useMastraAssistant` - persistent application shell and
442
+ - `MastraChat`: self-contained drop-in chat component.
443
+ - `MastraAssistant` / `useMastraAssistant`: persistent application shell and
438
444
  external open/close/context controller.
439
- - `useMastraChat` - headless driver that returns `ChatView` props.
440
- - `ChatView` - controlled presentational chat shell.
441
- - `MastraPluginClient` - native `@mastra/client-js` memory/agent APIs plus
445
+ - `useMastraChat`: headless driver that returns `ChatView` props.
446
+ - `ChatView`: controlled presentational chat shell.
447
+ - `MastraPluginClient`: native `@mastra/client-js` memory/agent APIs plus
442
448
  AppKit-Mastra model, suggestion, feedback, and embed routes.
443
449
  - `useMastraClient`, `useMastraConfig`, `useMastraModels`,
444
450
  `useMastraDefaultModel`, `useMastraSuggestions`, `useMastraThreads`,
445
- `useChartFetch`, `useStatementFetch` - route/config hooks for controlled
451
+ `useChartFetch`, `useStatementFetch`: route/config hooks for controlled
446
452
  clients.
447
- - `ThreadSidebar` - controlled conversation list, dockable to either edge.
448
- - `ThreadTabs` / `ThreadActions` - conversation pills plus reusable New/History
453
+ - `ThreadSidebar`: controlled conversation list, dockable to either edge.
454
+ - `ThreadTabs` / `ThreadActions`: conversation pills plus reusable New/History
449
455
  controls for the top strip or persistent assistant header.
450
- - `ExportMenu` - shared export format menu.
451
- - `src/support/thread-tabs.ts` - pure open-tab bookkeeping (`syncThreadTabs`,
452
- `closeThreadTab`, `nextActiveThreadTab`) so the strip's state is testable
453
- without a DOM.
454
- - `src/support/thread-labels.ts` - `threadTitle` / `relativeTime`, shared by
455
- the sidebar and the tab strip so a row and a tab never disagree about how an
456
- untitled or freshly-updated conversation reads.
457
- - `src/support/request-context.ts` - immutable per-run snapshots around Mastra's
458
- native typed `RequestContext`.
459
- - `src/support/tool-events.ts` - projection of native AI SDK persisted tool
460
- parts onto the live pill view model.
461
- - `src/support/chart-theme.ts` - `ChartChrome`, `LIGHT_CHART_CHROME`,
462
- `resolveChartChrome`, and the `useChartChrome` hook that keeps an inline
463
- chart's colors in step with the active theme.
464
- - `src/support/chart-option.ts` - `normalizeChartOption`, the pure pass that
465
- patches layout (compact ticks, axis-name placement, title/grid spacing) and
466
- an optional `ChartChrome` into a planner spec, shared by the inline chart and
467
- the PDF export so both read the same.
468
- - Types - `ChatViewProps`, `MastraChatProps`, `UseMastraChatOptions`,
456
+ - `ExportMenu`: shared export format menu.
457
+ - Types: `ChatViewProps`, `MastraChatProps`, `UseMastraChatOptions`,
469
458
  `MastraAssistantProps`, `MastraRequestContextInput`, `ThreadPlacement`,
470
459
  `ThreadSummary`, `ToolEvent`, `ToolProgress`, `PendingApproval`,
471
460
  `FeedbackSubmission`, and related UI contract types.
472
461
 
473
462
  Server-side routes and event production live in
474
- [`@dbx-tools/appkit-mastra`](../../node/appkit-mastra). Browser-safe route,
463
+ [@dbx-tools/appkit-mastra](../../node/appkit-mastra). Browser-safe route,
475
464
  marker, feedback, and wire schemas live in
476
- [`@dbx-tools/shared-mastra`](../../shared/mastra).
465
+ [@dbx-tools/shared-mastra](../../shared/mastra).
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/ui-mastra";
6
- export const PACKAGE_VERSION = "0.9.129";
6
+ export const PACKAGE_VERSION = "0.9.132";
7
7
  export * as reactBubbles from "./src/react/bubbles.tsx";
8
8
  export * as reactChatApprovals from "./src/react/chat-approvals.ts";
9
9
  export * as reactChatComposer from "./src/react/chat-composer.tsx";
@@ -33,10 +33,12 @@ export * as supportChartTheme from "./src/support/chart-theme.ts";
33
33
  export * as supportClipboard from "./src/support/clipboard.ts";
34
34
  export * as supportDownload from "./src/support/download.ts";
35
35
  export * as supportExport from "./src/support/export.ts";
36
+ export * as supportGenieClient from "./src/support/genie-client.ts";
36
37
  export * as supportMastraClient from "./src/support/mastra-client.ts";
37
38
  export * as supportModelSelection from "./src/support/model-selection.ts";
38
39
  export * as supportRequestContext from "./src/support/request-context.ts";
39
40
  export * as supportThreadLabels from "./src/support/thread-labels.ts";
41
+ export * as supportThreadPersistence from "./src/support/thread-persistence.ts";
40
42
  export * as supportThreadSessions from "./src/support/thread-sessions.ts";
41
43
  export * as supportThreadTabs from "./src/support/thread-tabs.ts";
42
44
  export * as supportToolEvents from "./src/support/tool-events.ts";
@@ -55,7 +57,7 @@ export { FeedbackControls } from "./src/react/feedback-controls.tsx";
55
57
  export { AssistantMarkdown, ToolMarkdown, SqlBlock, SourceBlock } from "./src/react/markdown.tsx";
56
58
  export type { MastraAssistantMode, MastraAssistantSide, MastraAssistantLauncherPosition, MastraAssistantResizeOptions, MastraAssistantLauncherOptions, MastraAssistantController, MastraAssistantProps } from "./src/react/mastra-assistant.tsx";
57
59
  export { useMastraChat, MastraChat } from "./src/react/mastra-chat.tsx";
58
- export type { UseMastraChatOptions, MastraChatProps } from "./src/react/mastra-chat.tsx";
60
+ export type { ThreadIdChangeReason, UseMastraChatOptions, MastraChatProps } from "./src/react/mastra-chat.tsx";
59
61
  export { SuggestionPills } from "./src/react/suggestion-pills.tsx";
60
62
  export type { SuggestionPillsProps } from "./src/react/suggestion-pills.tsx";
61
63
  export { dedupeSuggestions, collectSuggestions } from "./src/react/suggestions.ts";
@@ -71,7 +73,8 @@ export type { StoredActiveRun } from "./src/support/active-runs.ts";
71
73
  export { LIGHT_CHART_CHROME } from "./src/support/chart-theme.ts";
72
74
  export type { ChartChrome } from "./src/support/chart-theme.ts";
73
75
  export type { ExportFormat, ExportBrand, EmbedResolver, ExportChatOptions } from "./src/support/export.ts";
74
- export { MastraChatRequestError, MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch } from "./src/support/mastra-client.ts";
76
+ export { GenieChatClient } from "./src/support/genie-client.ts";
77
+ export { MastraChatRequestError, MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch, useVisualizationFetch } from "./src/support/mastra-client.ts";
75
78
  export type { MastraStreamResponse, MastraMemoryThread, ByIdFetchState } from "./src/support/mastra-client.ts";
76
79
  export { defaultReasoningEffort, modelStorageKey, readStoredModel, storeSelectedModel } from "./src/support/model-selection.ts";
77
80
  export type { MastraRequestContextInput, MastraRequestContextSource, MastraRequestContextSnapshot } from "./src/support/request-context.ts";
package/package.json CHANGED
@@ -29,11 +29,12 @@
29
29
  "react-dom": "~19.2.4"
30
30
  },
31
31
  "dependencies": {
32
- "@dbx-tools/shared-core": "^0.9.129",
33
- "@dbx-tools/shared-genie": "^0.9.129",
34
- "@dbx-tools/shared-mastra": "^0.9.129",
35
- "@dbx-tools/shared-model": "^0.9.129",
36
- "@dbx-tools/ui": "^0.9.129",
32
+ "@databricks/appkit-ui": "0.81.0",
33
+ "@dbx-tools/shared-core": "^0.9.132",
34
+ "@dbx-tools/shared-genie": "^0.9.132",
35
+ "@dbx-tools/shared-mastra": "^0.9.132",
36
+ "@dbx-tools/shared-model": "^0.9.132",
37
+ "@dbx-tools/ui": "^0.9.132",
37
38
  "@mastra/client-js": "1.50.0",
38
39
  "@mastra/core": "1.71.0",
39
40
  "@tanstack/react-table": "^8.21.3",
@@ -50,7 +51,7 @@
50
51
  "publishConfig": {
51
52
  "access": "public"
52
53
  },
53
- "version": "0.9.129",
54
+ "version": "0.9.132",
54
55
  "dbxToolsConfig": {
55
56
  "tags": [
56
57
  "ui"
@@ -18,6 +18,7 @@ import type { UIMessage } from "ai";
18
18
  import {
19
19
  BugIcon,
20
20
  CheckIcon,
21
+ ChevronDownIcon,
21
22
  CopyIcon,
22
23
  MessageSquareIcon,
23
24
  RefreshCcwIcon,
@@ -63,7 +64,8 @@ const UserAvatar = () => (
63
64
 
64
65
  const ThoughtsDisclosure = ({ text }: { text: string }) => (
65
66
  <Collapsible>
66
- <CollapsibleTrigger className="w-fit cursor-pointer rounded-md border border-border/40 bg-background/30 px-2 py-1 text-xs text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
67
+ <CollapsibleTrigger className="group flex w-fit cursor-pointer items-center gap-1.5 px-0 py-0.5 text-left text-xs text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
68
+ <ChevronDownIcon className="size-3 shrink-0 transition-transform group-data-[state=closed]:-rotate-90" />
67
69
  Thoughts
68
70
  </CollapsibleTrigger>
69
71
  <CollapsibleContent>