@dbx-tools/ui-mastra 0.9.119 → 0.9.121
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 +1 -0
- package/index.ts +2 -2
- package/package.json +6 -6
- package/src/react/bubbles.tsx +2 -0
- package/src/react/chat-composer.tsx +1 -1
- package/src/react/chat-feedback.ts +1 -1
- package/src/react/chat-history.ts +3 -3
- package/src/react/chat-sessions.ts +3 -0
- package/src/react/chat-stream.ts +1 -1
- package/src/react/chat-thread-layout.tsx +1 -1
- package/src/react/data-grid.tsx +1 -0
- package/src/react/feedback-controls.tsx +1 -0
- package/src/react/mastra-chat.tsx +14 -10
- package/src/react/suggestion-pills.tsx +1 -0
- package/src/react/tool-pill.tsx +2 -0
- package/src/support/index.ts +1 -1
- package/src/support/mastra-client.ts +15 -1
- package/src/support/thread-sessions.ts +3 -0
package/README.md
CHANGED
|
@@ -288,6 +288,7 @@ export function ReviewChat(props: ChatViewProps) {
|
|
|
288
288
|
sidebar, transcript, tool progress, approval cards, suggestions, export controls,
|
|
289
289
|
feedback controls, and composer from props. Use it when your app already has a
|
|
290
290
|
transport or needs to combine Mastra messages with another state model.
|
|
291
|
+
|
|
291
292
|
`MastraChat` shows a spinner in the model control while its live default model
|
|
292
293
|
is being resolved. The picker groups endpoints into
|
|
293
294
|
model-family submenus. Its compact first popup shows only the current
|
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.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.121";
|
|
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";
|
|
@@ -71,7 +71,7 @@ export type { StoredActiveRun } from "./src/support/active-runs.ts";
|
|
|
71
71
|
export { LIGHT_CHART_CHROME } from "./src/support/chart-theme.ts";
|
|
72
72
|
export type { ChartChrome } from "./src/support/chart-theme.ts";
|
|
73
73
|
export type { ExportFormat, ExportBrand, EmbedResolver, ExportChatOptions } from "./src/support/export.ts";
|
|
74
|
-
export { MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch } from "./src/support/mastra-client.ts";
|
|
74
|
+
export { MastraChatRequestError, MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch } from "./src/support/mastra-client.ts";
|
|
75
75
|
export type { MastraStreamResponse, MastraMemoryThread, ByIdFetchState } from "./src/support/mastra-client.ts";
|
|
76
76
|
export { defaultReasoningEffort, modelStorageKey, readStoredModel, storeSelectedModel } from "./src/support/model-selection.ts";
|
|
77
77
|
export type { MastraRequestContextInput, MastraRequestContextSource, MastraRequestContextSnapshot } from "./src/support/request-context.ts";
|
package/package.json
CHANGED
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"react-dom": "~19.2.4"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
33
|
-
"@dbx-tools/shared-genie": "^0.9.
|
|
34
|
-
"@dbx-tools/shared-mastra": "^0.9.
|
|
35
|
-
"@dbx-tools/shared-model": "^0.9.
|
|
36
|
-
"@dbx-tools/ui": "^0.9.
|
|
32
|
+
"@dbx-tools/shared-core": "^0.9.121",
|
|
33
|
+
"@dbx-tools/shared-genie": "^0.9.121",
|
|
34
|
+
"@dbx-tools/shared-mastra": "^0.9.121",
|
|
35
|
+
"@dbx-tools/shared-model": "^0.9.121",
|
|
36
|
+
"@dbx-tools/ui": "^0.9.121",
|
|
37
37
|
"@mastra/client-js": "1.50.0",
|
|
38
38
|
"@mastra/core": "1.71.0",
|
|
39
39
|
"@tanstack/react-table": "^8.21.3",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
-
"version": "0.9.
|
|
53
|
+
"version": "0.9.121",
|
|
54
54
|
"dbxToolsConfig": {
|
|
55
55
|
"tags": [
|
|
56
56
|
"ui"
|
package/src/react/bubbles.tsx
CHANGED
|
@@ -340,6 +340,7 @@ type AssistantBubbleProps = {
|
|
|
340
340
|
mlflowExperimentUrl?: string;
|
|
341
341
|
};
|
|
342
342
|
|
|
343
|
+
/** Render one assistant message with tool progress, actions, and optional feedback. */
|
|
343
344
|
export const AssistantBubble = ({
|
|
344
345
|
message,
|
|
345
346
|
isLast,
|
|
@@ -523,6 +524,7 @@ export const AssistantBubble = ({
|
|
|
523
524
|
);
|
|
524
525
|
};
|
|
525
526
|
|
|
527
|
+
/** Render one user message, including text and image attachments. */
|
|
526
528
|
export const UserBubble = ({ message }: { message: UIMessage }) => {
|
|
527
529
|
const text = message.parts
|
|
528
530
|
.filter((p): p is { type: "text"; text: string } => p.type === "text")
|
|
@@ -423,7 +423,7 @@ export const ChatComposer = ({
|
|
|
423
423
|
}}
|
|
424
424
|
placeholder="Send a message..."
|
|
425
425
|
rows={1}
|
|
426
|
-
className="field-sizing-fixed min-h-10 max-h-64 w-full flex-none overflow-y-auto px-4 pb-2 pt-4 text-
|
|
426
|
+
className="field-sizing-fixed min-h-10 max-h-64 w-full flex-none overflow-y-auto px-4 pb-2 pt-4 text-sm"
|
|
427
427
|
/>
|
|
428
428
|
{fileError && (
|
|
429
429
|
<div className="px-4 text-xs text-destructive" role="alert">
|
|
@@ -116,7 +116,7 @@ export function useChatHistory({
|
|
|
116
116
|
.catch((error: unknown) => {
|
|
117
117
|
if ((error as { name?: string }).name === "AbortError") throw error;
|
|
118
118
|
logger.warn("suspended-run discovery error", {
|
|
119
|
-
error: errorUtils.
|
|
119
|
+
error: errorUtils.toError(error),
|
|
120
120
|
});
|
|
121
121
|
return { runs: [], total: 0 };
|
|
122
122
|
});
|
|
@@ -140,7 +140,7 @@ export function useChatHistory({
|
|
|
140
140
|
.catch((error: unknown) => {
|
|
141
141
|
if (cancelled || (error as { name?: string }).name === "AbortError") return;
|
|
142
142
|
logger.error("history load error", {
|
|
143
|
-
error: errorUtils.
|
|
143
|
+
error: errorUtils.toError(error),
|
|
144
144
|
});
|
|
145
145
|
updateSession(threadId, (current) => ({
|
|
146
146
|
...current,
|
|
@@ -181,7 +181,7 @@ export function useChatHistory({
|
|
|
181
181
|
.catch((error: unknown) => {
|
|
182
182
|
logger.error("history load-more error", {
|
|
183
183
|
page,
|
|
184
|
-
error: errorUtils.
|
|
184
|
+
error: errorUtils.toError(error),
|
|
185
185
|
});
|
|
186
186
|
updateSession(threadId, (current) => ({
|
|
187
187
|
...current,
|
|
@@ -8,13 +8,16 @@ import {
|
|
|
8
8
|
type ThreadSession,
|
|
9
9
|
} from "../support/thread-sessions.ts";
|
|
10
10
|
|
|
11
|
+
/** Read or lazily create the mutable session state for one thread. */
|
|
11
12
|
export type ThreadSessionReader = (threadId: string) => ThreadSession;
|
|
12
13
|
|
|
14
|
+
/** Replace one thread session through a state-producing callback. */
|
|
13
15
|
export type ThreadSessionUpdater = (
|
|
14
16
|
threadId: string,
|
|
15
17
|
updater: (session: ThreadSession) => ThreadSession,
|
|
16
18
|
) => void;
|
|
17
19
|
|
|
20
|
+
/** Replace the transcript stored for one thread. */
|
|
18
21
|
export type ThreadMessageWriter = (threadId: string, messages: UIMessage[]) => void;
|
|
19
22
|
|
|
20
23
|
/** Own the mutable per-thread session registry behind the public chat hook. */
|
package/src/react/chat-stream.ts
CHANGED
|
@@ -127,7 +127,7 @@ export function useChatStream({ getSession, updateSession, writeMessages }: UseC
|
|
|
127
127
|
if (error instanceof StreamAborted || signal.aborted) return;
|
|
128
128
|
if (isStaleMastraResumeError(error)) {
|
|
129
129
|
logger.warn("ignored stale mastra resume", {
|
|
130
|
-
error: errorUtils.
|
|
130
|
+
error: errorUtils.toError(error),
|
|
131
131
|
});
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
@@ -113,7 +113,7 @@ export const ChatThreadLayout = ({
|
|
|
113
113
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
114
114
|
const isNarrow = useIsNarrow(rootRef);
|
|
115
115
|
const showThreads = Boolean(threads && onSelectThread) && threadPlacement !== "disabled";
|
|
116
|
-
const placement = threadPlacement === "auto" ? (isNarrow ? "top" : "
|
|
116
|
+
const placement = threadPlacement === "auto" ? (isNarrow ? "top" : "left") : threadPlacement;
|
|
117
117
|
const tabbedThreads = showThreads && placement === "top";
|
|
118
118
|
const dockedSide = placement === "right" ? "right" : "left";
|
|
119
119
|
const dockedThreads = showThreads && (placement === "left" || placement === "right");
|
package/src/react/data-grid.tsx
CHANGED
|
@@ -50,6 +50,7 @@ export type DataRow = Record<string, unknown>;
|
|
|
50
50
|
*/
|
|
51
51
|
const DELTA_PATTERN = /^([+\u2212-])\s*\d[\d,.\s]*(?:%|\s*pts?)?$/i;
|
|
52
52
|
|
|
53
|
+
/** Apply success or destructive text color to a signed numeric delta string. */
|
|
53
54
|
export function colorizeDelta(content: React.ReactNode): React.ReactNode {
|
|
54
55
|
if (typeof content !== "string") return content;
|
|
55
56
|
const text = content.trim();
|
|
@@ -23,6 +23,7 @@ import type { FeedbackSubmission, FeedbackValue } from "./types.ts";
|
|
|
23
23
|
// wires feedback (which only happens when MLflow logging is enabled and
|
|
24
24
|
// the turn has a captured trace id).
|
|
25
25
|
|
|
26
|
+
/** Render per-message rating and comment controls for an MLflow-backed trace. */
|
|
26
27
|
export const FeedbackControls = ({
|
|
27
28
|
value,
|
|
28
29
|
onSubmit,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
useMastraModels,
|
|
28
28
|
useMastraSuggestions,
|
|
29
29
|
useMastraThreads,
|
|
30
|
+
MastraChatRequestError,
|
|
30
31
|
type MastraMemoryThread,
|
|
31
32
|
type MastraStreamResponse,
|
|
32
33
|
} from "../support/mastra-client.ts";
|
|
@@ -479,6 +480,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
479
480
|
if (
|
|
480
481
|
controller.signal.aborted ||
|
|
481
482
|
getSession(threadId).runToken !== token ||
|
|
483
|
+
initialError instanceof MastraChatRequestError ||
|
|
482
484
|
!mastraClient.backgroundTurns ||
|
|
483
485
|
!runId
|
|
484
486
|
) {
|
|
@@ -486,7 +488,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
486
488
|
}
|
|
487
489
|
logger.warn("chat stream disconnected; reconnecting to background run", {
|
|
488
490
|
runId,
|
|
489
|
-
error: errorUtils.
|
|
491
|
+
error: errorUtils.toError(initialError),
|
|
490
492
|
});
|
|
491
493
|
const messagesBeforeReplay = getSession(threadId).messages;
|
|
492
494
|
writeMessages(
|
|
@@ -528,7 +530,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
528
530
|
if (getSession(threadId).runToken !== token) return;
|
|
529
531
|
if (isStaleMastraResumeError(caught)) {
|
|
530
532
|
logger.warn("ignored stale mastra resume", {
|
|
531
|
-
error: errorUtils.
|
|
533
|
+
error: errorUtils.toError(caught),
|
|
532
534
|
});
|
|
533
535
|
updateSession(threadId, (session) => {
|
|
534
536
|
if (session.runToken !== token) return session;
|
|
@@ -548,7 +550,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
548
550
|
return;
|
|
549
551
|
}
|
|
550
552
|
logger.error("stream error", {
|
|
551
|
-
error: errorUtils.
|
|
553
|
+
error: errorUtils.toError(caught),
|
|
552
554
|
});
|
|
553
555
|
updateSession(threadId, (session) => ({
|
|
554
556
|
...session,
|
|
@@ -557,6 +559,8 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
557
559
|
abortController: session.abortController === controller ? null : session.abortController,
|
|
558
560
|
runId: runIdRef.current,
|
|
559
561
|
}));
|
|
562
|
+
const failedRunId = runIdRef.current;
|
|
563
|
+
if (failedRunId) removeStoredActiveRun(activeRunsKey, failedRunId);
|
|
560
564
|
}
|
|
561
565
|
},
|
|
562
566
|
[
|
|
@@ -699,7 +703,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
699
703
|
.catch((error: unknown) => {
|
|
700
704
|
logger.warn("failed to abort background run", {
|
|
701
705
|
runId: current.runId,
|
|
702
|
-
error: errorUtils.
|
|
706
|
+
error: errorUtils.toError(error),
|
|
703
707
|
});
|
|
704
708
|
});
|
|
705
709
|
}
|
|
@@ -841,7 +845,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
841
845
|
logger.info("history cleared", { threadId });
|
|
842
846
|
} catch (error) {
|
|
843
847
|
logger.error("history clear error", {
|
|
844
|
-
error: errorUtils.
|
|
848
|
+
error: errorUtils.toError(error),
|
|
845
849
|
});
|
|
846
850
|
}
|
|
847
851
|
resetSession(threadId, true);
|
|
@@ -882,7 +886,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
882
886
|
} catch (error) {
|
|
883
887
|
logger.error("thread delete error", {
|
|
884
888
|
threadId,
|
|
885
|
-
error: errorUtils.
|
|
889
|
+
error: errorUtils.toError(error),
|
|
886
890
|
});
|
|
887
891
|
}
|
|
888
892
|
removeSession(threadId);
|
|
@@ -927,7 +931,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
927
931
|
} catch (error) {
|
|
928
932
|
logger.error("thread rename error", {
|
|
929
933
|
threadId,
|
|
930
|
-
error: errorUtils.
|
|
934
|
+
error: errorUtils.toError(error),
|
|
931
935
|
});
|
|
932
936
|
setRenamedThreads((prev) => {
|
|
933
937
|
if (!(threadId in prev)) return prev;
|
|
@@ -970,7 +974,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
970
974
|
.catch((error: unknown) => {
|
|
971
975
|
logger.error("regenerate cleanup error", {
|
|
972
976
|
threadId,
|
|
973
|
-
error: errorUtils.
|
|
977
|
+
error: errorUtils.toError(error),
|
|
974
978
|
});
|
|
975
979
|
updateSession(threadId, (session) => ({
|
|
976
980
|
...session,
|
|
@@ -1040,7 +1044,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
1040
1044
|
} catch (error) {
|
|
1041
1045
|
logger.error("conversation export error", {
|
|
1042
1046
|
format,
|
|
1043
|
-
error: errorUtils.
|
|
1047
|
+
error: errorUtils.toError(error),
|
|
1044
1048
|
});
|
|
1045
1049
|
}
|
|
1046
1050
|
},
|
|
@@ -1062,7 +1066,7 @@ export const useMastraChat = <TValues extends Record<string, unknown> = Record<s
|
|
|
1062
1066
|
} catch (error) {
|
|
1063
1067
|
logger.error("message export error", {
|
|
1064
1068
|
format,
|
|
1065
|
-
error: errorUtils.
|
|
1069
|
+
error: errorUtils.toError(error),
|
|
1066
1070
|
});
|
|
1067
1071
|
}
|
|
1068
1072
|
},
|
|
@@ -5,6 +5,7 @@ import { Button, cn } from "@dbx-tools/ui/react";
|
|
|
5
5
|
// the per-message follow-up suggestions use this so the two look and
|
|
6
6
|
// behave identically.
|
|
7
7
|
|
|
8
|
+
/** Props for the shared starter and follow-up question pill row. */
|
|
8
9
|
export interface SuggestionPillsProps {
|
|
9
10
|
/** Questions to render as clickable pills. Empty renders nothing. */
|
|
10
11
|
questions: string[];
|
package/src/react/tool-pill.tsx
CHANGED
|
@@ -424,6 +424,7 @@ const RawToolPayload = ({
|
|
|
424
424
|
);
|
|
425
425
|
};
|
|
426
426
|
|
|
427
|
+
/** Compact source-code preview extracted from a tool request payload. */
|
|
427
428
|
export type ToolInputPresentation = {
|
|
428
429
|
label: "Code" | "Command" | "Output";
|
|
429
430
|
language: "typescript" | "javascript" | "python" | "sql" | "json" | "bash" | "text";
|
|
@@ -511,6 +512,7 @@ const ToolInputSource = ({ presentation }: { presentation: ToolInputPresentation
|
|
|
511
512
|
|
|
512
513
|
type ToolStatusProgress = Extract<ToolProgress, { type: "tool_status" }>;
|
|
513
514
|
|
|
515
|
+
/** One native web-search request and the result progress events associated with it. */
|
|
514
516
|
export type WebSearchProgressGroup = {
|
|
515
517
|
key: string;
|
|
516
518
|
search?: ToolStatusProgress;
|
package/src/support/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type { StoredActiveRun } from "./active-runs.ts";
|
|
|
20
20
|
export { LIGHT_CHART_CHROME } from "./chart-theme.ts";
|
|
21
21
|
export type { ChartChrome } from "./chart-theme.ts";
|
|
22
22
|
export type { ExportFormat, ExportBrand, EmbedResolver, ExportChatOptions } from "./export.ts";
|
|
23
|
-
export { MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch } from "./mastra-client.ts";
|
|
23
|
+
export { MastraChatRequestError, MastraPluginClient, useMastraConfig, useMastraClient, useMastraMlflowExperiment, useMastraModels, useMastraDefaultModel, useMastraSuggestions, useMastraThreads, useChartFetch, useStatementFetch } from "./mastra-client.ts";
|
|
24
24
|
export type { MastraStreamResponse, MastraMemoryThread, ByIdFetchState } from "./mastra-client.ts";
|
|
25
25
|
export { defaultReasoningEffort, modelStorageKey, readStoredModel, storeSelectedModel } from "./model-selection.ts";
|
|
26
26
|
export type { MastraRequestContextInput, MastraRequestContextSource, MastraRequestContextSnapshot } from "./request-context.ts";
|
|
@@ -33,6 +33,17 @@ export interface MastraStreamResponse {
|
|
|
33
33
|
stream: ReadableStream<UIMessageChunk>;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** Terminal HTTP failure returned before a chat stream was established. */
|
|
37
|
+
export class MastraChatRequestError extends Error {
|
|
38
|
+
constructor(
|
|
39
|
+
message: string,
|
|
40
|
+
readonly status: number,
|
|
41
|
+
) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "MastraChatRequestError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
36
47
|
/** One memory thread returned by the native Mastra client. */
|
|
37
48
|
export type MastraMemoryThread = ListMemoryThreadsResponse["threads"][number];
|
|
38
49
|
|
|
@@ -634,7 +645,10 @@ async function assertChatResponse(response: Response): Promise<void> {
|
|
|
634
645
|
.clone()
|
|
635
646
|
.text()
|
|
636
647
|
.catch(() => ""));
|
|
637
|
-
throw new
|
|
648
|
+
throw new MastraChatRequestError(
|
|
649
|
+
message.trim() || `Chat request failed (${response.status})`,
|
|
650
|
+
response.status,
|
|
651
|
+
);
|
|
638
652
|
}
|
|
639
653
|
|
|
640
654
|
function responseErrorMessage(body: unknown): string | undefined {
|
|
@@ -42,6 +42,7 @@ export type ThreadSession = {
|
|
|
42
42
|
/** Map key for the classic single-thread chat (no explicit thread id). */
|
|
43
43
|
export const DEFAULT_THREAD_SESSION_KEY = "__session__";
|
|
44
44
|
|
|
45
|
+
/** Create the empty transcript and run state used for a new conversation thread. */
|
|
45
46
|
export function createThreadSession(): ThreadSession {
|
|
46
47
|
return {
|
|
47
48
|
messages: [],
|
|
@@ -61,6 +62,7 @@ export function createThreadSession(): ThreadSession {
|
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
/** Return whether a thread has a submitted or actively streaming run. */
|
|
64
66
|
export function isSessionRunning(session: ThreadSession): boolean {
|
|
65
67
|
return session.status === "submitted" || session.status === "streaming";
|
|
66
68
|
}
|
|
@@ -98,6 +100,7 @@ export function reorderSteers<T extends QueuedSteer>(queue: T[], orderedIds: str
|
|
|
98
100
|
return next;
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
/** Resolve an explicit thread id or the shared key used by single-thread chat. */
|
|
101
104
|
export function sessionKey(activeThreadId: string | undefined): string {
|
|
102
105
|
return activeThreadId ?? DEFAULT_THREAD_SESSION_KEY;
|
|
103
106
|
}
|