@mastra/playground-ui 48.0.0-alpha.16 → 48.0.0-alpha.18
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/CHANGELOG.md +33 -0
- package/dist/components/ChatShell.cjs.js +1 -1
- package/dist/components/ChatShell.es.js +1 -1
- package/dist/components/MessageScroller.cjs.js +1 -1
- package/dist/components/MessageScroller.es.js +1 -1
- package/dist/components/ThreadRail.cjs.js +4 -3
- package/dist/components/ThreadRail.cjs.js.map +1 -1
- package/dist/components/ThreadRail.es.js +4 -4
- package/dist/components/ThreadRail.es.js.map +1 -1
- package/dist/{message-scroller-BmzjZZNs.cjs → message-scroller-BssU0EKT.cjs} +89 -16
- package/dist/message-scroller-BssU0EKT.cjs.map +1 -0
- package/dist/{message-scroller-D5O7sUS5.js → message-scroller-DlVS0FW7.js} +89 -16
- package/dist/message-scroller-DlVS0FW7.js.map +1 -0
- package/dist/src/ds/components/ThreadRail/thread-rail-turns.d.ts +2 -0
- package/dist/style.css +4 -0
- package/package.json +7 -7
- package/dist/message-scroller-BmzjZZNs.cjs.map +0 -1
- package/dist/message-scroller-D5O7sUS5.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @mastra/playground-ui
|
|
2
2
|
|
|
3
|
+
## 48.0.0-alpha.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed saved chat transcripts to open at the latest turn after asynchronously loaded history finishes layout. ([#21301](https://github.com/mastra-ai/mastra/pull/21301))
|
|
8
|
+
|
|
9
|
+
## 48.0.0-alpha.17
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Added anchored turn positioning to `MessageScroller`. Newly added rows marked with `scrollAnchor` move toward the top of the viewport, while `defaultScrollPosition="last-anchor"` opens saved transcripts at their latest turn. ([#21283](https://github.com/mastra-ai/mastra/pull/21283))
|
|
14
|
+
|
|
15
|
+
Streaming replies can now grow beneath the current prompt without shifting the reading position. Completed replies retain that space until the next anchored turn arrives.
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<MessageScrollerProvider defaultScrollPosition="last-anchor">
|
|
19
|
+
<MessageScrollerViewport>
|
|
20
|
+
<MessageScrollerContent>
|
|
21
|
+
<MessageScrollerItem messageId="turn-1" scrollAnchor>
|
|
22
|
+
<p>How do I deploy this workflow?</p>
|
|
23
|
+
</MessageScrollerItem>
|
|
24
|
+
</MessageScrollerContent>
|
|
25
|
+
</MessageScrollerViewport>
|
|
26
|
+
</MessageScrollerProvider>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- Updated dependencies [[`296dc9a`](https://github.com/mastra-ai/mastra/commit/296dc9af29f3616e786c7825ec32e0df92d754c5), [`4a09a9c`](https://github.com/mastra-ai/mastra/commit/4a09a9c0474ef643558fcb5f0edc542b82f1cab0), [`1e83a47`](https://github.com/mastra-ai/mastra/commit/1e83a4734ab61ba5926af6793e3569a78b72ed37), [`ff28284`](https://github.com/mastra-ai/mastra/commit/ff2828416f14daff9d956e6a352fdaa23c950979), [`1670533`](https://github.com/mastra-ai/mastra/commit/1670533986f6bacf567746245348125e3a106448)]:
|
|
32
|
+
- @mastra/core@1.58.0-alpha.16
|
|
33
|
+
- @mastra/client-js@1.39.0-alpha.16
|
|
34
|
+
- @mastra/react@1.4.2-alpha.16
|
|
35
|
+
|
|
3
36
|
## 48.0.0-alpha.16
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
5
|
const jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
const messageScroller = require('../message-scroller-
|
|
6
|
+
const messageScroller = require('../message-scroller-BssU0EKT.cjs');
|
|
7
7
|
const utils_cn = require('../cn-vA5sWo9W.cjs');
|
|
8
8
|
|
|
9
9
|
function ChatShellRoot({ className, scroller, ...props }) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { d as MessageScrollerProvider, e as MessageScrollerViewport, M as MessageScroller, a as MessageScrollerButton, b as MessageScrollerContent } from '../message-scroller-
|
|
2
|
+
import { d as MessageScrollerProvider, e as MessageScrollerViewport, M as MessageScroller, a as MessageScrollerButton, b as MessageScrollerContent } from '../message-scroller-DlVS0FW7.js';
|
|
3
3
|
import { c as cn } from '../cn-BakJzhuv.js';
|
|
4
4
|
|
|
5
5
|
function ChatShellRoot({ className, scroller, ...props }) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
|
-
const messageScroller = require('../message-scroller-
|
|
5
|
+
const messageScroller = require('../message-scroller-BssU0EKT.cjs');
|
|
6
6
|
const messageScrollerHooks = require('../message-scroller-hooks-BxAf8k0Y.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { M as MessageScroller, a as MessageScrollerButton, b as MessageScrollerContent, c as MessageScrollerItem, d as MessageScrollerProvider, e as MessageScrollerViewport } from '../message-scroller-
|
|
1
|
+
export { M as MessageScroller, a as MessageScrollerButton, b as MessageScrollerContent, c as MessageScrollerItem, d as MessageScrollerProvider, e as MessageScrollerViewport } from '../message-scroller-DlVS0FW7.js';
|
|
2
2
|
export { u as useMessageScroller, a as useMessageScrollerScrollable, b as useMessageScrollerVisibility, c as useOptionalMessageScroller, d as useOptionalMessageScrollerScrollable, e as useOptionalMessageScrollerVisibility } from '../message-scroller-hooks-D5yxCon2.js';
|
|
3
3
|
//# sourceMappingURL=MessageScroller.es.js.map
|
|
@@ -393,7 +393,7 @@ const getSignalType = (message) => {
|
|
|
393
393
|
const metadataType = isRecord(signal) ? signal.type : void 0;
|
|
394
394
|
return typeof metadataType === "string" ? metadataType : message.type;
|
|
395
395
|
};
|
|
396
|
-
const
|
|
396
|
+
const startsUserTurn = (message) => {
|
|
397
397
|
if (message.role === "user") return true;
|
|
398
398
|
if (message.role !== "signal") return false;
|
|
399
399
|
const signalType = getSignalType(message);
|
|
@@ -403,7 +403,7 @@ const getNextAssistantReply = (messages, startIndex) => {
|
|
|
403
403
|
for (let index = startIndex + 1; index < messages.length; index += 1) {
|
|
404
404
|
const message = messages[index];
|
|
405
405
|
if (!message) continue;
|
|
406
|
-
if (
|
|
406
|
+
if (startsUserTurn(message)) return void 0;
|
|
407
407
|
if (message.role !== "assistant") continue;
|
|
408
408
|
const reply = normalizeSummary(getTextFromParts(message), "");
|
|
409
409
|
if (reply) return reply;
|
|
@@ -411,7 +411,7 @@ const getNextAssistantReply = (messages, startIndex) => {
|
|
|
411
411
|
return void 0;
|
|
412
412
|
};
|
|
413
413
|
const buildThreadRailTurns = (messages) => messages.flatMap((message, index) => {
|
|
414
|
-
if (!
|
|
414
|
+
if (!startsUserTurn(message)) return [];
|
|
415
415
|
const files = getFileLabels(message);
|
|
416
416
|
const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);
|
|
417
417
|
return [
|
|
@@ -429,4 +429,5 @@ const buildThreadRailTurns = (messages) => messages.flatMap((message, index) =>
|
|
|
429
429
|
exports.ThreadRail = ThreadRail;
|
|
430
430
|
exports.buildThreadRailTurns = buildThreadRailTurns;
|
|
431
431
|
exports.getClientMessageKey = getClientMessageKey;
|
|
432
|
+
exports.startsUserTurn = startsUserTurn;
|
|
432
433
|
//# sourceMappingURL=ThreadRail.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadRail.cjs.js","sources":["../../src/ds/components/ThreadRail/thread-rail.tsx","../../src/ds/components/ThreadRail/thread-rail-turns.ts"],"sourcesContent":["import { FileText } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { ThreadRailTurn } from './thread-rail-turns';\n\nimport { useOptionalMessageScroller, useOptionalMessageScrollerVisibility } from '@/ds/components/MessageScroller';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { useMeasuredAutoHeight } from '@/hooks/use-measured-auto-height';\nimport { cn } from '@/lib/utils';\n\ntype ThreadRailPreviewPhase = 'hidden' | 'entering' | 'visible' | 'exiting';\n\ntype ThreadRailPreviewState = {\n currentTurn: ThreadRailTurn | undefined;\n previousTurn: ThreadRailTurn | undefined;\n index: number | null;\n phase: ThreadRailPreviewPhase;\n top: number;\n transitionKey: number;\n};\n\nconst PREVIEW_TRANSITION_DURATION_MS = 360;\nconst PREVIEW_CLEANUP_DELAY_MS = PREVIEW_TRANSITION_DURATION_MS + 80;\n\nconst DEFAULT_PREVIEW_STATE: ThreadRailPreviewState = {\n currentTurn: undefined,\n previousTurn: undefined,\n index: null,\n phase: 'hidden',\n top: 0,\n transitionKey: 0,\n};\n\nexport interface ThreadRailProps {\n turns: ThreadRailTurn[];\n currentAnchorId?: string;\n visibleMessageIds?: string[];\n label?: string;\n className?: string;\n maxHeight?: string;\n scrollAreaClassName?: string;\n onSelect?: (turn: ThreadRailTurn) => void;\n}\n\nexport function ThreadRail({\n turns,\n currentAnchorId,\n visibleMessageIds,\n label = 'Conversation timeline',\n className,\n maxHeight = 'calc(100dvh - 12rem)',\n scrollAreaClassName,\n onSelect,\n}: ThreadRailProps) {\n const railRef = React.useRef<HTMLElement>(null);\n const previewId = React.useId();\n const [previewState, setPreviewState] = React.useState<ThreadRailPreviewState>(DEFAULT_PREVIEW_STATE);\n const messageScroller = useOptionalMessageScroller();\n const scrollerVisibility = useOptionalMessageScrollerVisibility();\n\n const fallbackMessageId = turns.at(-1)?.messageId;\n const activeMessageId = currentAnchorId ?? scrollerVisibility?.currentAnchorId ?? fallbackMessageId;\n const resolvedVisibleMessageIds =\n visibleMessageIds ?? scrollerVisibility?.visibleMessageIds ?? (activeMessageId ? [activeMessageId] : []);\n const visibleMessageIdSet = new Set(resolvedVisibleMessageIds);\n const previewHoverActive = previewState.phase === 'entering' || previewState.phase === 'visible';\n const hoveredIndex = previewHoverActive ? previewState.index : null;\n const selectTurn = React.useCallback(\n (turn: ThreadRailTurn) => {\n if (onSelect) {\n onSelect(turn);\n return;\n }\n\n messageScroller?.scrollToMessage(turn.messageId, { behavior: 'smooth', align: 'start' });\n },\n [messageScroller, onSelect],\n );\n\n const showPreview = (index: number, element: HTMLElement) => {\n const railTop = railRef.current?.getBoundingClientRect().top ?? 0;\n const itemRect = element.getBoundingClientRect();\n const nextTurn = turns[index];\n if (!nextTurn) return;\n\n setPreviewState(current => {\n const nextTop = itemRect.top + itemRect.height / 2 - railTop;\n if (current.index === index && current.phase !== 'hidden' && current.phase !== 'exiting') {\n return { ...current, top: nextTop };\n }\n\n const previousTurn =\n current.currentTurn && current.currentTurn.key !== nextTurn.key && current.phase !== 'hidden'\n ? current.currentTurn\n : undefined;\n\n return {\n currentTurn: nextTurn,\n previousTurn,\n index,\n phase: 'entering',\n top: nextTop,\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n const hidePreview = () => {\n setPreviewState(current => {\n if (!current.currentTurn || current.phase === 'hidden' || current.phase === 'exiting') {\n return { ...current, index: null };\n }\n\n return {\n ...current,\n index: null,\n previousTurn: undefined,\n phase: 'exiting',\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n React.useEffect(() => {\n if (previewState.phase !== 'entering') return;\n\n const requestFrame = window.requestAnimationFrame ?? window.setTimeout;\n const cancelFrame = window.cancelAnimationFrame ?? window.clearTimeout;\n let settleFrame: number | undefined;\n const startFrame = requestFrame(() => {\n settleFrame = requestFrame(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey && current.phase === 'entering'\n ? { ...current, phase: 'visible' }\n : current,\n );\n });\n });\n\n return () => {\n cancelFrame(startFrame);\n if (settleFrame !== undefined) cancelFrame(settleFrame);\n };\n }, [previewState.phase, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'visible' || !previewState.previousTurn) return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? { ...current, previousTurn: undefined } : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.previousTurn, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'exiting') return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? DEFAULT_PREVIEW_STATE : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.transitionKey]);\n\n if (turns.length === 0) return null;\n\n return (\n <nav\n ref={railRef}\n aria-label={label}\n data-testid=\"thread-rail\"\n className={cn('relative w-8 py-2', className)}\n onMouseLeave={hidePreview}\n onBlur={event => {\n const nextFocus = event.relatedTarget;\n if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) hidePreview();\n }}\n >\n <ScrollArea\n data-testid=\"thread-rail-scroll-area\"\n maxHeight={maxHeight}\n className={cn('w-8', scrollAreaClassName)}\n viewPortClassName=\"pr-3\"\n >\n <div className=\"flex w-4 flex-col items-start gap-2 py-2\">\n {turns.map((turn, index) => {\n const distance = hoveredIndex === null ? null : Math.abs(index - hoveredIndex);\n const active = turn.messageId === activeMessageId;\n const inView = visibleMessageIdSet.has(turn.messageId);\n const previewActive = hoveredIndex === index;\n\n return (\n <ThreadRailItem\n key={turn.key}\n turn={turn}\n index={index}\n distance={distance}\n active={active}\n inView={inView}\n previewId={previewActive ? previewId : undefined}\n onHoverChange={showPreview}\n onSelect={selectTurn}\n />\n );\n })}\n </div>\n </ScrollArea>\n\n {previewState.currentTurn && (\n <ThreadRailPreview\n id={previewId}\n currentTurn={previewState.currentTurn}\n previousTurn={previewState.previousTurn}\n phase={previewState.phase}\n top={previewState.top}\n />\n )}\n </nav>\n );\n}\n\ninterface ThreadRailItemProps {\n turn: ThreadRailTurn;\n index: number;\n distance: number | null;\n active: boolean;\n inView: boolean;\n previewId?: string;\n onHoverChange: (index: number, element: HTMLElement) => void;\n onSelect: (turn: ThreadRailTurn) => void;\n}\n\n/** Width of a rail tick: widest at the hovered item, tapering to neighbours. */\nconst getRailItemWidth = (distance: number | null): string => {\n if (distance === 0) return 'w-4';\n if (distance === 1) return 'w-3';\n return 'w-2';\n};\n\n/** Background tone of a rail tick, prioritising hovered/active, then in-view, then proximity. */\nconst getRailItemTone = ({\n distance,\n active,\n inView,\n}: Pick<ThreadRailItemProps, 'distance' | 'active' | 'inView'>): string => {\n if (distance === 0 || active) return 'bg-neutral6';\n if (inView) return 'bg-neutral5';\n if (distance === 1) return 'bg-neutral4';\n return 'bg-neutral3/60';\n};\n\nfunction ThreadRailItem({\n turn,\n index,\n distance,\n active,\n inView,\n previewId,\n onHoverChange,\n onSelect,\n}: ThreadRailItemProps) {\n const size = getRailItemWidth(distance);\n const tone = getRailItemTone({ distance, active, inView });\n\n return (\n <div\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n className=\"group/thread-rail-item relative flex items-center\"\n >\n <button\n type=\"button\"\n aria-label={`Jump to ${turn.prompt}`}\n aria-current={active ? 'location' : undefined}\n aria-describedby={previewId}\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n onClick={() => onSelect(turn)}\n onMouseEnter={event => onHoverChange(index, event.currentTarget)}\n onFocus={event => onHoverChange(index, event.currentTarget)}\n className={cn(\n 'relative block h-px cursor-pointer rounded-full transition-[width,background-color] duration-normal ease-out',\n \"before:absolute before:inset-x-0 before:-inset-y-1 before:content-['']\",\n 'focus-visible:ring-2 focus-visible:ring-accent1/40 focus-visible:outline-hidden',\n size,\n tone,\n )}\n />\n </div>\n );\n}\n\nfunction ThreadRailPreview({\n id,\n currentTurn,\n previousTurn,\n phase,\n top,\n}: {\n id: string;\n currentTurn: ThreadRailTurn;\n previousTurn: ThreadRailTurn | undefined;\n phase: ThreadRailPreviewPhase;\n top: number;\n}) {\n const {\n ref: previewSizerRef,\n heightStyle: previewHeightStyle,\n measure: measurePreviewHeight,\n } = useMeasuredAutoHeight<HTMLDivElement>();\n const containerVisible = phase === 'visible' || (phase === 'entering' && Boolean(previousTurn));\n // Entering and exiting share the same off-screen resting style.\n const hiddenLayerClassName = 'scale-95 opacity-0 blur-xs';\n const visibleLayerClassName = 'scale-100 opacity-100 blur-none';\n const layerClassName =\n 'absolute inset-x-0 top-0 h-full origin-left transition-[opacity,filter,scale] duration-150 ease-in-out will-change-[opacity,filter,scale] motion-reduce:scale-100 motion-reduce:blur-none motion-reduce:transition-none';\n\n React.useLayoutEffect(() => {\n measurePreviewHeight();\n }, [currentTurn.key, phase, measurePreviewHeight]);\n\n return (\n <div\n id={id}\n data-testid=\"thread-rail-preview\"\n data-visible={containerVisible ? 'true' : undefined}\n className={cn(\n 'pointer-events-none absolute top-0 left-full z-30 ml-3 w-72 overflow-hidden rounded-xl border border-border1 bg-surface3 text-left shadow-dialog transition-[height,translate,opacity] duration-360 ease-out-custom will-change-[height,translate,opacity] motion-reduce:transition-none',\n containerVisible ? 'opacity-100' : 'opacity-0',\n )}\n style={{ ...previewHeightStyle, translate: `0 calc(${top}px - 50%)` }}\n >\n <div ref={previewSizerRef} data-testid=\"thread-rail-preview-sizer\" aria-hidden className=\"invisible\">\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n <div data-testid=\"thread-rail-preview-viewport\" className=\"absolute inset-0\">\n <div className=\"relative h-full\">\n {previousTurn && (\n <div\n key={previousTurn.key}\n data-testid=\"thread-rail-preview-previous\"\n aria-hidden\n className={cn(layerClassName, phase === 'entering' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={previousTurn} className=\"p-3.5\" />\n </div>\n )}\n <div\n key={currentTurn.key}\n data-testid=\"thread-rail-preview-current\"\n className={cn(layerClassName, phase === 'visible' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ThreadRailPreviewContent({\n turn,\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & { turn: ThreadRailTurn }) {\n return (\n <div className={className} {...props}>\n <div className=\"text-ui-md leading-ui-md text-neutral6 truncate font-medium\">{turn.prompt}</div>\n {turn.reply && <p className=\"text-ui-sm leading-ui-sm text-neutral4 mt-1.5 line-clamp-3\">{turn.reply}</p>}\n {(turn.files.length > 0 || turn.hiddenFileCount > 0) && (\n <div className=\"border-border1/60 mt-3 flex flex-wrap items-center gap-2 border-t pt-2.5\">\n {turn.files.map(file => (\n <span key={file} className=\"text-ui-sm text-neutral4 inline-flex max-w-44 items-center gap-1.5 truncate\">\n <FileText className=\"size-3.5 shrink-0 opacity-70\" aria-hidden />\n {file}\n </span>\n ))}\n {turn.hiddenFileCount > 0 && (\n <span className=\"text-ui-sm text-neutral4 font-medium\">+{turn.hiddenFileCount}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n","import type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport type { MastraDBMessageMetadata } from '@mastra/react';\n\nconst SUMMARY_MAX_LENGTH = 120;\nconst FILE_PREVIEW_LIMIT = 2;\n// Inlined, not imported: the value export sits behind a barrel this browser bundle must not pull.\nconst CLIENT_MESSAGE_ID_KEY = 'clientMessageId' satisfies keyof MastraDBMessageMetadata;\n\nexport interface ThreadRailTurn {\n key: string;\n messageId: string;\n prompt: string;\n reply?: string;\n files: string[];\n hiddenFileCount: number;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const getClientMessageKey = (message: MastraDBMessage): string => {\n const metadata = message.content.metadata;\n const clientMessageId = isRecord(metadata) ? metadata[CLIENT_MESSAGE_ID_KEY] : undefined;\n return typeof clientMessageId === 'string' && clientMessageId.length > 0 ? clientMessageId : message.id;\n};\n\nconst normalizeSummary = (value: string, fallback: string): string => {\n const normalized = value.replace(/\\s+/g, ' ').trim();\n if (normalized.length === 0) return fallback;\n if (normalized.length <= SUMMARY_MAX_LENGTH) return normalized;\n return `${normalized.slice(0, SUMMARY_MAX_LENGTH - 3).trimEnd()}...`;\n};\n\nconst getTextFromParts = (message: MastraDBMessage): string =>\n message.content.parts\n .flatMap(part => {\n if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return [];\n return [part.text];\n })\n .join('\\n');\n\nconst getStringField = (part: Record<string, unknown>, keys: string[]): string | undefined => {\n for (const key of keys) {\n const value = part[key];\n if (typeof value === 'string' && value.trim().length > 0) return value;\n }\n return undefined;\n};\n\nconst getPathLabel = (value: string): string | undefined => {\n if (value.startsWith('data:')) return undefined;\n\n try {\n const url = new URL(value);\n const candidate = url.pathname.split('/').filter(Boolean).pop();\n return candidate || url.hostname || undefined;\n } catch {\n const candidate = value.split(/[?#]/)[0]?.split('/').filter(Boolean).pop();\n return candidate && !candidate.startsWith('data:') ? candidate : undefined;\n }\n};\n\nconst getFallbackFileLabel = (part: Record<string, unknown>): string => {\n const mediaType = getStringField(part, ['mimeType', 'mediaType']) ?? '';\n if (part.type === 'image' || mediaType.startsWith('image/')) return 'Image';\n if (mediaType === 'application/pdf') return 'PDF';\n if (mediaType.startsWith('video/')) return 'Video';\n if (mediaType.startsWith('audio/')) return 'Audio';\n return 'File';\n};\n\nconst getFileLabelFromPart = (part: MastraDBMessage['content']['parts'][number]): string | undefined => {\n if (!isRecord(part)) return undefined;\n\n const type = getStringField(part, ['type']);\n if (type !== 'file' && type !== 'image') return undefined;\n\n const explicitLabel = getStringField(part, ['filename', 'name']);\n if (explicitLabel) return explicitLabel;\n\n const source = getStringField(part, ['url', 'image', 'data']);\n const pathLabel = source ? getPathLabel(source) : undefined;\n return pathLabel ?? getFallbackFileLabel(part);\n};\n\nconst getFileLabels = (message: MastraDBMessage): string[] =>\n message.content.parts.map(getFileLabelFromPart).filter((label): label is string => Boolean(label));\n\nconst getSignalType = (message: MastraDBMessage): string | undefined => {\n const signal = message.content.metadata?.signal;\n const metadataType = isRecord(signal) ? signal.type : undefined;\n return typeof metadataType === 'string' ? metadataType : message.type;\n};\n\nconst isDisplayableUserMessage = (message: MastraDBMessage): boolean => {\n if (message.role === 'user') return true;\n if (message.role !== 'signal') return false;\n\n const signalType = getSignalType(message);\n return signalType === 'user' || signalType === 'user-message';\n};\n\nconst getNextAssistantReply = (messages: MastraDBMessage[], startIndex: number): string | undefined => {\n for (let index = startIndex + 1; index < messages.length; index += 1) {\n const message = messages[index];\n if (!message) continue;\n if (isDisplayableUserMessage(message)) return undefined;\n if (message.role !== 'assistant') continue;\n\n const reply = normalizeSummary(getTextFromParts(message), '');\n if (reply) return reply;\n }\n\n return undefined;\n};\n\nexport const buildThreadRailTurns = (messages: MastraDBMessage[]): ThreadRailTurn[] =>\n messages.flatMap((message, index) => {\n if (!isDisplayableUserMessage(message)) return [];\n\n const files = getFileLabels(message);\n const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);\n\n return [\n {\n key: getClientMessageKey(message),\n messageId: message.id,\n prompt: normalizeSummary(getTextFromParts(message), files.length > 0 ? 'Attached file' : 'User message'),\n reply: getNextAssistantReply(messages, index),\n files: visibleFiles,\n hiddenFileCount: files.length - visibleFiles.length,\n },\n ];\n });\n"],"names":["React","useOptionalMessageScroller","useOptionalMessageScrollerVisibility","jsxs","cn","jsx","ScrollArea","useMeasuredAutoHeight","FileText"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThreadRail.cjs.js","sources":["../../src/ds/components/ThreadRail/thread-rail.tsx","../../src/ds/components/ThreadRail/thread-rail-turns.ts"],"sourcesContent":["import { FileText } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { ThreadRailTurn } from './thread-rail-turns';\n\nimport { useOptionalMessageScroller, useOptionalMessageScrollerVisibility } from '@/ds/components/MessageScroller';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { useMeasuredAutoHeight } from '@/hooks/use-measured-auto-height';\nimport { cn } from '@/lib/utils';\n\ntype ThreadRailPreviewPhase = 'hidden' | 'entering' | 'visible' | 'exiting';\n\ntype ThreadRailPreviewState = {\n currentTurn: ThreadRailTurn | undefined;\n previousTurn: ThreadRailTurn | undefined;\n index: number | null;\n phase: ThreadRailPreviewPhase;\n top: number;\n transitionKey: number;\n};\n\nconst PREVIEW_TRANSITION_DURATION_MS = 360;\nconst PREVIEW_CLEANUP_DELAY_MS = PREVIEW_TRANSITION_DURATION_MS + 80;\n\nconst DEFAULT_PREVIEW_STATE: ThreadRailPreviewState = {\n currentTurn: undefined,\n previousTurn: undefined,\n index: null,\n phase: 'hidden',\n top: 0,\n transitionKey: 0,\n};\n\nexport interface ThreadRailProps {\n turns: ThreadRailTurn[];\n currentAnchorId?: string;\n visibleMessageIds?: string[];\n label?: string;\n className?: string;\n maxHeight?: string;\n scrollAreaClassName?: string;\n onSelect?: (turn: ThreadRailTurn) => void;\n}\n\nexport function ThreadRail({\n turns,\n currentAnchorId,\n visibleMessageIds,\n label = 'Conversation timeline',\n className,\n maxHeight = 'calc(100dvh - 12rem)',\n scrollAreaClassName,\n onSelect,\n}: ThreadRailProps) {\n const railRef = React.useRef<HTMLElement>(null);\n const previewId = React.useId();\n const [previewState, setPreviewState] = React.useState<ThreadRailPreviewState>(DEFAULT_PREVIEW_STATE);\n const messageScroller = useOptionalMessageScroller();\n const scrollerVisibility = useOptionalMessageScrollerVisibility();\n\n const fallbackMessageId = turns.at(-1)?.messageId;\n const activeMessageId = currentAnchorId ?? scrollerVisibility?.currentAnchorId ?? fallbackMessageId;\n const resolvedVisibleMessageIds =\n visibleMessageIds ?? scrollerVisibility?.visibleMessageIds ?? (activeMessageId ? [activeMessageId] : []);\n const visibleMessageIdSet = new Set(resolvedVisibleMessageIds);\n const previewHoverActive = previewState.phase === 'entering' || previewState.phase === 'visible';\n const hoveredIndex = previewHoverActive ? previewState.index : null;\n const selectTurn = React.useCallback(\n (turn: ThreadRailTurn) => {\n if (onSelect) {\n onSelect(turn);\n return;\n }\n\n messageScroller?.scrollToMessage(turn.messageId, { behavior: 'smooth', align: 'start' });\n },\n [messageScroller, onSelect],\n );\n\n const showPreview = (index: number, element: HTMLElement) => {\n const railTop = railRef.current?.getBoundingClientRect().top ?? 0;\n const itemRect = element.getBoundingClientRect();\n const nextTurn = turns[index];\n if (!nextTurn) return;\n\n setPreviewState(current => {\n const nextTop = itemRect.top + itemRect.height / 2 - railTop;\n if (current.index === index && current.phase !== 'hidden' && current.phase !== 'exiting') {\n return { ...current, top: nextTop };\n }\n\n const previousTurn =\n current.currentTurn && current.currentTurn.key !== nextTurn.key && current.phase !== 'hidden'\n ? current.currentTurn\n : undefined;\n\n return {\n currentTurn: nextTurn,\n previousTurn,\n index,\n phase: 'entering',\n top: nextTop,\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n const hidePreview = () => {\n setPreviewState(current => {\n if (!current.currentTurn || current.phase === 'hidden' || current.phase === 'exiting') {\n return { ...current, index: null };\n }\n\n return {\n ...current,\n index: null,\n previousTurn: undefined,\n phase: 'exiting',\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n React.useEffect(() => {\n if (previewState.phase !== 'entering') return;\n\n const requestFrame = window.requestAnimationFrame ?? window.setTimeout;\n const cancelFrame = window.cancelAnimationFrame ?? window.clearTimeout;\n let settleFrame: number | undefined;\n const startFrame = requestFrame(() => {\n settleFrame = requestFrame(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey && current.phase === 'entering'\n ? { ...current, phase: 'visible' }\n : current,\n );\n });\n });\n\n return () => {\n cancelFrame(startFrame);\n if (settleFrame !== undefined) cancelFrame(settleFrame);\n };\n }, [previewState.phase, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'visible' || !previewState.previousTurn) return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? { ...current, previousTurn: undefined } : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.previousTurn, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'exiting') return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? DEFAULT_PREVIEW_STATE : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.transitionKey]);\n\n if (turns.length === 0) return null;\n\n return (\n <nav\n ref={railRef}\n aria-label={label}\n data-testid=\"thread-rail\"\n className={cn('relative w-8 py-2', className)}\n onMouseLeave={hidePreview}\n onBlur={event => {\n const nextFocus = event.relatedTarget;\n if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) hidePreview();\n }}\n >\n <ScrollArea\n data-testid=\"thread-rail-scroll-area\"\n maxHeight={maxHeight}\n className={cn('w-8', scrollAreaClassName)}\n viewPortClassName=\"pr-3\"\n >\n <div className=\"flex w-4 flex-col items-start gap-2 py-2\">\n {turns.map((turn, index) => {\n const distance = hoveredIndex === null ? null : Math.abs(index - hoveredIndex);\n const active = turn.messageId === activeMessageId;\n const inView = visibleMessageIdSet.has(turn.messageId);\n const previewActive = hoveredIndex === index;\n\n return (\n <ThreadRailItem\n key={turn.key}\n turn={turn}\n index={index}\n distance={distance}\n active={active}\n inView={inView}\n previewId={previewActive ? previewId : undefined}\n onHoverChange={showPreview}\n onSelect={selectTurn}\n />\n );\n })}\n </div>\n </ScrollArea>\n\n {previewState.currentTurn && (\n <ThreadRailPreview\n id={previewId}\n currentTurn={previewState.currentTurn}\n previousTurn={previewState.previousTurn}\n phase={previewState.phase}\n top={previewState.top}\n />\n )}\n </nav>\n );\n}\n\ninterface ThreadRailItemProps {\n turn: ThreadRailTurn;\n index: number;\n distance: number | null;\n active: boolean;\n inView: boolean;\n previewId?: string;\n onHoverChange: (index: number, element: HTMLElement) => void;\n onSelect: (turn: ThreadRailTurn) => void;\n}\n\n/** Width of a rail tick: widest at the hovered item, tapering to neighbours. */\nconst getRailItemWidth = (distance: number | null): string => {\n if (distance === 0) return 'w-4';\n if (distance === 1) return 'w-3';\n return 'w-2';\n};\n\n/** Background tone of a rail tick, prioritising hovered/active, then in-view, then proximity. */\nconst getRailItemTone = ({\n distance,\n active,\n inView,\n}: Pick<ThreadRailItemProps, 'distance' | 'active' | 'inView'>): string => {\n if (distance === 0 || active) return 'bg-neutral6';\n if (inView) return 'bg-neutral5';\n if (distance === 1) return 'bg-neutral4';\n return 'bg-neutral3/60';\n};\n\nfunction ThreadRailItem({\n turn,\n index,\n distance,\n active,\n inView,\n previewId,\n onHoverChange,\n onSelect,\n}: ThreadRailItemProps) {\n const size = getRailItemWidth(distance);\n const tone = getRailItemTone({ distance, active, inView });\n\n return (\n <div\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n className=\"group/thread-rail-item relative flex items-center\"\n >\n <button\n type=\"button\"\n aria-label={`Jump to ${turn.prompt}`}\n aria-current={active ? 'location' : undefined}\n aria-describedby={previewId}\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n onClick={() => onSelect(turn)}\n onMouseEnter={event => onHoverChange(index, event.currentTarget)}\n onFocus={event => onHoverChange(index, event.currentTarget)}\n className={cn(\n 'relative block h-px cursor-pointer rounded-full transition-[width,background-color] duration-normal ease-out',\n \"before:absolute before:inset-x-0 before:-inset-y-1 before:content-['']\",\n 'focus-visible:ring-2 focus-visible:ring-accent1/40 focus-visible:outline-hidden',\n size,\n tone,\n )}\n />\n </div>\n );\n}\n\nfunction ThreadRailPreview({\n id,\n currentTurn,\n previousTurn,\n phase,\n top,\n}: {\n id: string;\n currentTurn: ThreadRailTurn;\n previousTurn: ThreadRailTurn | undefined;\n phase: ThreadRailPreviewPhase;\n top: number;\n}) {\n const {\n ref: previewSizerRef,\n heightStyle: previewHeightStyle,\n measure: measurePreviewHeight,\n } = useMeasuredAutoHeight<HTMLDivElement>();\n const containerVisible = phase === 'visible' || (phase === 'entering' && Boolean(previousTurn));\n // Entering and exiting share the same off-screen resting style.\n const hiddenLayerClassName = 'scale-95 opacity-0 blur-xs';\n const visibleLayerClassName = 'scale-100 opacity-100 blur-none';\n const layerClassName =\n 'absolute inset-x-0 top-0 h-full origin-left transition-[opacity,filter,scale] duration-150 ease-in-out will-change-[opacity,filter,scale] motion-reduce:scale-100 motion-reduce:blur-none motion-reduce:transition-none';\n\n React.useLayoutEffect(() => {\n measurePreviewHeight();\n }, [currentTurn.key, phase, measurePreviewHeight]);\n\n return (\n <div\n id={id}\n data-testid=\"thread-rail-preview\"\n data-visible={containerVisible ? 'true' : undefined}\n className={cn(\n 'pointer-events-none absolute top-0 left-full z-30 ml-3 w-72 overflow-hidden rounded-xl border border-border1 bg-surface3 text-left shadow-dialog transition-[height,translate,opacity] duration-360 ease-out-custom will-change-[height,translate,opacity] motion-reduce:transition-none',\n containerVisible ? 'opacity-100' : 'opacity-0',\n )}\n style={{ ...previewHeightStyle, translate: `0 calc(${top}px - 50%)` }}\n >\n <div ref={previewSizerRef} data-testid=\"thread-rail-preview-sizer\" aria-hidden className=\"invisible\">\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n <div data-testid=\"thread-rail-preview-viewport\" className=\"absolute inset-0\">\n <div className=\"relative h-full\">\n {previousTurn && (\n <div\n key={previousTurn.key}\n data-testid=\"thread-rail-preview-previous\"\n aria-hidden\n className={cn(layerClassName, phase === 'entering' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={previousTurn} className=\"p-3.5\" />\n </div>\n )}\n <div\n key={currentTurn.key}\n data-testid=\"thread-rail-preview-current\"\n className={cn(layerClassName, phase === 'visible' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ThreadRailPreviewContent({\n turn,\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & { turn: ThreadRailTurn }) {\n return (\n <div className={className} {...props}>\n <div className=\"text-ui-md leading-ui-md text-neutral6 truncate font-medium\">{turn.prompt}</div>\n {turn.reply && <p className=\"text-ui-sm leading-ui-sm text-neutral4 mt-1.5 line-clamp-3\">{turn.reply}</p>}\n {(turn.files.length > 0 || turn.hiddenFileCount > 0) && (\n <div className=\"border-border1/60 mt-3 flex flex-wrap items-center gap-2 border-t pt-2.5\">\n {turn.files.map(file => (\n <span key={file} className=\"text-ui-sm text-neutral4 inline-flex max-w-44 items-center gap-1.5 truncate\">\n <FileText className=\"size-3.5 shrink-0 opacity-70\" aria-hidden />\n {file}\n </span>\n ))}\n {turn.hiddenFileCount > 0 && (\n <span className=\"text-ui-sm text-neutral4 font-medium\">+{turn.hiddenFileCount}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n","import type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport type { MastraDBMessageMetadata } from '@mastra/react';\n\nconst SUMMARY_MAX_LENGTH = 120;\nconst FILE_PREVIEW_LIMIT = 2;\n// Inlined, not imported: the value export sits behind a barrel this browser bundle must not pull.\nconst CLIENT_MESSAGE_ID_KEY = 'clientMessageId' satisfies keyof MastraDBMessageMetadata;\n\nexport interface ThreadRailTurn {\n key: string;\n messageId: string;\n prompt: string;\n reply?: string;\n files: string[];\n hiddenFileCount: number;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const getClientMessageKey = (message: MastraDBMessage): string => {\n const metadata = message.content.metadata;\n const clientMessageId = isRecord(metadata) ? metadata[CLIENT_MESSAGE_ID_KEY] : undefined;\n return typeof clientMessageId === 'string' && clientMessageId.length > 0 ? clientMessageId : message.id;\n};\n\nconst normalizeSummary = (value: string, fallback: string): string => {\n const normalized = value.replace(/\\s+/g, ' ').trim();\n if (normalized.length === 0) return fallback;\n if (normalized.length <= SUMMARY_MAX_LENGTH) return normalized;\n return `${normalized.slice(0, SUMMARY_MAX_LENGTH - 3).trimEnd()}...`;\n};\n\nconst getTextFromParts = (message: MastraDBMessage): string =>\n message.content.parts\n .flatMap(part => {\n if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return [];\n return [part.text];\n })\n .join('\\n');\n\nconst getStringField = (part: Record<string, unknown>, keys: string[]): string | undefined => {\n for (const key of keys) {\n const value = part[key];\n if (typeof value === 'string' && value.trim().length > 0) return value;\n }\n return undefined;\n};\n\nconst getPathLabel = (value: string): string | undefined => {\n if (value.startsWith('data:')) return undefined;\n\n try {\n const url = new URL(value);\n const candidate = url.pathname.split('/').filter(Boolean).pop();\n return candidate || url.hostname || undefined;\n } catch {\n const candidate = value.split(/[?#]/)[0]?.split('/').filter(Boolean).pop();\n return candidate && !candidate.startsWith('data:') ? candidate : undefined;\n }\n};\n\nconst getFallbackFileLabel = (part: Record<string, unknown>): string => {\n const mediaType = getStringField(part, ['mimeType', 'mediaType']) ?? '';\n if (part.type === 'image' || mediaType.startsWith('image/')) return 'Image';\n if (mediaType === 'application/pdf') return 'PDF';\n if (mediaType.startsWith('video/')) return 'Video';\n if (mediaType.startsWith('audio/')) return 'Audio';\n return 'File';\n};\n\nconst getFileLabelFromPart = (part: MastraDBMessage['content']['parts'][number]): string | undefined => {\n if (!isRecord(part)) return undefined;\n\n const type = getStringField(part, ['type']);\n if (type !== 'file' && type !== 'image') return undefined;\n\n const explicitLabel = getStringField(part, ['filename', 'name']);\n if (explicitLabel) return explicitLabel;\n\n const source = getStringField(part, ['url', 'image', 'data']);\n const pathLabel = source ? getPathLabel(source) : undefined;\n return pathLabel ?? getFallbackFileLabel(part);\n};\n\nconst getFileLabels = (message: MastraDBMessage): string[] =>\n message.content.parts.map(getFileLabelFromPart).filter((label): label is string => Boolean(label));\n\nconst getSignalType = (message: MastraDBMessage): string | undefined => {\n const signal = message.content.metadata?.signal;\n const metadataType = isRecord(signal) ? signal.type : undefined;\n return typeof metadataType === 'string' ? metadataType : message.type;\n};\n\n/** What opens a turn: a rail stop, and the row the scroller parks at the top. */\nexport const startsUserTurn = (message: MastraDBMessage): boolean => {\n if (message.role === 'user') return true;\n if (message.role !== 'signal') return false;\n\n const signalType = getSignalType(message);\n return signalType === 'user' || signalType === 'user-message';\n};\n\nconst getNextAssistantReply = (messages: MastraDBMessage[], startIndex: number): string | undefined => {\n for (let index = startIndex + 1; index < messages.length; index += 1) {\n const message = messages[index];\n if (!message) continue;\n if (startsUserTurn(message)) return undefined;\n if (message.role !== 'assistant') continue;\n\n const reply = normalizeSummary(getTextFromParts(message), '');\n if (reply) return reply;\n }\n\n return undefined;\n};\n\nexport const buildThreadRailTurns = (messages: MastraDBMessage[]): ThreadRailTurn[] =>\n messages.flatMap((message, index) => {\n if (!startsUserTurn(message)) return [];\n\n const files = getFileLabels(message);\n const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);\n\n return [\n {\n key: getClientMessageKey(message),\n messageId: message.id,\n prompt: normalizeSummary(getTextFromParts(message), files.length > 0 ? 'Attached file' : 'User message'),\n reply: getNextAssistantReply(messages, index),\n files: visibleFiles,\n hiddenFileCount: files.length - visibleFiles.length,\n },\n ];\n });\n"],"names":["React","useOptionalMessageScroller","useOptionalMessageScrollerVisibility","jsxs","cn","jsx","ScrollArea","useMeasuredAutoHeight","FileText"],"mappings":"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"}
|
|
@@ -370,7 +370,7 @@ const getSignalType = (message) => {
|
|
|
370
370
|
const metadataType = isRecord(signal) ? signal.type : void 0;
|
|
371
371
|
return typeof metadataType === "string" ? metadataType : message.type;
|
|
372
372
|
};
|
|
373
|
-
const
|
|
373
|
+
const startsUserTurn = (message) => {
|
|
374
374
|
if (message.role === "user") return true;
|
|
375
375
|
if (message.role !== "signal") return false;
|
|
376
376
|
const signalType = getSignalType(message);
|
|
@@ -380,7 +380,7 @@ const getNextAssistantReply = (messages, startIndex) => {
|
|
|
380
380
|
for (let index = startIndex + 1; index < messages.length; index += 1) {
|
|
381
381
|
const message = messages[index];
|
|
382
382
|
if (!message) continue;
|
|
383
|
-
if (
|
|
383
|
+
if (startsUserTurn(message)) return void 0;
|
|
384
384
|
if (message.role !== "assistant") continue;
|
|
385
385
|
const reply = normalizeSummary(getTextFromParts(message), "");
|
|
386
386
|
if (reply) return reply;
|
|
@@ -388,7 +388,7 @@ const getNextAssistantReply = (messages, startIndex) => {
|
|
|
388
388
|
return void 0;
|
|
389
389
|
};
|
|
390
390
|
const buildThreadRailTurns = (messages) => messages.flatMap((message, index) => {
|
|
391
|
-
if (!
|
|
391
|
+
if (!startsUserTurn(message)) return [];
|
|
392
392
|
const files = getFileLabels(message);
|
|
393
393
|
const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);
|
|
394
394
|
return [
|
|
@@ -403,5 +403,5 @@ const buildThreadRailTurns = (messages) => messages.flatMap((message, index) =>
|
|
|
403
403
|
];
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
-
export { ThreadRail, buildThreadRailTurns, getClientMessageKey };
|
|
406
|
+
export { ThreadRail, buildThreadRailTurns, getClientMessageKey, startsUserTurn };
|
|
407
407
|
//# sourceMappingURL=ThreadRail.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadRail.es.js","sources":["../../src/ds/components/ThreadRail/thread-rail.tsx","../../src/ds/components/ThreadRail/thread-rail-turns.ts"],"sourcesContent":["import { FileText } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { ThreadRailTurn } from './thread-rail-turns';\n\nimport { useOptionalMessageScroller, useOptionalMessageScrollerVisibility } from '@/ds/components/MessageScroller';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { useMeasuredAutoHeight } from '@/hooks/use-measured-auto-height';\nimport { cn } from '@/lib/utils';\n\ntype ThreadRailPreviewPhase = 'hidden' | 'entering' | 'visible' | 'exiting';\n\ntype ThreadRailPreviewState = {\n currentTurn: ThreadRailTurn | undefined;\n previousTurn: ThreadRailTurn | undefined;\n index: number | null;\n phase: ThreadRailPreviewPhase;\n top: number;\n transitionKey: number;\n};\n\nconst PREVIEW_TRANSITION_DURATION_MS = 360;\nconst PREVIEW_CLEANUP_DELAY_MS = PREVIEW_TRANSITION_DURATION_MS + 80;\n\nconst DEFAULT_PREVIEW_STATE: ThreadRailPreviewState = {\n currentTurn: undefined,\n previousTurn: undefined,\n index: null,\n phase: 'hidden',\n top: 0,\n transitionKey: 0,\n};\n\nexport interface ThreadRailProps {\n turns: ThreadRailTurn[];\n currentAnchorId?: string;\n visibleMessageIds?: string[];\n label?: string;\n className?: string;\n maxHeight?: string;\n scrollAreaClassName?: string;\n onSelect?: (turn: ThreadRailTurn) => void;\n}\n\nexport function ThreadRail({\n turns,\n currentAnchorId,\n visibleMessageIds,\n label = 'Conversation timeline',\n className,\n maxHeight = 'calc(100dvh - 12rem)',\n scrollAreaClassName,\n onSelect,\n}: ThreadRailProps) {\n const railRef = React.useRef<HTMLElement>(null);\n const previewId = React.useId();\n const [previewState, setPreviewState] = React.useState<ThreadRailPreviewState>(DEFAULT_PREVIEW_STATE);\n const messageScroller = useOptionalMessageScroller();\n const scrollerVisibility = useOptionalMessageScrollerVisibility();\n\n const fallbackMessageId = turns.at(-1)?.messageId;\n const activeMessageId = currentAnchorId ?? scrollerVisibility?.currentAnchorId ?? fallbackMessageId;\n const resolvedVisibleMessageIds =\n visibleMessageIds ?? scrollerVisibility?.visibleMessageIds ?? (activeMessageId ? [activeMessageId] : []);\n const visibleMessageIdSet = new Set(resolvedVisibleMessageIds);\n const previewHoverActive = previewState.phase === 'entering' || previewState.phase === 'visible';\n const hoveredIndex = previewHoverActive ? previewState.index : null;\n const selectTurn = React.useCallback(\n (turn: ThreadRailTurn) => {\n if (onSelect) {\n onSelect(turn);\n return;\n }\n\n messageScroller?.scrollToMessage(turn.messageId, { behavior: 'smooth', align: 'start' });\n },\n [messageScroller, onSelect],\n );\n\n const showPreview = (index: number, element: HTMLElement) => {\n const railTop = railRef.current?.getBoundingClientRect().top ?? 0;\n const itemRect = element.getBoundingClientRect();\n const nextTurn = turns[index];\n if (!nextTurn) return;\n\n setPreviewState(current => {\n const nextTop = itemRect.top + itemRect.height / 2 - railTop;\n if (current.index === index && current.phase !== 'hidden' && current.phase !== 'exiting') {\n return { ...current, top: nextTop };\n }\n\n const previousTurn =\n current.currentTurn && current.currentTurn.key !== nextTurn.key && current.phase !== 'hidden'\n ? current.currentTurn\n : undefined;\n\n return {\n currentTurn: nextTurn,\n previousTurn,\n index,\n phase: 'entering',\n top: nextTop,\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n const hidePreview = () => {\n setPreviewState(current => {\n if (!current.currentTurn || current.phase === 'hidden' || current.phase === 'exiting') {\n return { ...current, index: null };\n }\n\n return {\n ...current,\n index: null,\n previousTurn: undefined,\n phase: 'exiting',\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n React.useEffect(() => {\n if (previewState.phase !== 'entering') return;\n\n const requestFrame = window.requestAnimationFrame ?? window.setTimeout;\n const cancelFrame = window.cancelAnimationFrame ?? window.clearTimeout;\n let settleFrame: number | undefined;\n const startFrame = requestFrame(() => {\n settleFrame = requestFrame(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey && current.phase === 'entering'\n ? { ...current, phase: 'visible' }\n : current,\n );\n });\n });\n\n return () => {\n cancelFrame(startFrame);\n if (settleFrame !== undefined) cancelFrame(settleFrame);\n };\n }, [previewState.phase, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'visible' || !previewState.previousTurn) return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? { ...current, previousTurn: undefined } : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.previousTurn, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'exiting') return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? DEFAULT_PREVIEW_STATE : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.transitionKey]);\n\n if (turns.length === 0) return null;\n\n return (\n <nav\n ref={railRef}\n aria-label={label}\n data-testid=\"thread-rail\"\n className={cn('relative w-8 py-2', className)}\n onMouseLeave={hidePreview}\n onBlur={event => {\n const nextFocus = event.relatedTarget;\n if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) hidePreview();\n }}\n >\n <ScrollArea\n data-testid=\"thread-rail-scroll-area\"\n maxHeight={maxHeight}\n className={cn('w-8', scrollAreaClassName)}\n viewPortClassName=\"pr-3\"\n >\n <div className=\"flex w-4 flex-col items-start gap-2 py-2\">\n {turns.map((turn, index) => {\n const distance = hoveredIndex === null ? null : Math.abs(index - hoveredIndex);\n const active = turn.messageId === activeMessageId;\n const inView = visibleMessageIdSet.has(turn.messageId);\n const previewActive = hoveredIndex === index;\n\n return (\n <ThreadRailItem\n key={turn.key}\n turn={turn}\n index={index}\n distance={distance}\n active={active}\n inView={inView}\n previewId={previewActive ? previewId : undefined}\n onHoverChange={showPreview}\n onSelect={selectTurn}\n />\n );\n })}\n </div>\n </ScrollArea>\n\n {previewState.currentTurn && (\n <ThreadRailPreview\n id={previewId}\n currentTurn={previewState.currentTurn}\n previousTurn={previewState.previousTurn}\n phase={previewState.phase}\n top={previewState.top}\n />\n )}\n </nav>\n );\n}\n\ninterface ThreadRailItemProps {\n turn: ThreadRailTurn;\n index: number;\n distance: number | null;\n active: boolean;\n inView: boolean;\n previewId?: string;\n onHoverChange: (index: number, element: HTMLElement) => void;\n onSelect: (turn: ThreadRailTurn) => void;\n}\n\n/** Width of a rail tick: widest at the hovered item, tapering to neighbours. */\nconst getRailItemWidth = (distance: number | null): string => {\n if (distance === 0) return 'w-4';\n if (distance === 1) return 'w-3';\n return 'w-2';\n};\n\n/** Background tone of a rail tick, prioritising hovered/active, then in-view, then proximity. */\nconst getRailItemTone = ({\n distance,\n active,\n inView,\n}: Pick<ThreadRailItemProps, 'distance' | 'active' | 'inView'>): string => {\n if (distance === 0 || active) return 'bg-neutral6';\n if (inView) return 'bg-neutral5';\n if (distance === 1) return 'bg-neutral4';\n return 'bg-neutral3/60';\n};\n\nfunction ThreadRailItem({\n turn,\n index,\n distance,\n active,\n inView,\n previewId,\n onHoverChange,\n onSelect,\n}: ThreadRailItemProps) {\n const size = getRailItemWidth(distance);\n const tone = getRailItemTone({ distance, active, inView });\n\n return (\n <div\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n className=\"group/thread-rail-item relative flex items-center\"\n >\n <button\n type=\"button\"\n aria-label={`Jump to ${turn.prompt}`}\n aria-current={active ? 'location' : undefined}\n aria-describedby={previewId}\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n onClick={() => onSelect(turn)}\n onMouseEnter={event => onHoverChange(index, event.currentTarget)}\n onFocus={event => onHoverChange(index, event.currentTarget)}\n className={cn(\n 'relative block h-px cursor-pointer rounded-full transition-[width,background-color] duration-normal ease-out',\n \"before:absolute before:inset-x-0 before:-inset-y-1 before:content-['']\",\n 'focus-visible:ring-2 focus-visible:ring-accent1/40 focus-visible:outline-hidden',\n size,\n tone,\n )}\n />\n </div>\n );\n}\n\nfunction ThreadRailPreview({\n id,\n currentTurn,\n previousTurn,\n phase,\n top,\n}: {\n id: string;\n currentTurn: ThreadRailTurn;\n previousTurn: ThreadRailTurn | undefined;\n phase: ThreadRailPreviewPhase;\n top: number;\n}) {\n const {\n ref: previewSizerRef,\n heightStyle: previewHeightStyle,\n measure: measurePreviewHeight,\n } = useMeasuredAutoHeight<HTMLDivElement>();\n const containerVisible = phase === 'visible' || (phase === 'entering' && Boolean(previousTurn));\n // Entering and exiting share the same off-screen resting style.\n const hiddenLayerClassName = 'scale-95 opacity-0 blur-xs';\n const visibleLayerClassName = 'scale-100 opacity-100 blur-none';\n const layerClassName =\n 'absolute inset-x-0 top-0 h-full origin-left transition-[opacity,filter,scale] duration-150 ease-in-out will-change-[opacity,filter,scale] motion-reduce:scale-100 motion-reduce:blur-none motion-reduce:transition-none';\n\n React.useLayoutEffect(() => {\n measurePreviewHeight();\n }, [currentTurn.key, phase, measurePreviewHeight]);\n\n return (\n <div\n id={id}\n data-testid=\"thread-rail-preview\"\n data-visible={containerVisible ? 'true' : undefined}\n className={cn(\n 'pointer-events-none absolute top-0 left-full z-30 ml-3 w-72 overflow-hidden rounded-xl border border-border1 bg-surface3 text-left shadow-dialog transition-[height,translate,opacity] duration-360 ease-out-custom will-change-[height,translate,opacity] motion-reduce:transition-none',\n containerVisible ? 'opacity-100' : 'opacity-0',\n )}\n style={{ ...previewHeightStyle, translate: `0 calc(${top}px - 50%)` }}\n >\n <div ref={previewSizerRef} data-testid=\"thread-rail-preview-sizer\" aria-hidden className=\"invisible\">\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n <div data-testid=\"thread-rail-preview-viewport\" className=\"absolute inset-0\">\n <div className=\"relative h-full\">\n {previousTurn && (\n <div\n key={previousTurn.key}\n data-testid=\"thread-rail-preview-previous\"\n aria-hidden\n className={cn(layerClassName, phase === 'entering' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={previousTurn} className=\"p-3.5\" />\n </div>\n )}\n <div\n key={currentTurn.key}\n data-testid=\"thread-rail-preview-current\"\n className={cn(layerClassName, phase === 'visible' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ThreadRailPreviewContent({\n turn,\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & { turn: ThreadRailTurn }) {\n return (\n <div className={className} {...props}>\n <div className=\"text-ui-md leading-ui-md text-neutral6 truncate font-medium\">{turn.prompt}</div>\n {turn.reply && <p className=\"text-ui-sm leading-ui-sm text-neutral4 mt-1.5 line-clamp-3\">{turn.reply}</p>}\n {(turn.files.length > 0 || turn.hiddenFileCount > 0) && (\n <div className=\"border-border1/60 mt-3 flex flex-wrap items-center gap-2 border-t pt-2.5\">\n {turn.files.map(file => (\n <span key={file} className=\"text-ui-sm text-neutral4 inline-flex max-w-44 items-center gap-1.5 truncate\">\n <FileText className=\"size-3.5 shrink-0 opacity-70\" aria-hidden />\n {file}\n </span>\n ))}\n {turn.hiddenFileCount > 0 && (\n <span className=\"text-ui-sm text-neutral4 font-medium\">+{turn.hiddenFileCount}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n","import type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport type { MastraDBMessageMetadata } from '@mastra/react';\n\nconst SUMMARY_MAX_LENGTH = 120;\nconst FILE_PREVIEW_LIMIT = 2;\n// Inlined, not imported: the value export sits behind a barrel this browser bundle must not pull.\nconst CLIENT_MESSAGE_ID_KEY = 'clientMessageId' satisfies keyof MastraDBMessageMetadata;\n\nexport interface ThreadRailTurn {\n key: string;\n messageId: string;\n prompt: string;\n reply?: string;\n files: string[];\n hiddenFileCount: number;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const getClientMessageKey = (message: MastraDBMessage): string => {\n const metadata = message.content.metadata;\n const clientMessageId = isRecord(metadata) ? metadata[CLIENT_MESSAGE_ID_KEY] : undefined;\n return typeof clientMessageId === 'string' && clientMessageId.length > 0 ? clientMessageId : message.id;\n};\n\nconst normalizeSummary = (value: string, fallback: string): string => {\n const normalized = value.replace(/\\s+/g, ' ').trim();\n if (normalized.length === 0) return fallback;\n if (normalized.length <= SUMMARY_MAX_LENGTH) return normalized;\n return `${normalized.slice(0, SUMMARY_MAX_LENGTH - 3).trimEnd()}...`;\n};\n\nconst getTextFromParts = (message: MastraDBMessage): string =>\n message.content.parts\n .flatMap(part => {\n if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return [];\n return [part.text];\n })\n .join('\\n');\n\nconst getStringField = (part: Record<string, unknown>, keys: string[]): string | undefined => {\n for (const key of keys) {\n const value = part[key];\n if (typeof value === 'string' && value.trim().length > 0) return value;\n }\n return undefined;\n};\n\nconst getPathLabel = (value: string): string | undefined => {\n if (value.startsWith('data:')) return undefined;\n\n try {\n const url = new URL(value);\n const candidate = url.pathname.split('/').filter(Boolean).pop();\n return candidate || url.hostname || undefined;\n } catch {\n const candidate = value.split(/[?#]/)[0]?.split('/').filter(Boolean).pop();\n return candidate && !candidate.startsWith('data:') ? candidate : undefined;\n }\n};\n\nconst getFallbackFileLabel = (part: Record<string, unknown>): string => {\n const mediaType = getStringField(part, ['mimeType', 'mediaType']) ?? '';\n if (part.type === 'image' || mediaType.startsWith('image/')) return 'Image';\n if (mediaType === 'application/pdf') return 'PDF';\n if (mediaType.startsWith('video/')) return 'Video';\n if (mediaType.startsWith('audio/')) return 'Audio';\n return 'File';\n};\n\nconst getFileLabelFromPart = (part: MastraDBMessage['content']['parts'][number]): string | undefined => {\n if (!isRecord(part)) return undefined;\n\n const type = getStringField(part, ['type']);\n if (type !== 'file' && type !== 'image') return undefined;\n\n const explicitLabel = getStringField(part, ['filename', 'name']);\n if (explicitLabel) return explicitLabel;\n\n const source = getStringField(part, ['url', 'image', 'data']);\n const pathLabel = source ? getPathLabel(source) : undefined;\n return pathLabel ?? getFallbackFileLabel(part);\n};\n\nconst getFileLabels = (message: MastraDBMessage): string[] =>\n message.content.parts.map(getFileLabelFromPart).filter((label): label is string => Boolean(label));\n\nconst getSignalType = (message: MastraDBMessage): string | undefined => {\n const signal = message.content.metadata?.signal;\n const metadataType = isRecord(signal) ? signal.type : undefined;\n return typeof metadataType === 'string' ? metadataType : message.type;\n};\n\nconst isDisplayableUserMessage = (message: MastraDBMessage): boolean => {\n if (message.role === 'user') return true;\n if (message.role !== 'signal') return false;\n\n const signalType = getSignalType(message);\n return signalType === 'user' || signalType === 'user-message';\n};\n\nconst getNextAssistantReply = (messages: MastraDBMessage[], startIndex: number): string | undefined => {\n for (let index = startIndex + 1; index < messages.length; index += 1) {\n const message = messages[index];\n if (!message) continue;\n if (isDisplayableUserMessage(message)) return undefined;\n if (message.role !== 'assistant') continue;\n\n const reply = normalizeSummary(getTextFromParts(message), '');\n if (reply) return reply;\n }\n\n return undefined;\n};\n\nexport const buildThreadRailTurns = (messages: MastraDBMessage[]): ThreadRailTurn[] =>\n messages.flatMap((message, index) => {\n if (!isDisplayableUserMessage(message)) return [];\n\n const files = getFileLabels(message);\n const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);\n\n return [\n {\n key: getClientMessageKey(message),\n messageId: message.id,\n prompt: normalizeSummary(getTextFromParts(message), files.length > 0 ? 'Attached file' : 'User message'),\n reply: getNextAssistantReply(messages, index),\n files: visibleFiles,\n hiddenFileCount: files.length - visibleFiles.length,\n },\n ];\n });\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThreadRail.es.js","sources":["../../src/ds/components/ThreadRail/thread-rail.tsx","../../src/ds/components/ThreadRail/thread-rail-turns.ts"],"sourcesContent":["import { FileText } from 'lucide-react';\nimport * as React from 'react';\n\nimport type { ThreadRailTurn } from './thread-rail-turns';\n\nimport { useOptionalMessageScroller, useOptionalMessageScrollerVisibility } from '@/ds/components/MessageScroller';\nimport { ScrollArea } from '@/ds/components/ScrollArea';\nimport { useMeasuredAutoHeight } from '@/hooks/use-measured-auto-height';\nimport { cn } from '@/lib/utils';\n\ntype ThreadRailPreviewPhase = 'hidden' | 'entering' | 'visible' | 'exiting';\n\ntype ThreadRailPreviewState = {\n currentTurn: ThreadRailTurn | undefined;\n previousTurn: ThreadRailTurn | undefined;\n index: number | null;\n phase: ThreadRailPreviewPhase;\n top: number;\n transitionKey: number;\n};\n\nconst PREVIEW_TRANSITION_DURATION_MS = 360;\nconst PREVIEW_CLEANUP_DELAY_MS = PREVIEW_TRANSITION_DURATION_MS + 80;\n\nconst DEFAULT_PREVIEW_STATE: ThreadRailPreviewState = {\n currentTurn: undefined,\n previousTurn: undefined,\n index: null,\n phase: 'hidden',\n top: 0,\n transitionKey: 0,\n};\n\nexport interface ThreadRailProps {\n turns: ThreadRailTurn[];\n currentAnchorId?: string;\n visibleMessageIds?: string[];\n label?: string;\n className?: string;\n maxHeight?: string;\n scrollAreaClassName?: string;\n onSelect?: (turn: ThreadRailTurn) => void;\n}\n\nexport function ThreadRail({\n turns,\n currentAnchorId,\n visibleMessageIds,\n label = 'Conversation timeline',\n className,\n maxHeight = 'calc(100dvh - 12rem)',\n scrollAreaClassName,\n onSelect,\n}: ThreadRailProps) {\n const railRef = React.useRef<HTMLElement>(null);\n const previewId = React.useId();\n const [previewState, setPreviewState] = React.useState<ThreadRailPreviewState>(DEFAULT_PREVIEW_STATE);\n const messageScroller = useOptionalMessageScroller();\n const scrollerVisibility = useOptionalMessageScrollerVisibility();\n\n const fallbackMessageId = turns.at(-1)?.messageId;\n const activeMessageId = currentAnchorId ?? scrollerVisibility?.currentAnchorId ?? fallbackMessageId;\n const resolvedVisibleMessageIds =\n visibleMessageIds ?? scrollerVisibility?.visibleMessageIds ?? (activeMessageId ? [activeMessageId] : []);\n const visibleMessageIdSet = new Set(resolvedVisibleMessageIds);\n const previewHoverActive = previewState.phase === 'entering' || previewState.phase === 'visible';\n const hoveredIndex = previewHoverActive ? previewState.index : null;\n const selectTurn = React.useCallback(\n (turn: ThreadRailTurn) => {\n if (onSelect) {\n onSelect(turn);\n return;\n }\n\n messageScroller?.scrollToMessage(turn.messageId, { behavior: 'smooth', align: 'start' });\n },\n [messageScroller, onSelect],\n );\n\n const showPreview = (index: number, element: HTMLElement) => {\n const railTop = railRef.current?.getBoundingClientRect().top ?? 0;\n const itemRect = element.getBoundingClientRect();\n const nextTurn = turns[index];\n if (!nextTurn) return;\n\n setPreviewState(current => {\n const nextTop = itemRect.top + itemRect.height / 2 - railTop;\n if (current.index === index && current.phase !== 'hidden' && current.phase !== 'exiting') {\n return { ...current, top: nextTop };\n }\n\n const previousTurn =\n current.currentTurn && current.currentTurn.key !== nextTurn.key && current.phase !== 'hidden'\n ? current.currentTurn\n : undefined;\n\n return {\n currentTurn: nextTurn,\n previousTurn,\n index,\n phase: 'entering',\n top: nextTop,\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n const hidePreview = () => {\n setPreviewState(current => {\n if (!current.currentTurn || current.phase === 'hidden' || current.phase === 'exiting') {\n return { ...current, index: null };\n }\n\n return {\n ...current,\n index: null,\n previousTurn: undefined,\n phase: 'exiting',\n transitionKey: current.transitionKey + 1,\n };\n });\n };\n\n React.useEffect(() => {\n if (previewState.phase !== 'entering') return;\n\n const requestFrame = window.requestAnimationFrame ?? window.setTimeout;\n const cancelFrame = window.cancelAnimationFrame ?? window.clearTimeout;\n let settleFrame: number | undefined;\n const startFrame = requestFrame(() => {\n settleFrame = requestFrame(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey && current.phase === 'entering'\n ? { ...current, phase: 'visible' }\n : current,\n );\n });\n });\n\n return () => {\n cancelFrame(startFrame);\n if (settleFrame !== undefined) cancelFrame(settleFrame);\n };\n }, [previewState.phase, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'visible' || !previewState.previousTurn) return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? { ...current, previousTurn: undefined } : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.previousTurn, previewState.transitionKey]);\n\n React.useEffect(() => {\n if (previewState.phase !== 'exiting') return;\n\n const timeout = window.setTimeout(() => {\n setPreviewState(current =>\n current.transitionKey === previewState.transitionKey ? DEFAULT_PREVIEW_STATE : current,\n );\n }, PREVIEW_CLEANUP_DELAY_MS);\n\n return () => window.clearTimeout(timeout);\n }, [previewState.phase, previewState.transitionKey]);\n\n if (turns.length === 0) return null;\n\n return (\n <nav\n ref={railRef}\n aria-label={label}\n data-testid=\"thread-rail\"\n className={cn('relative w-8 py-2', className)}\n onMouseLeave={hidePreview}\n onBlur={event => {\n const nextFocus = event.relatedTarget;\n if (!(nextFocus instanceof Node) || !event.currentTarget.contains(nextFocus)) hidePreview();\n }}\n >\n <ScrollArea\n data-testid=\"thread-rail-scroll-area\"\n maxHeight={maxHeight}\n className={cn('w-8', scrollAreaClassName)}\n viewPortClassName=\"pr-3\"\n >\n <div className=\"flex w-4 flex-col items-start gap-2 py-2\">\n {turns.map((turn, index) => {\n const distance = hoveredIndex === null ? null : Math.abs(index - hoveredIndex);\n const active = turn.messageId === activeMessageId;\n const inView = visibleMessageIdSet.has(turn.messageId);\n const previewActive = hoveredIndex === index;\n\n return (\n <ThreadRailItem\n key={turn.key}\n turn={turn}\n index={index}\n distance={distance}\n active={active}\n inView={inView}\n previewId={previewActive ? previewId : undefined}\n onHoverChange={showPreview}\n onSelect={selectTurn}\n />\n );\n })}\n </div>\n </ScrollArea>\n\n {previewState.currentTurn && (\n <ThreadRailPreview\n id={previewId}\n currentTurn={previewState.currentTurn}\n previousTurn={previewState.previousTurn}\n phase={previewState.phase}\n top={previewState.top}\n />\n )}\n </nav>\n );\n}\n\ninterface ThreadRailItemProps {\n turn: ThreadRailTurn;\n index: number;\n distance: number | null;\n active: boolean;\n inView: boolean;\n previewId?: string;\n onHoverChange: (index: number, element: HTMLElement) => void;\n onSelect: (turn: ThreadRailTurn) => void;\n}\n\n/** Width of a rail tick: widest at the hovered item, tapering to neighbours. */\nconst getRailItemWidth = (distance: number | null): string => {\n if (distance === 0) return 'w-4';\n if (distance === 1) return 'w-3';\n return 'w-2';\n};\n\n/** Background tone of a rail tick, prioritising hovered/active, then in-view, then proximity. */\nconst getRailItemTone = ({\n distance,\n active,\n inView,\n}: Pick<ThreadRailItemProps, 'distance' | 'active' | 'inView'>): string => {\n if (distance === 0 || active) return 'bg-neutral6';\n if (inView) return 'bg-neutral5';\n if (distance === 1) return 'bg-neutral4';\n return 'bg-neutral3/60';\n};\n\nfunction ThreadRailItem({\n turn,\n index,\n distance,\n active,\n inView,\n previewId,\n onHoverChange,\n onSelect,\n}: ThreadRailItemProps) {\n const size = getRailItemWidth(distance);\n const tone = getRailItemTone({ distance, active, inView });\n\n return (\n <div\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n className=\"group/thread-rail-item relative flex items-center\"\n >\n <button\n type=\"button\"\n aria-label={`Jump to ${turn.prompt}`}\n aria-current={active ? 'location' : undefined}\n aria-describedby={previewId}\n data-in-view={inView ? 'true' : undefined}\n data-active={active ? 'true' : undefined}\n onClick={() => onSelect(turn)}\n onMouseEnter={event => onHoverChange(index, event.currentTarget)}\n onFocus={event => onHoverChange(index, event.currentTarget)}\n className={cn(\n 'relative block h-px cursor-pointer rounded-full transition-[width,background-color] duration-normal ease-out',\n \"before:absolute before:inset-x-0 before:-inset-y-1 before:content-['']\",\n 'focus-visible:ring-2 focus-visible:ring-accent1/40 focus-visible:outline-hidden',\n size,\n tone,\n )}\n />\n </div>\n );\n}\n\nfunction ThreadRailPreview({\n id,\n currentTurn,\n previousTurn,\n phase,\n top,\n}: {\n id: string;\n currentTurn: ThreadRailTurn;\n previousTurn: ThreadRailTurn | undefined;\n phase: ThreadRailPreviewPhase;\n top: number;\n}) {\n const {\n ref: previewSizerRef,\n heightStyle: previewHeightStyle,\n measure: measurePreviewHeight,\n } = useMeasuredAutoHeight<HTMLDivElement>();\n const containerVisible = phase === 'visible' || (phase === 'entering' && Boolean(previousTurn));\n // Entering and exiting share the same off-screen resting style.\n const hiddenLayerClassName = 'scale-95 opacity-0 blur-xs';\n const visibleLayerClassName = 'scale-100 opacity-100 blur-none';\n const layerClassName =\n 'absolute inset-x-0 top-0 h-full origin-left transition-[opacity,filter,scale] duration-150 ease-in-out will-change-[opacity,filter,scale] motion-reduce:scale-100 motion-reduce:blur-none motion-reduce:transition-none';\n\n React.useLayoutEffect(() => {\n measurePreviewHeight();\n }, [currentTurn.key, phase, measurePreviewHeight]);\n\n return (\n <div\n id={id}\n data-testid=\"thread-rail-preview\"\n data-visible={containerVisible ? 'true' : undefined}\n className={cn(\n 'pointer-events-none absolute top-0 left-full z-30 ml-3 w-72 overflow-hidden rounded-xl border border-border1 bg-surface3 text-left shadow-dialog transition-[height,translate,opacity] duration-360 ease-out-custom will-change-[height,translate,opacity] motion-reduce:transition-none',\n containerVisible ? 'opacity-100' : 'opacity-0',\n )}\n style={{ ...previewHeightStyle, translate: `0 calc(${top}px - 50%)` }}\n >\n <div ref={previewSizerRef} data-testid=\"thread-rail-preview-sizer\" aria-hidden className=\"invisible\">\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n <div data-testid=\"thread-rail-preview-viewport\" className=\"absolute inset-0\">\n <div className=\"relative h-full\">\n {previousTurn && (\n <div\n key={previousTurn.key}\n data-testid=\"thread-rail-preview-previous\"\n aria-hidden\n className={cn(layerClassName, phase === 'entering' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={previousTurn} className=\"p-3.5\" />\n </div>\n )}\n <div\n key={currentTurn.key}\n data-testid=\"thread-rail-preview-current\"\n className={cn(layerClassName, phase === 'visible' ? visibleLayerClassName : hiddenLayerClassName)}\n >\n <ThreadRailPreviewContent turn={currentTurn} className=\"p-3.5\" />\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction ThreadRailPreviewContent({\n turn,\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement> & { turn: ThreadRailTurn }) {\n return (\n <div className={className} {...props}>\n <div className=\"text-ui-md leading-ui-md text-neutral6 truncate font-medium\">{turn.prompt}</div>\n {turn.reply && <p className=\"text-ui-sm leading-ui-sm text-neutral4 mt-1.5 line-clamp-3\">{turn.reply}</p>}\n {(turn.files.length > 0 || turn.hiddenFileCount > 0) && (\n <div className=\"border-border1/60 mt-3 flex flex-wrap items-center gap-2 border-t pt-2.5\">\n {turn.files.map(file => (\n <span key={file} className=\"text-ui-sm text-neutral4 inline-flex max-w-44 items-center gap-1.5 truncate\">\n <FileText className=\"size-3.5 shrink-0 opacity-70\" aria-hidden />\n {file}\n </span>\n ))}\n {turn.hiddenFileCount > 0 && (\n <span className=\"text-ui-sm text-neutral4 font-medium\">+{turn.hiddenFileCount}</span>\n )}\n </div>\n )}\n </div>\n );\n}\n","import type { MastraDBMessage } from '@mastra/core/agent/message-list';\nimport type { MastraDBMessageMetadata } from '@mastra/react';\n\nconst SUMMARY_MAX_LENGTH = 120;\nconst FILE_PREVIEW_LIMIT = 2;\n// Inlined, not imported: the value export sits behind a barrel this browser bundle must not pull.\nconst CLIENT_MESSAGE_ID_KEY = 'clientMessageId' satisfies keyof MastraDBMessageMetadata;\n\nexport interface ThreadRailTurn {\n key: string;\n messageId: string;\n prompt: string;\n reply?: string;\n files: string[];\n hiddenFileCount: number;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const getClientMessageKey = (message: MastraDBMessage): string => {\n const metadata = message.content.metadata;\n const clientMessageId = isRecord(metadata) ? metadata[CLIENT_MESSAGE_ID_KEY] : undefined;\n return typeof clientMessageId === 'string' && clientMessageId.length > 0 ? clientMessageId : message.id;\n};\n\nconst normalizeSummary = (value: string, fallback: string): string => {\n const normalized = value.replace(/\\s+/g, ' ').trim();\n if (normalized.length === 0) return fallback;\n if (normalized.length <= SUMMARY_MAX_LENGTH) return normalized;\n return `${normalized.slice(0, SUMMARY_MAX_LENGTH - 3).trimEnd()}...`;\n};\n\nconst getTextFromParts = (message: MastraDBMessage): string =>\n message.content.parts\n .flatMap(part => {\n if (!isRecord(part) || part.type !== 'text' || typeof part.text !== 'string') return [];\n return [part.text];\n })\n .join('\\n');\n\nconst getStringField = (part: Record<string, unknown>, keys: string[]): string | undefined => {\n for (const key of keys) {\n const value = part[key];\n if (typeof value === 'string' && value.trim().length > 0) return value;\n }\n return undefined;\n};\n\nconst getPathLabel = (value: string): string | undefined => {\n if (value.startsWith('data:')) return undefined;\n\n try {\n const url = new URL(value);\n const candidate = url.pathname.split('/').filter(Boolean).pop();\n return candidate || url.hostname || undefined;\n } catch {\n const candidate = value.split(/[?#]/)[0]?.split('/').filter(Boolean).pop();\n return candidate && !candidate.startsWith('data:') ? candidate : undefined;\n }\n};\n\nconst getFallbackFileLabel = (part: Record<string, unknown>): string => {\n const mediaType = getStringField(part, ['mimeType', 'mediaType']) ?? '';\n if (part.type === 'image' || mediaType.startsWith('image/')) return 'Image';\n if (mediaType === 'application/pdf') return 'PDF';\n if (mediaType.startsWith('video/')) return 'Video';\n if (mediaType.startsWith('audio/')) return 'Audio';\n return 'File';\n};\n\nconst getFileLabelFromPart = (part: MastraDBMessage['content']['parts'][number]): string | undefined => {\n if (!isRecord(part)) return undefined;\n\n const type = getStringField(part, ['type']);\n if (type !== 'file' && type !== 'image') return undefined;\n\n const explicitLabel = getStringField(part, ['filename', 'name']);\n if (explicitLabel) return explicitLabel;\n\n const source = getStringField(part, ['url', 'image', 'data']);\n const pathLabel = source ? getPathLabel(source) : undefined;\n return pathLabel ?? getFallbackFileLabel(part);\n};\n\nconst getFileLabels = (message: MastraDBMessage): string[] =>\n message.content.parts.map(getFileLabelFromPart).filter((label): label is string => Boolean(label));\n\nconst getSignalType = (message: MastraDBMessage): string | undefined => {\n const signal = message.content.metadata?.signal;\n const metadataType = isRecord(signal) ? signal.type : undefined;\n return typeof metadataType === 'string' ? metadataType : message.type;\n};\n\n/** What opens a turn: a rail stop, and the row the scroller parks at the top. */\nexport const startsUserTurn = (message: MastraDBMessage): boolean => {\n if (message.role === 'user') return true;\n if (message.role !== 'signal') return false;\n\n const signalType = getSignalType(message);\n return signalType === 'user' || signalType === 'user-message';\n};\n\nconst getNextAssistantReply = (messages: MastraDBMessage[], startIndex: number): string | undefined => {\n for (let index = startIndex + 1; index < messages.length; index += 1) {\n const message = messages[index];\n if (!message) continue;\n if (startsUserTurn(message)) return undefined;\n if (message.role !== 'assistant') continue;\n\n const reply = normalizeSummary(getTextFromParts(message), '');\n if (reply) return reply;\n }\n\n return undefined;\n};\n\nexport const buildThreadRailTurns = (messages: MastraDBMessage[]): ThreadRailTurn[] =>\n messages.flatMap((message, index) => {\n if (!startsUserTurn(message)) return [];\n\n const files = getFileLabels(message);\n const visibleFiles = files.slice(0, FILE_PREVIEW_LIMIT);\n\n return [\n {\n key: getClientMessageKey(message),\n messageId: message.id,\n prompt: normalizeSummary(getTextFromParts(message), files.length > 0 ? 'Attached file' : 'User message'),\n reply: getNextAssistantReply(messages, index),\n files: visibleFiles,\n hiddenFileCount: files.length - visibleFiles.length,\n },\n ];\n });\n"],"names":[],"mappings":"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"}
|