{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"agent-chat-transcript","title":"Agent Chat Transcript","description":"A component for displaying the agent session's chat transcript.","dependencies":["@livekit/components-react@^2.0.0","streamdown"],"registryDependencies":["message-scroller","message","bubble","marker","@agents-ui/agent-chat-indicator"],"files":[{"path":"components/agents-ui/agent-chat-transcript.tsx","content":"'use client';\n\nimport { type ComponentProps } from 'react';\nimport { type AgentState, type ReceivedMessage } from '@livekit/components-react';\nimport { Streamdown } from 'streamdown';\nimport { Bubble, BubbleContent } from '@/components/ui/bubble';\nimport { Message, MessageContent } from '@/components/ui/message';\nimport { Marker, MarkerContent, MarkerIcon } from '@/components/ui/marker';\nimport {\n  MessageScroller,\n  MessageScrollerButton,\n  MessageScrollerContent,\n  MessageScrollerItem,\n  MessageScrollerProvider,\n  MessageScrollerViewport,\n} from '@/components/ui/message-scroller';\nimport { AgentChatIndicator } from '@/components/agents-ui/agent-chat-indicator';\n\n/**\n * Props for the AgentChatTranscript component.\n */\nexport interface AgentChatTranscriptProps\n  extends\n    ComponentProps<'div'>,\n    ComponentProps<typeof MessageScrollerProvider>,\n    ComponentProps<typeof MessageScrollerViewport>,\n    ComponentProps<typeof MessageScrollerContent> {\n  /**\n   * Whether to automatically scroll to the bottom of the transcript when new messages are added.\n   * @defaultValue true\n   */\n  autoScroll?: boolean;\n  /**\n   * The scroll anchor to use when auto-scrolling.\n   * @defaultValue false\n   */\n  scrollAnchor?: boolean | 'user' | 'other' | 'any';\n  /**\n   * The scroll button render function\n   */\n  scrollButtonRender?: ComponentProps<typeof MessageScrollerButton>['render'];\n  /**\n   * The scroll button behavior\n   */\n  scrollButtonBehavior?: ComponentProps<typeof MessageScrollerButton>['behavior'];\n  /**\n   * The scroll button direction\n   */\n  scrollButtonDirection?: ComponentProps<typeof MessageScrollerButton>['direction'];\n  /**\n   * The current state of the agent. When 'thinking', displays a loading indicator.\n   */\n  agentState?: AgentState;\n  /**\n   * Array of messages to display in the transcript.\n   * @defaultValue []\n   */\n  messages?: ReceivedMessage[];\n  /**\n   * Additional CSS class names to apply to the conversation container.\n   */\n  className?: string;\n}\n\n/**\n * A chat transcript component that displays a conversation between the user and agent.\n * Shows messages with timestamps and origin indicators, plus a thinking indicator\n * when the agent is processing.\n *\n * @extends ComponentProps<'div'>, ComponentProps<typeof MessageScrollerProvider>, ComponentProps<typeof MessageScrollerViewport>, ComponentProps<typeof MessageScrollerContent>\n *\n *\n * @example\n * ```tsx\n * <AgentChatTranscript\n *   agentState={agentState}\n *   messages={chatMessages}\n * />\n * ```\n */\nexport function AgentChatTranscript({\n  scrollAnchor,\n  autoScroll = true,\n  scrollMargin,\n  scrollEdgeThreshold,\n  preserveScrollOnPrepend,\n  scrollPreviousItemPeek = 20,\n  defaultScrollPosition = 'last-anchor',\n  scrollButtonRender,\n  scrollButtonBehavior,\n  scrollButtonDirection,\n  spacerClassName,\n  agentState,\n  messages = [],\n  className,\n  ...props\n}: AgentChatTranscriptProps) {\n  return (\n    <MessageScrollerProvider\n      autoScroll={autoScroll}\n      scrollMargin={scrollMargin}\n      defaultScrollPosition={defaultScrollPosition}\n      scrollEdgeThreshold={scrollEdgeThreshold}\n      scrollPreviousItemPeek={scrollPreviousItemPeek}\n    >\n      <MessageScroller className={className} {...props}>\n        <MessageScrollerViewport preserveScrollOnPrepend={preserveScrollOnPrepend}>\n          <MessageScrollerContent\n            spacerClassName={spacerClassName}\n            aria-busy={agentState === 'thinking'}\n          >\n            {messages.map((receivedMessage) => {\n              const { id, timestamp, from, message } = receivedMessage;\n              const time = new Date(timestamp);\n              const isUser = from?.isLocal;\n              const locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US';\n              const title = time.toLocaleTimeString(locale, { timeStyle: 'full' });\n              let _scrollAnchor = false;\n\n              if (\n                scrollAnchor === 'any' ||\n                (scrollAnchor === 'user' && isUser) ||\n                (scrollAnchor === 'other' && !isUser)\n              ) {\n                _scrollAnchor = true;\n              }\n\n              return (\n                <MessageScrollerItem key={id} messageId={id} scrollAnchor={_scrollAnchor}>\n                  <Message align={isUser ? 'end' : 'start'} title={title}>\n                    <MessageContent>\n                      <Bubble\n                        align={isUser ? 'end' : 'start'}\n                        variant={isUser ? 'secondary' : 'ghost'}\n                      >\n                        <BubbleContent>\n                          <Streamdown>{message}</Streamdown>\n                        </BubbleContent>\n                      </Bubble>\n                    </MessageContent>\n                  </Message>\n                </MessageScrollerItem>\n              );\n            })}\n\n            {/* Agent is thinking indicator */}\n            {agentState === 'thinking' && (\n              <MessageScrollerItem>\n                <Marker role=\"status\">\n                  <MarkerIcon>\n                    <AgentChatIndicator size=\"sm\" />\n                  </MarkerIcon>\n                  <MarkerContent className=\"shimmer\">Thinking...</MarkerContent>\n                </Marker>\n              </MessageScrollerItem>\n            )}\n          </MessageScrollerContent>\n        </MessageScrollerViewport>\n\n        {/* Scroll to bottom button */}\n        <MessageScrollerButton\n          variant=\"outline\"\n          className=\"rounded-full\"\n          render={scrollButtonRender}\n          behavior={scrollButtonBehavior}\n          direction={scrollButtonDirection}\n        />\n      </MessageScroller>\n    </MessageScrollerProvider>\n  );\n}\n","type":"registry:component"}],"type":"registry:component"}