@dbx-tools/ui-mastra 0.9.175 → 0.9.177
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/index.react.ts +2 -1
- package/index.ts +1 -1
- package/package.json +7 -7
- package/src/react/_assistant-response-status.tsx +2 -2
- package/src/react/bubbles.tsx +9 -8
- package/src/react/chat-composer.tsx +4 -3
- package/src/react/chat-stream.ts +25 -3
- package/src/react/chat-transcript.tsx +2 -2
- package/src/react/chat-view.tsx +2 -2
- package/src/react/types.ts +9 -1
- package/src/support/thread-sessions.ts +9 -3
package/index.react.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type { GenieFeedbackTarget } from "./src/react/chat-feedback.ts";
|
|
|
33
33
|
export { useChatHistory } from "./src/react/chat-history.ts";
|
|
34
34
|
export { useChatSessions } from "./src/react/chat-sessions.ts";
|
|
35
35
|
export type { ThreadSessionReader, ThreadSessionUpdater, ThreadMessageWriter } from "./src/react/chat-sessions.ts";
|
|
36
|
-
export { readMlflowTracePart, closeOnTerminalChunk, waitForTerminalChunk, useChatStream } from "./src/react/chat-stream.ts";
|
|
36
|
+
export { readMlflowTracePart, chatStatusForChunk, closeOnTerminalChunk, waitForTerminalChunk, useChatStream } from "./src/react/chat-stream.ts";
|
|
37
37
|
export { ChatThreadLayout } from "./src/react/chat-thread-layout.tsx";
|
|
38
38
|
export { useChatTranscriptController, ChatTranscript } from "./src/react/chat-transcript.tsx";
|
|
39
39
|
export type { ChatTranscriptController } from "./src/react/chat-transcript.tsx";
|
|
@@ -57,5 +57,6 @@ export { ThreadActions, ThreadTabs } from "./src/react/thread-tabs.tsx";
|
|
|
57
57
|
export type { ThreadTabsProps, ThreadActionsProps } from "./src/react/thread-tabs.tsx";
|
|
58
58
|
export { humanizeToolName, formatRawToolPayload, structuredToolPayload, detectToolSourceLanguage, toolInputPresentation, toolOutputPresentation, webSearchProgressGroups, webSearchQueryLabel, webSearchResultLabel, ToolSessionPill } from "./src/react/tool-pill.tsx";
|
|
59
59
|
export type { ToolInputPresentation, WebSearchProgressGroup } from "./src/react/tool-pill.tsx";
|
|
60
|
+
export { isActiveChatStatus, isRespondingChatStatus } from "./src/react/types.ts";
|
|
60
61
|
export type { ChatStatus, ToolEvent, ToolProgress, ChatModelOption, ChatInputMessage, QueuedSteer, FeedbackValue, FeedbackSubmission, MessageFeedback, ThreadSummary, ThreadPlacement, ChatViewProps, ApprovalDecision, PendingApproval } from "./src/react/types.ts";
|
|
61
62
|
export { useChatThreadQuery } from "./src/react/use-chat-thread-query.ts";
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@databricks/appkit-ui": "0.81.0",
|
|
35
|
-
"@dbx-tools/shared-auth": "^0.9.
|
|
36
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
37
|
-
"@dbx-tools/shared-genie": "^0.9.
|
|
38
|
-
"@dbx-tools/shared-mastra": "^0.9.
|
|
39
|
-
"@dbx-tools/shared-model": "^0.9.
|
|
40
|
-
"@dbx-tools/ui": "^0.9.
|
|
35
|
+
"@dbx-tools/shared-auth": "^0.9.177",
|
|
36
|
+
"@dbx-tools/shared-core": "^0.9.177",
|
|
37
|
+
"@dbx-tools/shared-genie": "^0.9.177",
|
|
38
|
+
"@dbx-tools/shared-mastra": "^0.9.177",
|
|
39
|
+
"@dbx-tools/shared-model": "^0.9.177",
|
|
40
|
+
"@dbx-tools/ui": "^0.9.177",
|
|
41
41
|
"@mastra/client-js": "1.50.0",
|
|
42
42
|
"@mastra/core": "1.71.0",
|
|
43
43
|
"@tanstack/react-table": "^8.21.3",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
|
-
"version": "0.9.
|
|
58
|
+
"version": "0.9.177",
|
|
59
59
|
"types": "index.ts",
|
|
60
60
|
"dbxToolsConfig": {
|
|
61
61
|
"tags": [
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Spinner } from "@databricks/appkit-ui/react";
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import { isRespondingChatStatus, type ChatStatus } from "./types.ts";
|
|
4
4
|
|
|
5
5
|
/** Whether an assistant bubble should show its active-response status. */
|
|
6
6
|
export const shouldShowAssistantResponseStatus = (
|
|
7
7
|
isLast: boolean,
|
|
8
8
|
status: ChatStatus,
|
|
9
9
|
hasVisibleResponse: boolean,
|
|
10
|
-
): boolean => isLast && hasVisibleResponse && (status
|
|
10
|
+
): boolean => isLast && hasVisibleResponse && isRespondingChatStatus(status);
|
|
11
11
|
|
|
12
12
|
/** Compact progress affordance for an active assistant response. */
|
|
13
13
|
export const AssistantResponseSpinner = () => (
|
package/src/react/bubbles.tsx
CHANGED
|
@@ -36,13 +36,14 @@ import { ExportMenu } from "./export-menu.tsx";
|
|
|
36
36
|
import { FeedbackControls } from "./feedback-controls.tsx";
|
|
37
37
|
import { ToolMarkdown } from "./markdown.tsx";
|
|
38
38
|
import { ToolSessionPill, humanizeToolName } from "./tool-pill.tsx";
|
|
39
|
-
import
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
import {
|
|
40
|
+
isRespondingChatStatus,
|
|
41
|
+
type ApprovalDecision,
|
|
42
|
+
type ChatStatus,
|
|
43
|
+
type FeedbackSubmission,
|
|
44
|
+
type FeedbackValue,
|
|
45
|
+
type PendingApproval,
|
|
46
|
+
type ToolEvent,
|
|
46
47
|
} from "./types.ts";
|
|
47
48
|
import { copyText } from "../support/clipboard.ts";
|
|
48
49
|
import type { ExportFormat } from "../support/export.ts";
|
|
@@ -390,7 +391,7 @@ export const AssistantBubble = ({
|
|
|
390
391
|
// pop in mid-stream. A bubble is "settled" if it isn't the active
|
|
391
392
|
// streaming target - either the agent has returned to `ready` /
|
|
392
393
|
// `error`, or a newer message has taken over the `isLast` slot.
|
|
393
|
-
const isStreamingThisBubble = isLast && (status
|
|
394
|
+
const isStreamingThisBubble = isLast && isRespondingChatStatus(status);
|
|
394
395
|
const showResponseStatus = shouldShowAssistantResponseStatus(
|
|
395
396
|
isLast,
|
|
396
397
|
status,
|
|
@@ -34,7 +34,7 @@ import { imageFileToUIPart, MAX_COMPOSER_IMAGES } from "./_image-attachments.ts"
|
|
|
34
34
|
import { ModelSelector } from "./_model-selector.tsx";
|
|
35
35
|
import { ExportMenu } from "./export-menu.tsx";
|
|
36
36
|
import { SuggestionPills } from "./suggestion-pills.tsx";
|
|
37
|
-
import type
|
|
37
|
+
import { isActiveChatStatus, isRespondingChatStatus, type ChatViewProps } from "./types.ts";
|
|
38
38
|
|
|
39
39
|
type QueuedSteerListProps = {
|
|
40
40
|
queuedSteers: NonNullable<ChatViewProps["queuedSteers"]>;
|
|
@@ -316,7 +316,8 @@ export const ChatComposer = ({
|
|
|
316
316
|
return observeComposerWidth(group, resizeTextarea);
|
|
317
317
|
}, [resizeTextarea]);
|
|
318
318
|
|
|
319
|
-
const isRunning = status
|
|
319
|
+
const isRunning = isActiveChatStatus(status);
|
|
320
|
+
const canStop = isRespondingChatStatus(status);
|
|
320
321
|
const hasDraft = Boolean(input.trim() || files.length > 0);
|
|
321
322
|
const submit = () => {
|
|
322
323
|
const text = input.trim();
|
|
@@ -560,7 +561,7 @@ export const ChatComposer = ({
|
|
|
560
561
|
)}
|
|
561
562
|
</span>
|
|
562
563
|
))}
|
|
563
|
-
{
|
|
564
|
+
{canStop && onStop && !hasDraft ? (
|
|
564
565
|
<InputGroupButton
|
|
565
566
|
type="button"
|
|
566
567
|
size="icon-sm"
|
package/src/react/chat-stream.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
MLFLOW_TRACE_ID_HEADER,
|
|
4
4
|
MLFLOW_TRACE_PART_TYPE,
|
|
5
5
|
MlflowTracePartDataSchema,
|
|
6
|
+
RESPONSE_COMPLETE_PART_TYPE,
|
|
6
7
|
isStaleMastraResumeError,
|
|
7
8
|
} from "@dbx-tools/shared-mastra";
|
|
8
9
|
import { readUIMessageStream, type UIMessage, type UIMessageChunk } from "ai";
|
|
@@ -12,6 +13,7 @@ import type {
|
|
|
12
13
|
ThreadSessionReader,
|
|
13
14
|
ThreadSessionUpdater,
|
|
14
15
|
} from "./chat-sessions.ts";
|
|
16
|
+
import type { ChatStatus } from "./types.ts";
|
|
15
17
|
import type { MastraStreamResponse } from "../support/mastra-client.ts";
|
|
16
18
|
|
|
17
19
|
const logger = log.logger("ui-mastra/chat");
|
|
@@ -29,6 +31,13 @@ export const readMlflowTracePart = (chunk: UIMessageChunk): string | undefined =
|
|
|
29
31
|
return parsed.success ? parsed.data.traceId : undefined;
|
|
30
32
|
};
|
|
31
33
|
|
|
34
|
+
/** Map lifecycle-only chunks onto the UI's active-turn state. */
|
|
35
|
+
export const chatStatusForChunk = (chunk: UIMessageChunk): ChatStatus | undefined => {
|
|
36
|
+
if ((chunk as { type?: string }).type === RESPONSE_COMPLETE_PART_TYPE) return "finishing";
|
|
37
|
+
if (chunk.type === "finish" || chunk.type === "abort") return "ready";
|
|
38
|
+
return undefined;
|
|
39
|
+
};
|
|
40
|
+
|
|
32
41
|
class StreamAborted extends Error {}
|
|
33
42
|
|
|
34
43
|
/** Stop reading a background run once the AI SDK has delivered its terminal chunk. */
|
|
@@ -46,7 +55,7 @@ export function closeOnTerminalChunk(
|
|
|
46
55
|
while (true) {
|
|
47
56
|
const { done, value } = await reader.read();
|
|
48
57
|
if (done) {
|
|
49
|
-
controller.
|
|
58
|
+
controller.error(new Error("Chat stream ended before a terminal AI SDK chunk"));
|
|
50
59
|
return;
|
|
51
60
|
}
|
|
52
61
|
onChunk?.(value);
|
|
@@ -140,7 +149,15 @@ export function useChatStream({ getSession, updateSession, writeMessages }: UseC
|
|
|
140
149
|
() => {
|
|
141
150
|
terminalReceived = true;
|
|
142
151
|
},
|
|
143
|
-
(chunk) =>
|
|
152
|
+
(chunk) => {
|
|
153
|
+
recordTraceId(readMlflowTracePart(chunk));
|
|
154
|
+
const status = chatStatusForChunk(chunk);
|
|
155
|
+
if (!status) return;
|
|
156
|
+
updateSession(threadId, (current) => ({
|
|
157
|
+
...current,
|
|
158
|
+
status,
|
|
159
|
+
}));
|
|
160
|
+
},
|
|
144
161
|
),
|
|
145
162
|
terminateOnError: true,
|
|
146
163
|
})) {
|
|
@@ -150,7 +167,12 @@ export function useChatStream({ getSession, updateSession, writeMessages }: UseC
|
|
|
150
167
|
updateSession(threadId, (current) => ({
|
|
151
168
|
...current,
|
|
152
169
|
runId: runIdRef.current,
|
|
153
|
-
status:
|
|
170
|
+
status:
|
|
171
|
+
terminalReceived || current.status === "finishing"
|
|
172
|
+
? terminalReceived
|
|
173
|
+
? "ready"
|
|
174
|
+
: "finishing"
|
|
175
|
+
: "streaming",
|
|
154
176
|
}));
|
|
155
177
|
}
|
|
156
178
|
} catch (error) {
|
|
@@ -17,7 +17,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from
|
|
|
17
17
|
import { AssistantBubble, UserBubble } from "./bubbles.tsx";
|
|
18
18
|
import { genieFeedbackTarget } from "./chat-feedback.ts";
|
|
19
19
|
import { SuggestionPills } from "./suggestion-pills.tsx";
|
|
20
|
-
import type
|
|
20
|
+
import { isRespondingChatStatus, type ChatViewProps } from "./types.ts";
|
|
21
21
|
import { messageText } from "../support/export.ts";
|
|
22
22
|
|
|
23
23
|
const BOTTOM_THRESHOLD_PX = 24;
|
|
@@ -186,7 +186,7 @@ export const ChatTranscript = ({
|
|
|
186
186
|
onFeedback,
|
|
187
187
|
mlflowExperimentUrl,
|
|
188
188
|
}: ChatTranscriptProps) => {
|
|
189
|
-
const isRunning = status
|
|
189
|
+
const isRunning = isRespondingChatStatus(status);
|
|
190
190
|
const lastMessage = messages.at(-1);
|
|
191
191
|
const lastEvents = lastMessage ? toolEventsByMessage[lastMessage.id] : undefined;
|
|
192
192
|
const lastAssistantParts = lastMessage?.role === "assistant" ? lastMessage.parts : [];
|
package/src/react/chat-view.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { ChatComposer } from "./chat-composer.tsx";
|
|
|
2
2
|
import { ChatThreadLayout } from "./chat-thread-layout.tsx";
|
|
3
3
|
import { ChatTranscript, useChatTranscriptController } from "./chat-transcript.tsx";
|
|
4
4
|
import { collectSuggestions } from "./suggestions.ts";
|
|
5
|
-
import type
|
|
5
|
+
import { isActiveChatStatus, type ChatViewProps } from "./types.ts";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Controlled chat facade for hosts that own message and transport state.
|
|
@@ -81,7 +81,7 @@ export const ChatView = ({
|
|
|
81
81
|
});
|
|
82
82
|
const latestMessage = messages[messages.length - 1];
|
|
83
83
|
const latestAssistant = latestMessage?.role === "assistant" ? latestMessage : undefined;
|
|
84
|
-
const running = status
|
|
84
|
+
const running = isActiveChatStatus(status);
|
|
85
85
|
const followUpQuestions =
|
|
86
86
|
latestAssistant && !running
|
|
87
87
|
? collectSuggestions(
|
package/src/react/types.ts
CHANGED
|
@@ -10,7 +10,15 @@ import type { ExportFormat } from "../support/export.ts";
|
|
|
10
10
|
// layer and the `useMastraChat` driver can share them.
|
|
11
11
|
|
|
12
12
|
/** User-visible lifecycle state of the active chat turn. */
|
|
13
|
-
export type ChatStatus = "submitted" | "streaming" | "ready" | "error";
|
|
13
|
+
export type ChatStatus = "submitted" | "streaming" | "finishing" | "ready" | "error";
|
|
14
|
+
|
|
15
|
+
/** Whether a turn still owns its session and queues new messages. */
|
|
16
|
+
export const isActiveChatStatus = (status: ChatStatus): boolean =>
|
|
17
|
+
status === "submitted" || status === "streaming" || status === "finishing";
|
|
18
|
+
|
|
19
|
+
/** Whether the assistant is still visibly producing its response. */
|
|
20
|
+
export const isRespondingChatStatus = (status: ChatStatus): boolean =>
|
|
21
|
+
status === "submitted" || status === "streaming";
|
|
14
22
|
|
|
15
23
|
/**
|
|
16
24
|
* Lifecycle of a single tool invocation surfaced inline in the assistant
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { RequestContext } from "@mastra/client-js";
|
|
2
2
|
import type { UIMessage } from "ai";
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
isActiveChatStatus,
|
|
5
|
+
type ChatStatus,
|
|
6
|
+
type MessageFeedback,
|
|
7
|
+
type PendingApproval,
|
|
8
|
+
type QueuedSteer,
|
|
9
|
+
} from "../react/types.ts";
|
|
4
10
|
|
|
5
11
|
/** A queued steer plus the application context captured when it was submitted. */
|
|
6
12
|
export type SessionQueuedSteer = QueuedSteer & {
|
|
@@ -60,9 +66,9 @@ export function createThreadSession(): ThreadSession {
|
|
|
60
66
|
};
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
/** Return whether a thread
|
|
69
|
+
/** Return whether a thread still owns an active run. */
|
|
64
70
|
export function isSessionRunning(session: ThreadSession): boolean {
|
|
65
|
-
return session.status
|
|
71
|
+
return isActiveChatStatus(session.status);
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
/** Return the newest user message in a transcript or turn. */
|