@nextclaw/agent-chat-ui 0.4.7 → 0.4.9-beta.0
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/dist/index.js +46 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["DefaultPopover","DefaultPopoverAnchor","DefaultPopoverContent","DefaultPopoverTrigger","DefaultInput","DefaultSelect","DefaultSelectContent","DefaultSelectGroup","DefaultSelectItem","DefaultSelectLabel","DefaultSelectSeparator","DefaultSelectTrigger","DefaultSelectValue","DefaultTooltip","DefaultTooltipContent","DefaultTooltipProvider","DefaultTooltipTrigger"],"sources":["../src/components/chat/hooks/use-active-item-scroll.ts","../src/components/chat/hooks/use-element-width.ts","../src/components/chat/internal/cn.ts","../src/components/chat/default-skin/input.tsx","../src/components/chat/default-skin/popover.tsx","../src/components/chat/default-skin/select.tsx","../src/components/chat/default-skin/tooltip.tsx","../src/components/chat/ui/primitives/chat-ui-primitives.tsx","../src/components/chat/ui/chat-input-bar/chat-slash-menu.tsx","../src/components/chat/default-skin/button.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-actions.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-skill-picker.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-toolbar.tsx","../src/components/chat/ui/chat-input-bar/chat-composer.utils.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-token-node.tsx","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-editor-state.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-operations.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-controller.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-plugins.tsx","../src/components/chat/ui/chat-input-bar/lexical/chat-input-bar-tokenized-composer.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar.tsx","../src/components/chat/ui/chat-message-list/chat-message-avatar.tsx","../src/components/chat/utils/copy-text.ts","../src/components/chat/hooks/use-copy-feedback.ts","../src/components/chat/ui/chat-message-list/code-block/chat-code-syntax-highlighter.ts","../src/components/chat/ui/chat-message-list/chat-code-block.tsx","../src/components/chat/ui/chat-message-list/chat-message-markdown.tsx","../src/components/chat/ui/chat-message-list/chat-message-inline-content.tsx","../src/components/chat/ui/chat-message-list/chat-message-file/meta.ts","../src/components/chat/ui/chat-message-list/chat-message-file/index.tsx","../src/components/chat/hooks/use-reasoning-block-open-state.ts","../src/components/chat/hooks/use-sticky-bottom-scroll.ts","../src/components/chat/ui/chat-message-list/chat-reasoning-block.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-root.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-status.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-header.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation-lines.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx","../src/components/chat/ui/chat-message-list/chat-tool-card.tsx","../src/components/chat/ui/chat-message-list/chat-unknown-part.tsx","../src/components/chat/ui/chat-message-list/chat-message.tsx","../src/components/chat/ui/chat-message-list/chat-message-meta.tsx","../src/components/chat/ui/chat-message-list/chat-message-action-copy.tsx","../src/components/chat/ui/chat-message-list/chat-message-list.tsx"],"sourcesContent":["import { useEffect, type RefObject } from 'react';\n\ntype UseActiveItemScrollParams = {\n containerRef: RefObject<HTMLElement>;\n activeIndex: number;\n itemCount: number;\n isEnabled: boolean;\n getItemSelector?: (index: number) => string;\n};\n\nconst defaultGetItemSelector = (index: number) => `[data-item-index=\"${index}\"]`;\n\nexport function useActiveItemScroll(params: UseActiveItemScrollParams) {\n const { activeIndex, containerRef, getItemSelector: customGetItemSelector, isEnabled, itemCount } =\n params;\n const getItemSelector = customGetItemSelector ?? defaultGetItemSelector;\n\n useEffect(() => {\n if (!isEnabled || itemCount === 0) {\n return;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const activeItem = container.querySelector<HTMLElement>(getItemSelector(activeIndex));\n if (typeof activeItem?.scrollIntoView === 'function') {\n activeItem.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n }, [activeIndex, containerRef, getItemSelector, isEnabled, itemCount]);\n}\n","import { useEffect, useRef, useState, type RefObject } from 'react';\n\ntype UseElementWidthResult<T extends HTMLElement> = {\n elementRef: RefObject<T>;\n width: number | null;\n};\n\nexport function useElementWidth<T extends HTMLElement>(): UseElementWidthResult<T> {\n const elementRef = useRef<T | null>(null);\n const [width, setWidth] = useState<number | null>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n const updateWidth = () => {\n setWidth(element.getBoundingClientRect().width);\n };\n\n updateWidth();\n\n const observer = new ResizeObserver(() => updateWidth());\n observer.observe(element);\n\n return () => observer.disconnect();\n }, []);\n\n return {\n elementRef,\n width\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport { cn } from '../internal/cn';\n\nexport type ChatInputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst ChatInput = React.forwardRef<HTMLInputElement, ChatInputProps>(({ className, type, ...props }, ref) => (\n <input\n type={type}\n className={cn(\n 'flex h-9 w-full rounded-xl border border-gray-200/80 bg-white px-3.5 py-2 text-sm text-gray-900 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-gray-300 placeholder:font-normal focus:outline-none focus:ring-1 focus:ring-primary/40 focus:border-primary/40 transition-colors disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n));\n\nChatInput.displayName = 'ChatInput';\n\nexport { ChatInput };\n","import * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '../internal/cn';\n\nconst ChatPopover = PopoverPrimitive.Root;\nconst ChatPopoverTrigger = PopoverPrimitive.Trigger;\nconst ChatPopoverAnchor = PopoverPrimitive.Anchor;\n\nconst ChatPopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, sideOffset = 8, align = 'start', ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n align={align}\n className={cn(\n 'z-[var(--z-popover,50)] w-72 overflow-hidden rounded-2xl border border-gray-200/50 bg-white p-4 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\n\nChatPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { ChatPopover, ChatPopoverTrigger, ChatPopoverContent, ChatPopoverAnchor };\n","import * as React from 'react';\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react';\nimport { cn } from '../internal/cn';\n\nconst ChatSelect = SelectPrimitive.Root;\nconst ChatSelectGroup = SelectPrimitive.Group;\nconst ChatSelectValue = SelectPrimitive.Value;\n\nconst ChatSelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-gray-200/80 bg-white px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\n\nChatSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst ChatSelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton ref={ref} className={cn('flex cursor-default items-center justify-center py-1', className)} {...props}>\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\n\nChatSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst ChatSelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton ref={ref} className={cn('flex cursor-default items-center justify-center py-1', className)} {...props}>\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\n\nChatSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst ChatSelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md bg-white text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <ChatSelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn('p-1', position === 'popper' && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]')}\n >\n {children}\n </SelectPrimitive.Viewport>\n <ChatSelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nChatSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst ChatSelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label ref={ref} className={cn('px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-gray-500', className)} {...props} />\n));\n\nChatSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst ChatSelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-gray-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-gray-100',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\n\nChatSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst ChatSelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('-mx-1 my-1 h-px bg-gray-100', className)} {...props} />\n));\n\nChatSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n ChatSelect,\n ChatSelectContent,\n ChatSelectGroup,\n ChatSelectItem,\n ChatSelectLabel,\n ChatSelectSeparator,\n ChatSelectTrigger,\n ChatSelectValue\n};\n","import * as React from 'react';\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport { cn } from '../internal/cn';\n\nconst ChatTooltipProvider = TooltipPrimitive.Provider;\nconst ChatTooltip = TooltipPrimitive.Root;\nconst ChatTooltipTrigger = TooltipPrimitive.Trigger;\n\nconst ChatTooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-[var(--z-tooltip)] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n));\n\nChatTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { ChatTooltip, ChatTooltipTrigger, ChatTooltipContent, ChatTooltipProvider };\n","import { ChatInput as DefaultInput } from '../../default-skin/input';\nimport {\n ChatPopover as DefaultPopover,\n ChatPopoverAnchor as DefaultPopoverAnchor,\n ChatPopoverContent as DefaultPopoverContent,\n ChatPopoverTrigger as DefaultPopoverTrigger\n} from '../../default-skin/popover';\nimport {\n ChatSelect as DefaultSelect,\n ChatSelectContent as DefaultSelectContent,\n ChatSelectGroup as DefaultSelectGroup,\n ChatSelectItem as DefaultSelectItem,\n ChatSelectLabel as DefaultSelectLabel,\n ChatSelectSeparator as DefaultSelectSeparator,\n ChatSelectTrigger as DefaultSelectTrigger,\n ChatSelectValue as DefaultSelectValue\n} from '../../default-skin/select';\nimport {\n ChatTooltip as DefaultTooltip,\n ChatTooltipContent as DefaultTooltipContent,\n ChatTooltipProvider as DefaultTooltipProvider,\n ChatTooltipTrigger as DefaultTooltipTrigger\n} from '../../default-skin/tooltip';\n\n// Centralized primitive adapter layer for chat UI.\nexport const ChatUiPrimitives = {\n Popover: DefaultPopover,\n PopoverAnchor: DefaultPopoverAnchor,\n PopoverContent: DefaultPopoverContent,\n PopoverTrigger: DefaultPopoverTrigger,\n Input: DefaultInput,\n Select: DefaultSelect,\n SelectContent: DefaultSelectContent,\n SelectGroup: DefaultSelectGroup,\n SelectItem: DefaultSelectItem,\n SelectLabel: DefaultSelectLabel,\n SelectSeparator: DefaultSelectSeparator,\n SelectTrigger: DefaultSelectTrigger,\n SelectValue: DefaultSelectValue,\n Tooltip: DefaultTooltip,\n TooltipContent: DefaultTooltipContent,\n TooltipProvider: DefaultTooltipProvider,\n TooltipTrigger: DefaultTooltipTrigger\n};\n","import { useMemo, useRef } from 'react';\nimport { useActiveItemScroll } from '../../hooks/use-active-item-scroll';\nimport { useElementWidth } from '../../hooks/use-element-width';\nimport { ChatUiPrimitives } from '../primitives/chat-ui-primitives';\nimport type { ChatSlashMenuProps } from '../../view-models/chat-ui.types';\n\nconst SLASH_PANEL_MAX_WIDTH = 680;\nconst SLASH_PANEL_DESKTOP_SHRINK_RATIO = 0.82;\nconst SLASH_PANEL_DESKTOP_MIN_WIDTH = 560;\n\nexport function ChatSlashMenu(props: ChatSlashMenuProps) {\n const { Popover, PopoverAnchor, PopoverContent } = ChatUiPrimitives;\n const { elementRef: anchorRef, width: panelWidth } = useElementWidth<HTMLDivElement>();\n const listRef = useRef<HTMLDivElement | null>(null);\n const {\n isOpen,\n isLoading,\n items,\n activeIndex,\n activeItem,\n texts,\n onSelectItem,\n onOpenChange,\n onDetailsPointerDown,\n onSetActiveIndex\n } = props;\n\n const resolvedWidth = useMemo(() => {\n if (!panelWidth) {\n return undefined;\n }\n return Math.min(\n panelWidth > SLASH_PANEL_DESKTOP_MIN_WIDTH ? panelWidth * SLASH_PANEL_DESKTOP_SHRINK_RATIO : panelWidth,\n SLASH_PANEL_MAX_WIDTH\n );\n }, [panelWidth]);\n\n useActiveItemScroll({\n containerRef: listRef,\n activeIndex,\n itemCount: items.length,\n isEnabled: isOpen && !isLoading,\n getItemSelector: (index) => `[data-slash-index=\"${index}\"]`\n });\n\n return (\n <Popover open={isOpen} onOpenChange={onOpenChange}>\n <PopoverAnchor asChild>\n <div ref={anchorRef} className=\"pointer-events-none absolute bottom-full left-3 right-3 h-0\" />\n </PopoverAnchor>\n <PopoverContent\n side=\"top\"\n align=\"start\"\n sideOffset={10}\n className=\"z-[70] max-w-[calc(100vw-1.5rem)] overflow-hidden rounded-2xl border border-gray-200 bg-white/95 p-0 shadow-2xl backdrop-blur-md\"\n onOpenAutoFocus={(event) => event.preventDefault()}\n style={resolvedWidth ? { width: `${resolvedWidth}px` } : undefined}\n >\n <div className=\"grid min-h-[240px] grid-cols-[minmax(220px,300px)_minmax(0,1fr)]\">\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label={texts.slashSectionLabel}\n className=\"custom-scrollbar max-h-[320px] overflow-y-auto border-r border-gray-200 p-2.5\"\n >\n {isLoading ? (\n <div className=\"p-2 text-xs text-gray-500\">{texts.slashLoadingLabel}</div>\n ) : (\n <>\n <div className=\"mb-2 px-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500\">\n {texts.slashSectionLabel}\n </div>\n {items.length === 0 ? (\n <div className=\"px-2 text-xs text-gray-400\">{texts.slashEmptyLabel}</div>\n ) : (\n <div className=\"space-y-1\">\n {items.map((item, index) => {\n const isActive = index === activeIndex;\n return (\n <button\n key={item.key}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-slash-index={index}\n onMouseEnter={() => onSetActiveIndex(index)}\n onClick={() => onSelectItem(item)}\n className={`flex w-full items-start gap-2 rounded-lg px-2 py-1.5 text-left transition ${\n isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-700 hover:bg-gray-50'\n }`}\n >\n <span className=\"truncate text-xs font-semibold\">{item.title}</span>\n <span className=\"truncate text-xs text-gray-500\">{item.subtitle}</span>\n </button>\n );\n })}\n </div>\n )}\n </>\n )}\n </div>\n <div className=\"min-w-0 p-2.5\" onPointerDown={onDetailsPointerDown}>\n {activeItem ? (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <span className=\"inline-flex rounded-full bg-primary/10 px-2 py-0.5 text-[11px] font-semibold text-primary\">\n {activeItem.subtitle}\n </span>\n <span className=\"text-sm font-semibold text-gray-900\">{activeItem.title}</span>\n </div>\n <p className=\"text-xs leading-5 text-gray-600\">{activeItem.description}</p>\n <div className=\"space-y-1\">\n {activeItem.detailLines.map((line) => (\n <div\n key={line}\n className=\"min-w-0 break-all rounded-md bg-gray-50 px-2 py-1 text-[11px] leading-5 text-gray-600\"\n >\n {line}\n </div>\n ))}\n </div>\n <div className=\"pt-1 text-[11px] text-gray-500\">{texts.slashSkillHintLabel}</div>\n </div>\n ) : (\n <div className=\"text-xs text-gray-500\">{texts.slashHintLabel}</div>\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../internal/cn';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-full text-sm font-medium ring-offset-background transition-all duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-gray-200 bg-white hover:bg-gray-50 hover:text-gray-800 text-gray-600',\n secondary: 'bg-gray-100 text-gray-700 hover:bg-gray-200/80',\n ghost: 'hover:bg-gray-100/80 hover:text-gray-800',\n link: 'text-primary underline-offset-4 hover:underline',\n primary: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',\n subtle: 'bg-gray-100 text-gray-600 hover:bg-gray-200/80',\n 'primary-outline': 'border border-primary/30 text-primary hover:bg-primary hover:text-primary-foreground'\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-11 px-5 text-[14px]',\n xl: 'h-12 px-6 text-[15px]',\n icon: 'h-9 w-9'\n }\n },\n defaultVariants: {\n variant: 'default',\n size: 'default'\n }\n }\n);\n\nexport interface ChatButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst ChatButton = React.forwardRef<HTMLButtonElement, ChatButtonProps>(\n ({ className, variant, size, ...props }, ref) => (\n <button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />\n )\n);\n\nChatButton.displayName = 'ChatButton';\n\nexport { ChatButton, buttonVariants };\n","import { ChatButton } from '../../default-skin/button';\nimport { ChatUiPrimitives } from '../primitives/chat-ui-primitives';\nimport type { ChatContextWindowIndicator, ChatInputBarActionsProps } from '../../view-models/chat-ui.types';\nimport { ArrowUp } from 'lucide-react';\n\nconst SEND_ERROR_PREVIEW_MAX_CHARS = 120;\n\nfunction buildSendErrorPreview(value: string): string {\n const compact = value.replace(/\\s+/g, ' ').trim();\n if (compact.length <= SEND_ERROR_PREVIEW_MAX_CHARS) {\n return compact;\n }\n return `${compact.slice(0, SEND_ERROR_PREVIEW_MAX_CHARS - 1)}…`;\n}\n\nfunction StopIcon() {\n return (\n <span\n aria-hidden=\"true\"\n data-testid=\"chat-stop-icon\"\n className=\"block h-3 w-3 rounded-[2px] bg-gray-700 shadow-[inset_0_0_0_1px_rgba(17,24,39,0.06)]\"\n />\n );\n}\n\nfunction ContextWindowIndicator({ contextWindow }: { contextWindow: ChatContextWindowIndicator }) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;\n const clampedRatio = Math.max(0, Math.min(1, contextWindow.ratio));\n const angle = Math.round(clampedRatio * 360);\n const ringColor = '#9ca3af';\n\n return (\n <TooltipProvider delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700\"\n aria-label={contextWindow.label}\n title={contextWindow.label}\n >\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-[7px] rounded-full\"\n style={{ background: `conic-gradient(${ringColor} ${angle}deg, #e5e7eb 0deg)` }}\n />\n <span aria-hidden=\"true\" className=\"absolute inset-[10px] rounded-full bg-white\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[18rem]\">\n <div className=\"space-y-1.5 text-xs\">\n <div className=\"flex items-center justify-between gap-5 font-semibold text-gray-800\">\n <span>{contextWindow.label}</span>\n <span>{contextWindow.percentLabel}</span>\n </div>\n {contextWindow.details.map((detail) => (\n <div key={detail.label} className=\"flex items-center justify-between gap-5 text-gray-600\">\n <span>{detail.label}</span>\n <span className=\"font-medium text-gray-800\">{detail.value}</span>\n </div>\n ))}\n </div>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\nexport function ChatInputBarActions({\n sendError,\n sendErrorDetailsLabel,\n isSending,\n canStopGeneration,\n sendDisabled,\n stopDisabled,\n stopHint,\n sendButtonLabel,\n stopButtonLabel,\n contextWindow,\n onSend,\n onStop\n}: ChatInputBarActionsProps) {\n const {\n Popover,\n PopoverContent,\n PopoverTrigger,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger\n } = ChatUiPrimitives;\n const normalizedSendError = sendError?.trim() ?? '';\n const sendErrorPreview = normalizedSendError\n ? buildSendErrorPreview(normalizedSendError)\n : '';\n const resolvedSendErrorDetailsLabel = sendErrorDetailsLabel?.trim() || 'Details';\n\n return (\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {normalizedSendError ? (\n <div className=\"flex max-w-[420px] items-start justify-end gap-2 text-right\">\n <div className=\"min-w-0 flex-1 text-[11px] text-red-600\">\n <span\n className=\"block truncate\"\n title={normalizedSendError}\n >\n {sendErrorPreview}\n </span>\n </div>\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"shrink-0 rounded-full border border-red-200/80 bg-red-50 px-2 py-0.5 text-[10px] font-semibold text-red-700 transition-colors hover:bg-red-100\"\n >\n {resolvedSendErrorDetailsLabel}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"w-[min(32rem,calc(100vw-1.5rem))] border-red-100/80 p-0\"\n >\n <div className=\"border-b border-red-100 bg-red-50/80 px-4 py-2 text-xs font-semibold text-red-700\">\n {resolvedSendErrorDetailsLabel}\n </div>\n <pre className=\"max-h-80 overflow-auto whitespace-pre-wrap break-words px-4 py-3 text-xs leading-relaxed text-red-700\">\n {normalizedSendError}\n </pre>\n </PopoverContent>\n </Popover>\n </div>\n ) : null}\n <div className=\"flex items-center gap-2\">\n {contextWindow ? <ContextWindowIndicator contextWindow={contextWindow} /> : null}\n {isSending ? (\n canStopGeneration ? (\n <ChatButton\n size=\"icon\"\n variant=\"outline\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={stopButtonLabel}\n onClick={() => void onStop()}\n disabled={stopDisabled}\n >\n <StopIcon />\n </ChatButton>\n ) : (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <span>\n <ChatButton\n size=\"icon\"\n variant=\"outline\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={stopButtonLabel}\n disabled\n >\n <StopIcon />\n </ChatButton>\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n <p className=\"text-xs\">{stopHint}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n ) : (\n <ChatButton\n size=\"icon\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={sendButtonLabel}\n onClick={() => void onSend()}\n disabled={sendDisabled}\n >\n <ArrowUp className=\"h-5 w-5\" />\n </ChatButton>\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useId, useMemo, useRef, useState, type KeyboardEventHandler } from 'react';\nimport { BrainCircuit, Check, ExternalLink, Puzzle, Search } from 'lucide-react';\nimport { useActiveItemScroll } from '@agent-chat-ui/components/chat/hooks/use-active-item-scroll';\nimport { ChatUiPrimitives } from '@agent-chat-ui/components/chat/ui/primitives/chat-ui-primitives';\nimport type { ChatSkillPickerOption, ChatSkillPickerOptionGroup, ChatSkillPickerProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\n\nfunction filterOptions(options: ChatSkillPickerOption[], query: string): ChatSkillPickerOption[] {\n const keyword = query.trim().toLowerCase();\n if (!keyword) {\n return options;\n }\n return options.filter((option) => {\n const haystack = [option.label, option.key, option.description]\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n .join(' ')\n .toLowerCase();\n return haystack.includes(keyword);\n });\n}\n\nexport function ChatInputBarSkillPicker(props: { picker: ChatSkillPickerProps }) {\n const { Input, Popover, PopoverContent, PopoverTrigger } = ChatUiPrimitives;\n const { picker } = props;\n const listRef = useRef<HTMLDivElement | null>(null);\n const listId = useId();\n const [query, setQuery] = useState('');\n const [activeIndex, setActiveIndex] = useState(0);\n const selectedSet = useMemo(() => new Set(picker.selectedKeys), [picker.selectedKeys]);\n const selectedCount = picker.selectedKeys.length;\n const isSearchActive = query.trim().length > 0;\n const groupedOptions = useMemo<ChatSkillPickerOptionGroup[] | null>(() => {\n if (isSearchActive) {\n return null;\n }\n const groups = picker.groups?.filter((group) => group.options.length > 0) ?? [];\n return groups.length > 0 ? groups : null;\n }, [isSearchActive, picker.groups]);\n const visibleOptions = useMemo(() => {\n if (groupedOptions) {\n return groupedOptions.flatMap((group) => group.options);\n }\n return filterOptions(picker.options, query);\n }, [groupedOptions, picker.options, query]);\n\n useEffect(() => {\n setActiveIndex(0);\n }, [query]);\n\n useEffect(() => {\n setActiveIndex((current) => {\n if (visibleOptions.length === 0) {\n return 0;\n }\n return Math.min(current, visibleOptions.length - 1);\n });\n }, [visibleOptions.length]);\n\n useActiveItemScroll({\n containerRef: listRef,\n activeIndex,\n itemCount: visibleOptions.length,\n isEnabled: visibleOptions.length > 0,\n getItemSelector: (index) => `[data-skill-index=\"${index}\"]`\n });\n\n const onToggleOption = (optionKey: string) => {\n if (selectedSet.has(optionKey)) {\n picker.onSelectedKeysChange(picker.selectedKeys.filter((item) => item !== optionKey));\n return;\n }\n picker.onSelectedKeysChange([...picker.selectedKeys, optionKey]);\n };\n\n const onSearchKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {\n if (visibleOptions.length === 0) {\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setActiveIndex((current) => Math.min(current + 1, visibleOptions.length - 1));\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n setActiveIndex((current) => Math.max(current - 1, 0));\n return;\n }\n\n if (event.key === 'Enter') {\n event.preventDefault();\n const activeOption = visibleOptions[activeIndex];\n if (activeOption) {\n onToggleOption(activeOption.key);\n }\n }\n };\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-label={picker.title}\n className=\"relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg px-0 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 sm:w-auto sm:gap-1.5 sm:px-3\"\n >\n <BrainCircuit className=\"h-4 w-4\" />\n <span className=\"nextclaw-chat-skill-picker-label hidden sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{picker.title}</span>\n {selectedCount > 0 ? (\n <span className=\"absolute -right-1 -top-1 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1 text-[10px] font-semibold leading-none text-white shadow-sm sm:static sm:ml-0.5 sm:bg-primary/10 sm:text-primary sm:shadow-none\">\n {selectedCount}\n </span>\n ) : null}\n </button>\n </PopoverTrigger>\n <PopoverContent side=\"top\" align=\"start\" className=\"w-[360px] p-0\">\n <div className=\"space-y-2 border-b border-gray-100 px-4 py-3\">\n <div className=\"text-sm font-semibold text-gray-900\">{picker.title}</div>\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-3 top-2.5 h-3.5 w-3.5 text-gray-400\" />\n <Input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onSearchKeyDown}\n placeholder={picker.searchPlaceholder}\n role=\"combobox\"\n aria-controls={listId}\n aria-expanded=\"true\"\n aria-autocomplete=\"list\"\n aria-activedescendant={visibleOptions[activeIndex] ? `${listId}-option-${activeIndex}` : undefined}\n className=\"h-8 rounded-lg pl-8 text-xs\"\n />\n </div>\n </div>\n\n <div\n ref={listRef}\n id={listId}\n role=\"listbox\"\n aria-multiselectable=\"true\"\n className=\"custom-scrollbar max-h-[320px] overflow-y-auto\"\n >\n {picker.isLoading ? (\n <div className=\"p-4 text-xs text-gray-500\">{picker.loadingLabel}</div>\n ) : visibleOptions.length === 0 ? (\n <div className=\"p-4 text-center text-xs text-gray-500\">{picker.emptyLabel}</div>\n ) : (\n <div className=\"py-1\">\n {(() => {\n const groups = groupedOptions ?? [{ key: 'all-skills', options: visibleOptions }];\n let visibleIndex = 0;\n return groups.map((group) => (\n <div key={group.key}>\n {group.label ? (\n <div className=\"px-4 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500\">\n {group.label}\n </div>\n ) : null}\n {group.options.map((option) => {\n const index = visibleIndex;\n visibleIndex += 1;\n const isSelected = selectedSet.has(option.key);\n const isActive = index === activeIndex;\n return (\n <div\n key={option.key}\n id={`${listId}-option-${index}`}\n role=\"option\"\n aria-selected={isSelected}\n data-skill-index={index}\n onMouseEnter={() => setActiveIndex(index)}\n className={`flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${\n isActive ? 'bg-gray-50' : 'hover:bg-gray-50'\n }`}\n >\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 text-gray-500\">\n <Puzzle className=\"h-4 w-4\" />\n </div>\n <div className=\"min-w-0 flex-1 select-text\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"truncate text-sm text-gray-900\">{option.label}</span>\n {option.badgeLabel ? (\n <span className=\"shrink-0 rounded-full bg-primary/10 px-1.5 py-0.5 text-[10px] font-medium text-primary\">\n {option.badgeLabel}\n </span>\n ) : null}\n </div>\n <div className=\"mt-0.5 truncate text-xs text-gray-500\">{option.description || option.key}</div>\n </div>\n <div className=\"ml-3 shrink-0\">\n <button\n type=\"button\"\n aria-label={`${isSelected ? 'Remove' : 'Add'} ${option.label}`}\n onClick={() => onToggleOption(option.key)}\n className={\n isSelected\n ? 'inline-flex h-5 w-5 items-center justify-center rounded-full bg-primary text-white'\n : 'inline-flex h-5 w-5 items-center justify-center rounded-full border border-gray-300 bg-white'\n }\n >\n {isSelected ? <Check className=\"h-3 w-3\" /> : null}\n </button>\n </div>\n </div>\n );\n })}\n </div>\n ));\n })()}\n </div>\n )}\n </div>\n\n {picker.manageHref && picker.manageLabel ? (\n <div className=\"border-t border-gray-100 px-4 py-2.5\">\n <a\n href={picker.manageHref}\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-colors hover:text-primary/80\"\n >\n {picker.manageLabel}\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n}\n","import { ChatUiPrimitives } from '@agent-chat-ui/components/chat/ui/primitives/chat-ui-primitives';\nimport type {\n ChatInputBarToolbarProps,\n ChatToolbarAccessoryIcon,\n ChatToolbarIcon,\n ChatToolbarSelect\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { Brain, Paperclip, Sparkles } from 'lucide-react';\nimport { ChatInputBarActions } from './chat-input-bar-actions';\nimport { ChatInputBarSkillPicker } from './chat-input-bar-skill-picker';\n\nfunction ToolbarIcon({ icon }: { icon?: ChatToolbarIcon }) {\n return icon === 'sparkles'\n ? <Sparkles className=\"h-3.5 w-3.5 shrink-0 text-primary\" />\n : icon === 'brain'\n ? <Brain className=\"h-3.5 w-3.5 shrink-0 text-gray-500\" />\n : null;\n}\n\nfunction AccessoryIcon({ icon }: { icon?: ChatToolbarAccessoryIcon }) {\n return icon === 'paperclip' ? <Paperclip className=\"h-4 w-4\" /> : <ToolbarIcon icon={icon} />;\n}\n\nconst TRIGGER_WIDTH_BY_KEY: Record<string, string> = {\n model: 'min-w-0 max-w-full flex-1 basis-[12rem] sm:max-w-[320px]',\n 'session-type': 'shrink-0',\n thinking: 'shrink-0'\n};\n\nconst CONTENT_WIDTH_BY_KEY: Record<string, string> = {\n model: 'w-[min(18rem,calc(100vw-1rem))] sm:w-[320px]',\n 'session-type': 'w-[220px]',\n thinking: 'w-[180px]'\n};\n\nfunction resolveMobileSelectedLabel(item: ChatToolbarSelect): string | undefined {\n return item.key === 'model' && item.selectedLabel\n ? item.selectedLabel.split('/').slice(1).join('/').trim() || item.selectedLabel\n : item.selectedLabel;\n}\n\nfunction ToolbarSelect({ item }: { item: ChatToolbarSelect }) {\n const { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } =\n ChatUiPrimitives;\n const groups =\n item.groups?.filter((group) => group.options.length > 0) ??\n (item.options.length > 0 ? [{ key: `${item.key}-default`, options: item.options }] : []);\n const hasOptions = groups.some((group) => group.options.length > 0);\n const mobileSelectedLabel = resolveMobileSelectedLabel(item);\n\n return (\n <Select value={item.value} onValueChange={item.onValueChange} disabled={item.disabled}>\n <SelectTrigger\n aria-label={item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder}\n title={item.selectedLabel}\n className={`nextclaw-chat-toolbar-select-trigger h-8 w-auto rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-gray-600 shadow-none hover:bg-gray-100 focus:ring-0 sm:px-3 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!basis-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!justify-center [@container_nextclaw-chat-input-bar_(max-width:440px)]:!max-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!min-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!px-0 ${TRIGGER_WIDTH_BY_KEY[item.key] ?? ''}`}\n >\n {item.selectedLabel ? (\n <div className=\"flex min-w-0 items-center gap-2 text-left\">\n <ToolbarIcon icon={item.icon} />\n <span className=\"nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-gray-700 sm:hidden [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{mobileSelectedLabel}</span>\n <span className=\"nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-gray-700 sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{item.selectedLabel}</span>\n </div>\n ) : item.loading ? (\n <div className=\"h-3 w-24 animate-pulse rounded bg-gray-200\" />\n ) : (\n <SelectValue placeholder={item.placeholder} />\n )}\n </SelectTrigger>\n <SelectContent className={CONTENT_WIDTH_BY_KEY[item.key] ?? ''}>\n {!hasOptions ? (\n item.loading ? (\n <div className=\"space-y-2 px-3 py-2\">\n <div className=\"h-3 w-36 animate-pulse rounded bg-gray-200\" />\n <div className=\"h-3 w-28 animate-pulse rounded bg-gray-200\" />\n <div className=\"h-3 w-32 animate-pulse rounded bg-gray-200\" />\n </div>\n ) : item.emptyLabel ? (\n <div className=\"px-3 py-2 text-xs text-gray-500\">{item.emptyLabel}</div>\n ) : null\n ) : null}\n {groups.map((group, groupIndex) => (\n <div key={group.key}>\n {groupIndex > 0 ? <SelectSeparator /> : null}\n <SelectGroup>\n {group.label ? <SelectLabel>{group.label}</SelectLabel> : null}\n {group.options.map((option) => (\n <SelectItem key={option.value} value={option.value} className=\"py-2\">\n {option.description ? (\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n <span className=\"truncate text-xs font-semibold text-gray-800\">{option.label}</span>\n <span className=\"truncate text-[11px] text-gray-500\">{option.description}</span>\n </div>\n ) : (\n <span className=\"truncate text-xs font-semibold text-gray-800\">{option.label}</span>\n )}\n </SelectItem>\n ))}\n </SelectGroup>\n </div>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nexport function ChatInputBarToolbar({ actions, accessories, selects, skillPicker }: ChatInputBarToolbarProps) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-2 px-3 pb-3\">\n <div className=\"flex min-w-[12rem] flex-1 flex-wrap items-center gap-1 overflow-hidden\">\n {skillPicker ? <ChatInputBarSkillPicker picker={skillPicker} /> : null}\n {selects.map((item) => (\n <ToolbarSelect key={item.key} item={item} />\n ))}\n {accessories?.map((item) => {\n const button = (\n <button\n type=\"button\"\n className={`inline-flex items-center rounded-lg py-1.5 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 disabled:cursor-not-allowed disabled:text-gray-400 ${\n item.iconOnly ? 'h-8 w-8 justify-center px-0' : 'gap-1.5 px-3'\n }`}\n onClick={item.onClick}\n disabled={item.disabled}\n aria-label={item.label}\n >\n <AccessoryIcon icon={item.icon} />\n {item.iconOnly ? null : <span>{item.label}</span>}\n </button>\n );\n if (!item.tooltip) {\n return <div key={item.key}>{button}</div>;\n }\n const trigger = item.disabled ? <span className=\"inline-flex\">{button}</span> : button;\n return (\n <TooltipProvider key={item.key}>\n <Tooltip>\n <TooltipTrigger asChild>{trigger}</TooltipTrigger>\n <TooltipContent side=\"top\">\n <p className=\"text-xs\">{item.tooltip}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n })}\n </div>\n <ChatInputBarActions {...actions} />\n </div>\n );\n}\n","import type { ChatComposerNode, ChatComposerSelection, ChatComposerTextNode, ChatComposerTokenKind, ChatComposerTokenNode } from '../../view-models/chat-ui.types';\n\nexport const CHAT_COMPOSER_TOKEN_PLACEHOLDER = '\\uFFFC';\n\nfunction createComposerNodeId(): string {\n return `composer-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function createChatComposerTextNode(text = ''): ChatComposerTextNode {\n return {\n id: createComposerNodeId(),\n type: 'text',\n text\n };\n}\n\nexport function createChatComposerTokenNode(params: {\n tokenKind: ChatComposerTokenKind;\n tokenKey: string;\n label: string;\n}): ChatComposerTokenNode {\n return {\n id: createComposerNodeId(),\n type: 'token',\n tokenKind: params.tokenKind,\n tokenKey: params.tokenKey,\n label: params.label\n };\n}\n\nexport function getChatComposerNodeLength(node: ChatComposerNode): number {\n return node.type === 'text' ? node.text.length : 1;\n}\n\nexport function createEmptyChatComposerNodes(): ChatComposerNode[] {\n return [createChatComposerTextNode('')];\n}\n\nexport function createChatComposerNodesFromText(text: string): ChatComposerNode[] {\n return [createChatComposerTextNode(text)];\n}\n\nexport function normalizeChatComposerNodes(nodes: ChatComposerNode[]): ChatComposerNode[] {\n const normalized: ChatComposerNode[] = [];\n for (const node of nodes) {\n if (node.type === 'text') {\n if (node.text.length === 0) {\n continue;\n }\n const previous = normalized[normalized.length - 1];\n if (previous?.type === 'text') {\n normalized[normalized.length - 1] = {\n ...previous,\n text: previous.text + node.text\n };\n continue;\n }\n }\n normalized.push(node);\n }\n if (normalized.length === 0) {\n return createEmptyChatComposerNodes();\n }\n return normalized;\n}\n\nexport function serializeChatComposerDocument(nodes: ChatComposerNode[]): string {\n return nodes.map((node) => (node.type === 'text' ? node.text : CHAT_COMPOSER_TOKEN_PLACEHOLDER)).join('');\n}\n\nexport function serializeChatComposerPlainText(nodes: ChatComposerNode[]): string {\n return nodes.filter((node): node is ChatComposerTextNode => node.type === 'text').map((node) => node.text).join('');\n}\n\nexport function extractChatComposerTokenKeys(\n nodes: ChatComposerNode[],\n tokenKind: ChatComposerTokenKind\n): string[] {\n const keys: string[] = [];\n const keySet = new Set<string>();\n for (const node of nodes) {\n if (node.type !== 'token' || node.tokenKind !== tokenKind || keySet.has(node.tokenKey)) {\n continue;\n }\n keySet.add(node.tokenKey);\n keys.push(node.tokenKey);\n }\n return keys;\n}\n\nfunction buildTrimmedTextEdges(\n node: ChatComposerTextNode,\n nodeStart: number,\n rangeStart: number,\n rangeEnd: number\n): ChatComposerTextNode[] {\n const prefixLength = Math.max(0, rangeStart - nodeStart);\n const suffixLength = Math.max(0, nodeStart + node.text.length - rangeEnd);\n const edges: ChatComposerTextNode[] = [];\n\n if (prefixLength > 0) {\n edges.push({\n ...node,\n text: node.text.slice(0, prefixLength)\n });\n }\n if (suffixLength > 0) {\n edges.push({\n ...node,\n text: node.text.slice(node.text.length - suffixLength)\n });\n }\n\n return edges;\n}\n\nfunction isNodeOutsideComposerRange(\n nodeStart: number,\n nodeEnd: number,\n boundedStart: number,\n boundedEnd: number\n): boolean {\n return nodeEnd <= boundedStart || nodeStart >= boundedEnd;\n}\n\nfunction appendReplacementBeforeNode(\n nextNodes: ChatComposerNode[],\n replacement: ChatComposerNode[],\n inserted: boolean,\n nodeStart: number,\n boundedEnd: number\n): boolean {\n if (!inserted && nodeStart >= boundedEnd) {\n nextNodes.push(...replacement);\n return true;\n }\n return inserted;\n}\n\nfunction appendTextNodeWithReplacement(\n nextNodes: ChatComposerNode[],\n node: ChatComposerTextNode,\n nodeStart: number,\n boundedStart: number,\n boundedEnd: number,\n replacement: ChatComposerNode[],\n inserted: boolean\n): boolean {\n const edges = buildTrimmedTextEdges(node, nodeStart, boundedStart, boundedEnd);\n if (edges[0]) {\n nextNodes.push(edges[0]);\n }\n let didInsert = inserted;\n if (!didInsert) {\n nextNodes.push(...replacement);\n didInsert = true;\n }\n if (edges[1]) {\n nextNodes.push(edges[1]);\n }\n return didInsert;\n}\n\nfunction appendTokenNodeWithReplacement(\n nextNodes: ChatComposerNode[],\n node: ChatComposerNode,\n replacement: ChatComposerNode[],\n inserted: boolean,\n boundedStart: number,\n nodeStart: number\n): boolean {\n if (!inserted && boundedStart <= nodeStart) {\n nextNodes.push(...replacement);\n return true;\n }\n nextNodes.push(node);\n return inserted;\n}\n\nexport function replaceChatComposerRange(\n nodes: ChatComposerNode[],\n start: number,\n end: number,\n replacement: ChatComposerNode[]\n): ChatComposerNode[] {\n const boundedStart = Math.max(0, start);\n const boundedEnd = Math.max(boundedStart, end);\n const nextNodes: ChatComposerNode[] = [];\n let cursor = 0;\n let inserted = false;\n\n for (const node of nodes) {\n const nodeLength = getChatComposerNodeLength(node);\n const nodeStart = cursor;\n const nodeEnd = cursor + nodeLength;\n const isOutsideRange = isNodeOutsideComposerRange(nodeStart, nodeEnd, boundedStart, boundedEnd);\n\n if (isOutsideRange) {\n inserted = appendReplacementBeforeNode(nextNodes, replacement, inserted, nodeStart, boundedEnd);\n nextNodes.push(node);\n cursor = nodeEnd;\n continue;\n }\n\n if (node.type === 'text') {\n inserted = appendTextNodeWithReplacement(\n nextNodes,\n node,\n nodeStart,\n boundedStart,\n boundedEnd,\n replacement,\n inserted\n );\n } else {\n inserted = appendTokenNodeWithReplacement(nextNodes, node, replacement, inserted, boundedStart, nodeStart);\n }\n\n cursor = nodeEnd;\n }\n\n if (!inserted) {\n nextNodes.push(...replacement);\n }\n\n return normalizeChatComposerNodes(nextNodes);\n}\n\nexport function removeChatComposerTokenNodes(\n nodes: ChatComposerNode[],\n predicate: (node: ChatComposerTokenNode) => boolean\n): ChatComposerNode[] {\n return normalizeChatComposerNodes(\n nodes.filter((node) => node.type !== 'token' || !predicate(node))\n );\n}\n\nexport function resolveChatComposerSlashTrigger(\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null\n): { query: string; start: number; end: number } | null {\n if (!selection || selection.start !== selection.end) {\n return null;\n }\n\n const documentText = serializeChatComposerDocument(nodes);\n const caret = selection.end;\n const prefix = documentText.slice(0, caret);\n const match = /(?:^|\\s)\\/([^\\s\\uFFFC]*)$/.exec(prefix);\n if (!match) {\n return null;\n }\n\n const slashStart = caret - match[0].length + (match[0].startsWith('/') ? 0 : 1);\n return {\n query: (match[1] ?? '').trim().toLowerCase(),\n start: slashStart,\n end: caret\n };\n}\n\nexport function isChatComposerSelectionInsideRange(\n selection: ChatComposerSelection | null,\n start: number,\n end: number\n): boolean {\n if (!selection) {\n return false;\n }\n return selection.start < end && selection.end > start;\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type EditorConfig,\n type LexicalEditor,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n} from 'lexical';\nimport type { ReactElement } from 'react';\nimport { CHAT_COMPOSER_TOKEN_PLACEHOLDER } from '../chat-composer.utils';\nimport type { ChatComposerTokenKind } from '../../../view-models/chat-ui.types';\n\ntype SerializedChatComposerTokenNode = SerializedLexicalNode & {\n composerId: string;\n label: string;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n type: 'chat-composer-token';\n version: 1;\n};\n\nfunction buildTokenClassName(tokenKind: ChatComposerTokenKind): string {\n if (tokenKind === 'file') {\n return [\n 'mx-[2px]',\n 'inline-flex',\n 'h-7',\n 'max-w-[min(100%,17rem)]',\n 'items-center',\n 'gap-1.5',\n 'rounded-lg',\n 'border',\n 'border-slate-200/80',\n 'bg-slate-50',\n 'px-2',\n 'align-baseline',\n 'text-slate-700',\n 'transition-[border-color,background-color,box-shadow,color]',\n 'duration-150',\n ].join(' ');\n }\n\n return [\n 'mx-[2px]',\n 'inline-flex',\n 'h-7',\n 'max-w-full',\n 'items-center',\n 'gap-1.5',\n 'rounded-lg',\n 'border',\n 'border-primary/12',\n 'bg-primary/8',\n 'px-2',\n 'align-baseline',\n 'text-[11px]',\n 'font-medium',\n 'text-primary',\n 'transition',\n ].join(' ');\n}\n\nfunction ChatComposerTokenChip(props: {\n label: string;\n tokenKind: ChatComposerTokenKind;\n}): ReactElement {\n return (\n <>\n <span\n className={\n props.tokenKind === 'file'\n ? 'inline-flex h-4.5 w-4.5 shrink-0 items-center justify-center rounded-md bg-white text-slate-500 ring-1 ring-black/5'\n : 'inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center text-primary/70'\n }\n >\n {props.tokenKind === 'file' ? (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M3.25 4.25A1.5 1.5 0 0 1 4.75 2.75h6.5a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-6.5a1.5 1.5 0 0 1-1.5-1.5v-7.5Z\" />\n <path d=\"m4.75 10 2.25-2.5 1.75 1.75 1.25-1.25 2 2\" />\n <path d=\"M9.75 6.25h.01\" />\n </svg>\n ) : (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M8.5 2.75 2.75 6l5.75 3.25L14.25 6 8.5 2.75Z\" />\n <path d=\"M2.75 10 8.5 13.25 14.25 10\" />\n <path d=\"M2.75 6v4l5.75 3.25V9.25L2.75 6Z\" />\n <path d=\"M14.25 6v4L8.5 13.25V9.25L14.25 6Z\" />\n </svg>\n )}\n </span>\n <span\n className={\n props.tokenKind === 'file'\n ? 'min-w-0 flex-1 truncate text-[12px] font-medium text-slate-700'\n : 'truncate'\n }\n >\n {props.label}\n </span>\n </>\n );\n}\n\nexport class ChatComposerTokenNode extends DecoratorNode<ReactElement> {\n __composerId: string;\n __tokenKind: ChatComposerTokenKind;\n __tokenKey: string;\n __label: string;\n\n static getType(): string {\n return 'chat-composer-token';\n }\n\n static clone(node: ChatComposerTokenNode): ChatComposerTokenNode {\n return new ChatComposerTokenNode(\n node.__composerId,\n node.__tokenKind,\n node.__tokenKey,\n node.__label,\n node.__key,\n );\n }\n\n static importJSON(serializedNode: SerializedChatComposerTokenNode): ChatComposerTokenNode {\n return $createChatComposerTokenNode({\n composerId: serializedNode.composerId,\n label: serializedNode.label,\n tokenKey: serializedNode.tokenKey,\n tokenKind: serializedNode.tokenKind,\n });\n }\n\n constructor(\n composerId: string,\n tokenKind: ChatComposerTokenKind,\n tokenKey: string,\n label: string,\n key?: NodeKey,\n ) {\n super(key);\n this.__composerId = composerId;\n this.__tokenKind = tokenKind;\n this.__tokenKey = tokenKey;\n this.__label = label;\n }\n\n private readonly applyTokenDom = (element: HTMLElement): void => {\n element.contentEditable = 'false';\n element.dataset.composerNodeId = this.__composerId;\n element.dataset.composerNodeType = 'token';\n element.dataset.composerTokenKind = this.__tokenKind;\n element.dataset.composerTokenKey = this.__tokenKey;\n element.dataset.composerLabel = this.__label;\n element.title = this.__label;\n element.className = buildTokenClassName(this.__tokenKind);\n };\n\n createDOM = (_config: EditorConfig, _editor: LexicalEditor): HTMLElement => {\n const element = document.createElement('span');\n this.applyTokenDom(element);\n return element;\n };\n\n updateDOM = (_prevNode: ChatComposerTokenNode, dom: HTMLElement): false => {\n this.applyTokenDom(dom);\n return false;\n };\n\n decorate = (): ReactElement => {\n return <ChatComposerTokenChip label={this.__label} tokenKind={this.__tokenKind} />;\n };\n\n exportJSON = (): SerializedChatComposerTokenNode => {\n return {\n composerId: this.__composerId,\n label: this.__label,\n tokenKey: this.__tokenKey,\n tokenKind: this.__tokenKind,\n type: 'chat-composer-token',\n version: 1,\n };\n };\n\n getComposerId = (): string => {\n return this.getLatest().__composerId;\n };\n\n getTokenKind = (): ChatComposerTokenKind => {\n return this.getLatest().__tokenKind;\n };\n\n getTokenKey = (): string => {\n return this.getLatest().__tokenKey;\n };\n\n getLabel = (): string => {\n return this.getLatest().__label;\n };\n\n getTextContent = (): string => {\n return CHAT_COMPOSER_TOKEN_PLACEHOLDER;\n };\n\n isInline = (): true => {\n return true;\n };\n\n isIsolated = (): true => {\n return true;\n };\n\n isKeyboardSelectable = (): boolean => {\n return false;\n };\n}\n\nexport function $createChatComposerTokenNode(params: {\n composerId: string;\n label: string;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n}): ChatComposerTokenNode {\n const { composerId, label, tokenKey, tokenKind } = params;\n return $applyNodeReplacement(\n new ChatComposerTokenNode(composerId, tokenKind, tokenKey, label),\n );\n}\n\nexport function $isChatComposerTokenNode(\n node: LexicalNode | null | undefined,\n): node is ChatComposerTokenNode {\n return node instanceof ChatComposerTokenNode;\n}\n","import {\n $createLineBreakNode,\n $createParagraphNode,\n $createRangeSelection,\n $createTextNode,\n $getRoot,\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n type EditorState,\n type ElementPoint,\n type LexicalEditor,\n type LexicalNode,\n type NodeKey,\n type PointType,\n} from 'lexical';\nimport type { ChatComposerNode, ChatComposerSelection } from '../../../view-models/chat-ui.types';\nimport { normalizeChatComposerNodes } from '../chat-composer.utils';\nimport {\n $createChatComposerTokenNode,\n $isChatComposerTokenNode,\n type ChatComposerTokenNode,\n} from './chat-composer-token-node';\n\ntype LeafDescriptor =\n | {\n index: number;\n key: NodeKey;\n length: number;\n node: LexicalNode;\n start: number;\n type: 'linebreak' | 'token';\n }\n | {\n index: number;\n key: NodeKey;\n length: number;\n node: LexicalNode;\n start: number;\n text: string;\n type: 'text';\n };\n\ntype SelectionPointDescriptor = {\n key: NodeKey;\n offset: number;\n type: 'element' | 'text';\n};\n\nexport type ChatComposerEditorSnapshot = {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n};\n\nfunction getComposerLeafDescriptors(): {\n descriptors: LeafDescriptor[];\n paragraphKey: NodeKey;\n paragraphSize: number;\n totalLength: number;\n} {\n const root = $getRoot();\n const paragraph = root.getFirstChild();\n if (!$isElementNode(paragraph)) {\n return {\n descriptors: [],\n paragraphKey: root.getKey(),\n paragraphSize: 0,\n totalLength: 0,\n };\n }\n\n const children = paragraph.getChildren();\n const descriptors: LeafDescriptor[] = [];\n let cursor = 0;\n\n for (const [index, child] of children.entries()) {\n if ($isTextNode(child)) {\n const text = child.getTextContent();\n descriptors.push({\n index,\n key: child.getKey(),\n length: text.length,\n node: child,\n start: cursor,\n text,\n type: 'text',\n });\n cursor += text.length;\n continue;\n }\n\n if ($isChatComposerTokenNode(child)) {\n descriptors.push({\n index,\n key: child.getKey(),\n length: 1,\n node: child,\n start: cursor,\n type: 'token',\n });\n cursor += 1;\n continue;\n }\n\n descriptors.push({\n index,\n key: child.getKey(),\n length: child.getTextContent().length,\n node: child,\n start: cursor,\n type: 'linebreak',\n });\n cursor += child.getTextContent().length;\n }\n\n return {\n descriptors,\n paragraphKey: paragraph.getKey(),\n paragraphSize: children.length,\n totalLength: cursor,\n };\n}\n\nfunction buildSelectionPointFromOffset(offset: number): SelectionPointDescriptor {\n const { descriptors, paragraphKey, paragraphSize, totalLength } = getComposerLeafDescriptors();\n const boundedOffset = Math.max(0, Math.min(offset, totalLength));\n\n if (descriptors.length === 0) {\n return {\n key: paragraphKey,\n offset: 0,\n type: 'element',\n };\n }\n\n for (const descriptor of descriptors) {\n const end = descriptor.start + descriptor.length;\n\n if (descriptor.type === 'text' && boundedOffset >= descriptor.start && boundedOffset <= end) {\n return {\n key: descriptor.key,\n offset: boundedOffset - descriptor.start,\n type: 'text',\n };\n }\n\n if (descriptor.type !== 'text') {\n if (boundedOffset === descriptor.start) {\n return {\n key: paragraphKey,\n offset: descriptor.index,\n type: 'element',\n };\n }\n\n if (boundedOffset === end) {\n const nextDescriptor = descriptors[descriptor.index + 1];\n if (nextDescriptor?.type === 'text' && nextDescriptor.length === 0) {\n return {\n key: nextDescriptor.key,\n offset: 0,\n type: 'text',\n };\n }\n return {\n key: paragraphKey,\n offset: descriptor.index + 1,\n type: 'element',\n };\n }\n }\n }\n\n return {\n key: paragraphKey,\n offset: paragraphSize,\n type: 'element',\n };\n}\n\nfunction getOffsetFromElementPoint(point: ElementPoint): number {\n const { descriptors, paragraphKey, totalLength } = getComposerLeafDescriptors();\n\n if (point.key === paragraphKey) {\n const previous = descriptors[point.offset - 1];\n return previous ? previous.start + previous.length : 0;\n }\n\n const descriptor = descriptors.find((item) => item.key === point.key);\n if (!descriptor) {\n return totalLength;\n }\n\n return descriptor.start + Math.min(point.offset, descriptor.length);\n}\n\nfunction getOffsetFromPoint(point: PointType): number {\n if (point.type === 'element') {\n return getOffsetFromElementPoint(point);\n }\n\n const { descriptors, totalLength } = getComposerLeafDescriptors();\n const descriptor = descriptors.find((item) => item.key === point.key);\n if (!descriptor) {\n return totalLength;\n }\n\n return descriptor.start + Math.min(point.offset, descriptor.length);\n}\n\nfunction readNodesFromEditor(): ChatComposerNode[] {\n const { descriptors } = getComposerLeafDescriptors();\n const nextNodes: ChatComposerNode[] = [];\n let textBuffer = '';\n let textId = '';\n\n const flushTextBuffer = (): void => {\n if (textBuffer.length === 0) {\n return;\n }\n nextNodes.push({\n id: textId,\n type: 'text',\n text: textBuffer,\n });\n textBuffer = '';\n textId = '';\n };\n\n for (const descriptor of descriptors) {\n if (descriptor.type === 'text') {\n if (textBuffer.length === 0) {\n textId = descriptor.key;\n }\n textBuffer += descriptor.text;\n continue;\n }\n\n if (descriptor.type === 'linebreak') {\n if (textBuffer.length === 0) {\n textId = descriptor.key;\n }\n textBuffer += '\\n';\n continue;\n }\n\n flushTextBuffer();\n const tokenNode = descriptor.node as ChatComposerTokenNode;\n nextNodes.push({\n id: tokenNode.getComposerId(),\n label: tokenNode.getLabel(),\n tokenKey: tokenNode.getTokenKey(),\n tokenKind: tokenNode.getTokenKind(),\n type: 'token',\n });\n }\n\n flushTextBuffer();\n return normalizeChatComposerNodes(nextNodes);\n}\n\nexport function readChatComposerSnapshotFromEditorState(\n editorState: EditorState,\n): ChatComposerEditorSnapshot {\n return editorState.read(() => {\n const selection = $getSelection();\n const nodes = readNodesFromEditor();\n\n if (!$isRangeSelection(selection)) {\n return {\n nodes,\n selection: null,\n };\n }\n\n return {\n nodes,\n selection: {\n start: Math.min(getOffsetFromPoint(selection.anchor), getOffsetFromPoint(selection.focus)),\n end: Math.max(getOffsetFromPoint(selection.anchor), getOffsetFromPoint(selection.focus)),\n },\n };\n });\n}\n\nexport function writeChatComposerStateToLexicalRoot(\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null,\n): void {\n const root = $getRoot();\n root.clear();\n\n const paragraph = $createParagraphNode();\n root.append(paragraph);\n\n for (const node of normalizeChatComposerNodes(nodes)) {\n if (node.type === 'token') {\n paragraph.append(\n $createChatComposerTokenNode({\n composerId: node.id,\n label: node.label,\n tokenKey: node.tokenKey,\n tokenKind: node.tokenKind,\n }),\n );\n continue;\n }\n\n const parts = node.text.split('\\n');\n for (const [index, part] of parts.entries()) {\n if (part.length > 0) {\n paragraph.append($createTextNode(part));\n }\n if (index < parts.length - 1) {\n paragraph.append($createLineBreakNode());\n }\n }\n }\n\n if ($isChatComposerTokenNode(paragraph.getLastChild())) {\n paragraph.append($createTextNode(''));\n }\n\n if (!selection) {\n return;\n }\n\n const nextSelection = $createRangeSelection();\n const anchor = buildSelectionPointFromOffset(selection.start);\n const focus = buildSelectionPointFromOffset(selection.end);\n nextSelection.anchor.set(anchor.key, anchor.offset, anchor.type);\n nextSelection.focus.set(focus.key, focus.offset, focus.type);\n $setSelection(nextSelection);\n}\n\nexport function syncLexicalEditorFromChatComposerState(\n editor: LexicalEditor,\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null,\n): void {\n editor.update(() => {\n writeChatComposerStateToLexicalRoot(nodes, selection);\n });\n}\n\nexport function syncLexicalSelectionFromChatComposerSelection(\n editor: LexicalEditor,\n selection: ChatComposerSelection,\n): void {\n editor.update(() => {\n const nextSelection = $createRangeSelection();\n const anchor = buildSelectionPointFromOffset(selection.start);\n const focus = buildSelectionPointFromOffset(selection.end);\n nextSelection.anchor.set(anchor.key, anchor.offset, anchor.type);\n nextSelection.focus.set(focus.key, focus.offset, focus.type);\n $setSelection(nextSelection);\n });\n}\n","import type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatComposerTokenKind,\n ChatSkillPickerOption,\n} from '../../../view-models/chat-ui.types';\nimport {\n createChatComposerTextNode,\n createChatComposerTokenNode,\n extractChatComposerTokenKeys,\n getChatComposerNodeLength,\n normalizeChatComposerNodes,\n removeChatComposerTokenNodes,\n replaceChatComposerRange,\n resolveChatComposerSlashTrigger,\n} from '../chat-composer.utils';\nimport type { ChatComposerEditorSnapshot } from './chat-composer-lexical-editor-state';\n\nfunction getDocumentLength(nodes: ChatComposerNode[]): number {\n return nodes.reduce((sum, node) => sum + getChatComposerNodeLength(node), 0);\n}\n\nfunction insertToken(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n trigger?: { end: number; query: string; start: number } | null;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey, tokenKind, trigger } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = selection ? [Math.min(selection.start, selection.end), Math.max(selection.start, selection.end)] : [documentLength, documentLength];\n const replaceStart = trigger?.start ?? selectionStart;\n const replaceEnd = trigger?.end ?? selectionEnd;\n\n return {\n nodes: replaceChatComposerRange(\n nodes,\n replaceStart,\n replaceEnd,\n [\n createChatComposerTokenNode({\n label,\n tokenKey,\n tokenKind,\n }),\n ],\n ),\n selection: {\n start: replaceStart + 1,\n end: replaceStart + 1,\n },\n };\n}\n\nexport function getChatComposerNodesSignature(nodes: ChatComposerNode[]): string {\n return nodes\n .map((node) =>\n node.type === 'text'\n ? `text:${node.id}:${node.text}`\n : `token:${node.id}:${node.tokenKind}:${node.tokenKey}:${node.label}`,\n )\n .join('\\u001f');\n}\n\nexport function replaceChatComposerSelectionWithText(params: {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n text: string;\n}): ChatComposerEditorSnapshot {\n const { nodes, selection, text } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = selection ? [Math.min(selection.start, selection.end), Math.max(selection.start, selection.end)] : [documentLength, documentLength];\n const nextOffset = selectionStart + text.length;\n\n return {\n nodes: replaceChatComposerRange(\n nodes,\n selectionStart,\n selectionEnd,\n [createChatComposerTextNode(text)],\n ),\n selection: {\n start: nextOffset,\n end: nextOffset,\n },\n };\n}\n\nexport function insertFileTokenIntoChatComposer(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey } = params;\n return insertToken({\n label,\n nodes,\n selection,\n tokenKey,\n tokenKind: 'file',\n });\n}\n\nexport function insertSkillTokenIntoChatComposer(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey } = params;\n\n if (extractChatComposerTokenKeys(nodes, 'skill').includes(tokenKey)) {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection,\n };\n }\n\n return insertToken({\n label,\n nodes,\n selection,\n tokenKey,\n tokenKind: 'skill',\n trigger: resolveChatComposerSlashTrigger(nodes, selection),\n });\n}\n\nexport function syncSelectedSkillsIntoChatComposer(params: {\n nextKeys: string[];\n nodes: ChatComposerNode[];\n options: ChatSkillPickerOption[];\n selection: ChatComposerSelection | null;\n}): ChatComposerEditorSnapshot {\n const { nextKeys, nodes, options, selection } = params;\n const selectedSkillKeys = extractChatComposerTokenKeys(nodes, 'skill');\n const optionMap = new Map(options.map((option) => [option.key, option]));\n const addedKey = nextKeys.find((key) => !selectedSkillKeys.includes(key));\n\n if (addedKey) {\n const option = optionMap.get(addedKey);\n return insertSkillTokenIntoChatComposer({\n label: option?.label ?? addedKey,\n nodes,\n selection,\n tokenKey: addedKey,\n });\n }\n\n const removedKey = selectedSkillKeys.find((key) => !nextKeys.includes(key));\n if (!removedKey) {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection,\n };\n }\n\n return {\n nodes: removeChatComposerTokenNodes(\n nodes,\n (node) => node.tokenKind === 'skill' && node.tokenKey === removedKey,\n ),\n selection,\n };\n}\n\nexport function deleteChatComposerContent(params: {\n direction: 'backward' | 'forward';\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n}): ChatComposerEditorSnapshot {\n const { direction, nodes, selection: currentSelection } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = currentSelection ? [Math.min(currentSelection.start, currentSelection.end), Math.max(currentSelection.start, currentSelection.end)] : [documentLength, documentLength];\n let rangeStart = selectionStart;\n let rangeEnd = selectionEnd;\n\n if (rangeStart === rangeEnd) {\n if (direction === 'backward' && rangeStart > 0) {\n rangeStart -= 1;\n } else if (direction === 'forward' && rangeEnd < documentLength) {\n rangeEnd += 1;\n } else {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection: { start: rangeStart, end: rangeEnd },\n };\n }\n }\n\n return {\n nodes: replaceChatComposerRange(nodes, rangeStart, rangeEnd, []),\n selection: {\n start: rangeStart,\n end: rangeStart,\n },\n };\n}\n","import type { FormEvent } from 'react';\nimport type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatInputBarActionsProps,\n ChatSkillPickerOption,\n ChatSlashItem,\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { resolveChatComposerSlashTrigger } from '@agent-chat-ui/components/chat/ui/chat-input-bar/chat-composer.utils';\nimport {\n deleteChatComposerContent,\n insertFileTokenIntoChatComposer,\n insertSkillTokenIntoChatComposer,\n replaceChatComposerSelectionWithText,\n syncSelectedSkillsIntoChatComposer,\n type ChatComposerEditorSnapshot,\n} from './chat-composer-lexical-adapter';\nimport type { ChatInputBarTokenizedComposerHandle } from './chat-input-bar-tokenized-composer';\n\ntype ComposerActions = Pick<\n ChatInputBarActionsProps,\n 'onSend' | 'onStop' | 'isSending' | 'canStopGeneration'\n>;\n\ntype ChatComposerKeyboardAction =\n | { type: 'close-slash' }\n | { type: 'consume' }\n | { type: 'delete-content'; direction: 'backward' | 'forward' }\n | { type: 'insert-active-slash-item' }\n | { type: 'insert-line-break' }\n | { type: 'move-slash-index'; index: number }\n | { type: 'noop' }\n | { type: 'send-message' }\n | { type: 'stop-generation' };\n\nexport function resolveLexicalComposerKeyboardAction(params: {\n activeSlashIndex: number;\n canStopGeneration: boolean;\n isComposing: boolean;\n isSending: boolean;\n isSlashMenuOpen: boolean;\n key: string;\n shiftKey: boolean;\n slashItemCount: number;\n}): ChatComposerKeyboardAction {\n const {\n activeSlashIndex,\n canStopGeneration,\n isComposing,\n isSending,\n isSlashMenuOpen,\n key,\n shiftKey,\n slashItemCount,\n } = params;\n\n if (key === 'Enter' && !shiftKey && isSending) {\n return { type: 'consume' };\n }\n\n if (isSlashMenuOpen && slashItemCount > 0) {\n if (key === 'ArrowDown') {\n return {\n type: 'move-slash-index',\n index: (activeSlashIndex + 1) % slashItemCount,\n };\n }\n if (key === 'ArrowUp') {\n return {\n type: 'move-slash-index',\n index: (activeSlashIndex - 1 + slashItemCount) % slashItemCount,\n };\n }\n if ((key === 'Enter' && !shiftKey) || key === 'Tab') {\n return { type: 'insert-active-slash-item' };\n }\n }\n\n if (key === 'Escape') {\n if (isSlashMenuOpen) {\n return { type: 'close-slash' };\n }\n if (isSending && canStopGeneration) {\n return { type: 'stop-generation' };\n }\n return { type: 'noop' };\n }\n\n if (key === 'Enter' && shiftKey) {\n return { type: 'insert-line-break' };\n }\n\n if (key === 'Enter') {\n return { type: 'send-message' };\n }\n\n if (!isComposing && (key === 'Backspace' || key === 'Delete')) {\n return {\n type: 'delete-content',\n direction: key === 'Backspace' ? 'backward' : 'forward',\n };\n }\n\n return { type: 'noop' };\n}\n\ntype LexicalComposerHandleOwnerParams = {\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n optionsReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n};\n\nclass LexicalComposerHandleOwner implements ChatInputBarTokenizedComposerHandle {\n constructor(private readonly params: LexicalComposerHandleOwnerParams) {}\n\n insertSlashItem = (item: ChatSlashItem): void => {\n if (!item.value) {\n return;\n }\n\n this.params.onSlashItemSelect?.(item);\n this.params.publishSnapshot(\n insertSkillTokenIntoChatComposer({\n label: item.title,\n nodes: this.params.optionsReader().nodes,\n selection: this.params.optionsReader().selection,\n tokenKey: item.value,\n }),\n { focusAfterSync: true },\n );\n };\n\n insertFileToken = (tokenKey: string, label: string): void => {\n this.params.publishSnapshot(\n insertFileTokenIntoChatComposer({\n label,\n nodes: this.params.optionsReader().nodes,\n selection: this.params.optionsReader().selection,\n tokenKey,\n }),\n { focusAfterSync: true },\n );\n };\n\n insertFileTokens = (tokens: Array<{ tokenKey: string; label: string }>): void => {\n let nextNodes = this.params.optionsReader().nodes;\n let nextSelection = this.params.optionsReader().selection;\n\n for (const token of tokens) {\n const snapshot = insertFileTokenIntoChatComposer({\n label: token.label,\n nodes: nextNodes,\n selection: nextSelection,\n tokenKey: token.tokenKey,\n });\n nextNodes = snapshot.nodes;\n nextSelection = snapshot.selection;\n }\n\n this.params.publishSnapshot(\n {\n nodes: nextNodes,\n selection: nextSelection,\n },\n { focusAfterSync: true },\n );\n };\n\n focusComposer = (): void => {\n this.params.focusComposer();\n };\n\n focusComposerAtEnd = (): void => {\n this.params.focusComposerAtEnd();\n };\n\n syncSelectedSkills = (nextKeys: string[], options: ChatSkillPickerOption[]): void => {\n this.params.publishSnapshot(\n syncSelectedSkillsIntoChatComposer({\n nextKeys,\n nodes: this.params.optionsReader().nodes,\n options,\n selection: this.params.optionsReader().selection,\n }),\n { focusAfterSync: true },\n );\n };\n}\n\nexport function createLexicalComposerHandle(\n params: LexicalComposerHandleOwnerParams,\n): ChatInputBarTokenizedComposerHandle {\n return new LexicalComposerHandleOwner(params);\n}\n\nfunction getChatComposerContentSignature(nodes: ChatComposerNode[]): string {\n return JSON.stringify(\n nodes.map((node) =>\n node.type === 'text'\n ? { text: node.text, type: node.type }\n : {\n label: node.label,\n tokenKey: node.tokenKey,\n tokenKind: node.tokenKind,\n type: node.type,\n },\n ),\n );\n}\n\nexport function handleLexicalComposerBeforeInput(params: {\n disabled: boolean;\n event: FormEvent<HTMLDivElement>;\n isComposing: boolean;\n publishSnapshot: (snapshot: ChatComposerEditorSnapshot) => void;\n snapshotReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n}): void {\n const { disabled, event, isComposing, publishSnapshot, snapshotReader } = params;\n const nativeEvent = event.nativeEvent as InputEvent;\n const shouldInsertText =\n nativeEvent.inputType === 'insertText' ||\n nativeEvent.inputType === 'insertReplacementText';\n\n if (\n disabled ||\n isComposing ||\n nativeEvent.isComposing ||\n !shouldInsertText ||\n !nativeEvent.data\n ) {\n return;\n }\n\n event.preventDefault();\n publishSnapshot(\n replaceChatComposerSelectionWithText({\n nodes: snapshotReader().nodes,\n selection: snapshotReader().selection,\n text: nativeEvent.data,\n }),\n );\n}\n\nexport function handleLexicalComposerCompositionEnd(params: {\n data: string;\n fallbackSnapshot: () => ChatComposerEditorSnapshot;\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n snapshotReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n}): void {\n const { data, fallbackSnapshot, publishSnapshot, snapshotReader } = params;\n const currentSnapshot = snapshotReader();\n const editorSnapshot = fallbackSnapshot();\n const shouldUseEditorSnapshot =\n getChatComposerContentSignature(editorSnapshot.nodes) !==\n getChatComposerContentSignature(currentSnapshot.nodes);\n const snapshot = shouldUseEditorSnapshot\n ? editorSnapshot\n : data.length > 0\n ? replaceChatComposerSelectionWithText({\n nodes: currentSnapshot.nodes,\n selection: currentSnapshot.selection,\n text: data,\n })\n : editorSnapshot;\n publishSnapshot(snapshot, { forcePublish: true });\n}\n\nexport function handleLexicalComposerKeyboardCommand(params: {\n actions: ComposerActions;\n activeSlashIndex: number;\n onSlashActiveIndexChange: (index: number) => void;\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n onSlashOpenChange: (open: boolean) => void;\n onSlashQueryChange?: (query: string | null) => void;\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n slashItems: ChatSlashItem[];\n snapshot: ChatComposerEditorSnapshot;\n nativeEvent: KeyboardEvent;\n}): boolean {\n const {\n actions,\n activeSlashIndex,\n nativeEvent,\n onSlashActiveIndexChange,\n onSlashItemSelect,\n onSlashOpenChange,\n onSlashQueryChange,\n publishSnapshot,\n slashItems,\n snapshot,\n } = params;\n const action = resolveLexicalComposerKeyboardAction({\n activeSlashIndex,\n canStopGeneration: actions.canStopGeneration,\n isComposing: nativeEvent.isComposing,\n isSending: actions.isSending,\n isSlashMenuOpen: resolveChatComposerSlashTrigger(snapshot.nodes, snapshot.selection) !== null,\n key: nativeEvent.key,\n shiftKey: nativeEvent.shiftKey,\n slashItemCount: slashItems.length,\n });\n const activeSlashItem = slashItems[activeSlashIndex] ?? null;\n\n if (action.type !== 'noop') {\n nativeEvent.preventDefault();\n }\n\n switch (action.type) {\n case 'move-slash-index':\n onSlashActiveIndexChange(action.index);\n return true;\n case 'insert-active-slash-item':\n if (!activeSlashItem) {\n return true;\n }\n onSlashItemSelect?.(activeSlashItem);\n publishSnapshot(\n insertSkillTokenIntoChatComposer({\n label: activeSlashItem.title,\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n tokenKey: activeSlashItem.value ?? activeSlashItem.key,\n }),\n { focusAfterSync: true },\n );\n return true;\n case 'close-slash':\n onSlashQueryChange?.(null);\n onSlashOpenChange(false);\n return true;\n case 'consume':\n return true;\n case 'stop-generation':\n void actions.onStop();\n return true;\n case 'insert-line-break':\n publishSnapshot(\n replaceChatComposerSelectionWithText({\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n text: '\\n',\n }),\n );\n return true;\n case 'send-message':\n void actions.onSend();\n return true;\n case 'delete-content':\n publishSnapshot(\n deleteChatComposerContent({\n direction: action.direction,\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n }),\n );\n return true;\n case 'noop':\n return false;\n }\n}\n","import { useEffect, useLayoutEffect, type MutableRefObject } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n BLUR_COMMAND,\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_HIGH,\n KEY_DOWN_COMMAND,\n SELECTION_CHANGE_COMMAND,\n mergeRegister,\n type LexicalEditor,\n} from 'lexical';\nimport type { ChatComposerNode, ChatComposerSelection } from '../../../view-models/chat-ui.types';\nimport {\n getChatComposerNodesSignature,\n readChatComposerSnapshotFromEditorState,\n syncLexicalEditorFromChatComposerState,\n syncLexicalSelectionFromChatComposerSelection,\n} from './chat-composer-lexical-adapter';\n\ntype ChatComposerBindingsPluginProps = {\n disabled: boolean;\n editorRef: MutableRefObject<LexicalEditor | null>;\n editorSignatureRef: MutableRefObject<string>;\n isApplyingExternalUpdateRef: MutableRefObject<boolean>;\n isComposingRef: MutableRefObject<boolean>;\n lastPublishedSignatureRef: MutableRefObject<string>;\n nodes: ChatComposerNode[];\n onBlur: () => void;\n onKeyDown: (event: KeyboardEvent) => boolean;\n onNodesChange: (nodes: ChatComposerNode[]) => void;\n pendingSelectionRef: MutableRefObject<ChatComposerSelection | null>;\n selectionRef: MutableRefObject<ChatComposerSelection | null>;\n shouldFocusAfterSyncRef: MutableRefObject<boolean>;\n syncSlashState: (nodes: ChatComposerNode[], selection: ChatComposerSelection | null) => void;\n};\n\nexport function ChatComposerBindingsPlugin(\n props: ChatComposerBindingsPluginProps,\n): null {\n const [editor] = useLexicalComposerContext();\n\n useLayoutEffect(() => {\n props.editorRef.current = editor;\n return () => {\n if (props.editorRef.current === editor) {\n props.editorRef.current = null;\n }\n };\n }, [editor, props.editorRef]);\n\n useLayoutEffect(() => {\n editor.setEditable(!props.disabled);\n }, [editor, props.disabled]);\n\n useLayoutEffect(() => {\n const nextSignature = getChatComposerNodesSignature(props.nodes);\n const pendingSelection = props.pendingSelectionRef.current;\n const shouldSyncDocument = nextSignature !== props.editorSignatureRef.current;\n\n if (!shouldSyncDocument && !pendingSelection) {\n return;\n }\n\n props.isApplyingExternalUpdateRef.current = true;\n\n if (shouldSyncDocument) {\n syncLexicalEditorFromChatComposerState(editor, props.nodes, pendingSelection);\n props.editorSignatureRef.current = nextSignature;\n props.lastPublishedSignatureRef.current = nextSignature;\n } else if (pendingSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, pendingSelection);\n }\n\n if (pendingSelection) {\n props.selectionRef.current = pendingSelection;\n props.pendingSelectionRef.current = null;\n }\n\n if (props.shouldFocusAfterSyncRef.current) {\n props.shouldFocusAfterSyncRef.current = false;\n const targetSelection = props.selectionRef.current;\n editor.focus(() => {\n if (targetSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n }\n });\n }\n\n requestAnimationFrame(() => {\n props.isApplyingExternalUpdateRef.current = false;\n });\n }, [\n editor,\n props.editorSignatureRef,\n props.isApplyingExternalUpdateRef,\n props.lastPublishedSignatureRef,\n props.nodes,\n props.pendingSelectionRef,\n props.selectionRef,\n props.shouldFocusAfterSyncRef,\n ]);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n const snapshot = readChatComposerSnapshotFromEditorState(editorState);\n const signature = getChatComposerNodesSignature(snapshot.nodes);\n\n props.selectionRef.current = snapshot.selection;\n props.editorSignatureRef.current = signature;\n props.syncSlashState(snapshot.nodes, snapshot.selection);\n\n if (props.isApplyingExternalUpdateRef.current || props.isComposingRef.current) {\n return;\n }\n\n if (signature === props.lastPublishedSignatureRef.current) {\n return;\n }\n\n props.lastPublishedSignatureRef.current = signature;\n props.onNodesChange(snapshot.nodes);\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n props.selectionRef.current = snapshot.selection;\n if (!props.isComposingRef.current) {\n props.syncSlashState(snapshot.nodes, snapshot.selection);\n }\n return false;\n },\n COMMAND_PRIORITY_EDITOR,\n ),\n editor.registerCommand(\n BLUR_COMMAND,\n () => {\n props.onBlur();\n return false;\n },\n COMMAND_PRIORITY_EDITOR,\n ),\n editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event) => props.onKeyDown(event),\n COMMAND_PRIORITY_HIGH,\n ),\n );\n }, [\n editor,\n props.editorSignatureRef,\n props.isApplyingExternalUpdateRef,\n props.isComposingRef,\n props.lastPublishedSignatureRef,\n props.onBlur,\n props.onKeyDown,\n props.onNodesChange,\n props.selectionRef,\n props.syncSlashState,\n ]);\n\n return null;\n}\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type ClipboardEvent,\n type FormEvent,\n} from 'react';\nimport type { LexicalEditor } from 'lexical';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { EditorRefPlugin } from '@lexical/react/LexicalEditorRefPlugin';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';\nimport type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatInputBarActionsProps,\n ChatSkillPickerOption,\n ChatSlashItem,\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { resolveChatComposerSlashTrigger } from '@agent-chat-ui/components/chat/ui/chat-input-bar/chat-composer.utils';\nimport {\n getChatComposerNodesSignature,\n readChatComposerSnapshotFromEditorState,\n syncLexicalSelectionFromChatComposerSelection,\n writeChatComposerStateToLexicalRoot,\n} from './chat-composer-lexical-adapter';\nimport {\n createLexicalComposerHandle,\n handleLexicalComposerBeforeInput,\n handleLexicalComposerCompositionEnd,\n handleLexicalComposerKeyboardCommand,\n} from './chat-composer-lexical-controller';\nimport { ChatComposerBindingsPlugin } from './chat-composer-plugins';\nimport { ChatComposerTokenNode } from './chat-composer-token-node';\n\nexport type ChatInputBarTokenizedComposerHandle = {\n insertSlashItem: (item: ChatSlashItem) => void;\n insertFileToken: (tokenKey: string, label: string) => void;\n insertFileTokens: (tokens: Array<{ tokenKey: string; label: string }>) => void;\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n syncSelectedSkills: (nextKeys: string[], options: ChatSkillPickerOption[]) => void;\n};\n\ntype ChatInputBarTokenizedComposerProps = {\n nodes: ChatComposerNode[];\n placeholder: string;\n disabled: boolean;\n slashItems: ChatSlashItem[];\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n actions: Pick<ChatInputBarActionsProps, 'onSend' | 'onStop' | 'isSending' | 'canStopGeneration'>;\n onNodesChange: (nodes: ChatComposerNode[]) => void;\n onFilesAdd?: (files: File[]) => Promise<void> | void;\n onSlashQueryChange?: (query: string | null) => void;\n onSlashTriggerChange?: (trigger: { query: string; start: number; end: number } | null) => void;\n onSlashOpenChange: (open: boolean) => void;\n onSlashActiveIndexChange: (index: number) => void;\n activeSlashIndex: number;\n};\n\nexport const ChatInputBarTokenizedComposer = forwardRef<\n ChatInputBarTokenizedComposerHandle,\n ChatInputBarTokenizedComposerProps\n>(function ChatInputBarTokenizedComposer(props, ref) {\n const editorRef = useRef<LexicalEditor | null>(null);\n const selectionRef = useRef<ChatComposerSelection | null>(null);\n const pendingSelectionRef = useRef<ChatComposerSelection | null>(null);\n const shouldFocusAfterSyncRef = useRef(false);\n const isComposingRef = useRef(false);\n const isApplyingExternalUpdateRef = useRef(false);\n const editorSignatureRef = useRef('');\n const lastPublishedSignatureRef = useRef('');\n\n const syncSlashState = (nodes: ChatComposerNode[], selection: ChatComposerSelection | null): void => {\n const trigger = resolveChatComposerSlashTrigger(nodes, selection);\n props.onSlashTriggerChange?.(trigger);\n props.onSlashQueryChange?.(trigger?.query ?? null);\n props.onSlashOpenChange(trigger !== null);\n };\n\n const readCurrentNodes = (): ChatComposerNode[] => {\n return props.nodes;\n };\n\n const readCurrentSelection = (): ChatComposerSelection | null => {\n if (selectionRef.current) {\n return selectionRef.current;\n }\n\n if (!editorRef.current) {\n return null;\n }\n\n const snapshot = readChatComposerSnapshotFromEditorState(editorRef.current.getEditorState());\n selectionRef.current = snapshot.selection;\n return snapshot.selection;\n };\n\n const publishSnapshot = (\n snapshot: { nodes: ChatComposerNode[]; selection: ChatComposerSelection | null },\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ): void => {\n selectionRef.current = snapshot.selection;\n pendingSelectionRef.current = snapshot.selection;\n\n if (options?.focusAfterSync) {\n shouldFocusAfterSyncRef.current = true;\n }\n\n const signature = getChatComposerNodesSignature(snapshot.nodes);\n syncSlashState(snapshot.nodes, snapshot.selection);\n\n if (options?.forcePublish || signature !== lastPublishedSignatureRef.current) {\n lastPublishedSignatureRef.current = signature;\n props.onNodesChange(snapshot.nodes);\n }\n };\n\n const focusComposer = (): void => {\n const editor = editorRef.current;\n if (!editor) {\n return;\n }\n\n editor.getRootElement()?.focus({ preventScroll: true });\n const targetSelection = selectionRef.current;\n if (targetSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n }\n editor.focus();\n };\n\n const focusComposerAtEnd = (): void => {\n const editor = editorRef.current;\n if (!editor) {\n return;\n }\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n const end = snapshot.nodes.reduce((cursor, node) => cursor + (node.type === 'text' ? node.text.length : 1), 0);\n const targetSelection = { start: end, end };\n selectionRef.current = targetSelection;\n editor.getRootElement()?.focus({ preventScroll: true });\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n editor.focus();\n };\n\n const readComposerSnapshot = (): { nodes: ChatComposerNode[]; selection: ChatComposerSelection | null } => ({\n nodes: readCurrentNodes(),\n selection: readCurrentSelection(),\n });\n\n useImperativeHandle(\n ref,\n () =>\n createLexicalComposerHandle({\n focusComposer,\n focusComposerAtEnd,\n onSlashItemSelect: props.onSlashItemSelect,\n optionsReader: readComposerSnapshot,\n publishSnapshot,\n }),\n [props.onSlashItemSelect],\n );\n\n const initialConfig = useMemo(\n () => ({\n editable: !props.disabled,\n editorState: () => {\n writeChatComposerStateToLexicalRoot(props.nodes, null);\n },\n namespace: 'NextClawChatComposerLexical',\n nodes: [ChatComposerTokenNode],\n onError: (error: Error) => {\n throw error;\n },\n theme: {},\n }),\n [props.disabled, props.nodes],\n );\n\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <div className=\"px-3 py-2 sm:px-4 sm:py-2.5\">\n <div className=\"min-h-11 sm:min-h-[60px]\">\n <PlainTextPlugin\n contentEditable={\n <ContentEditable\n className=\"min-h-7 max-h-[188px] w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent py-0.5 text-sm leading-6 text-gray-800 outline-none\"\n onBeforeInput={(event: FormEvent<HTMLDivElement>) => {\n handleLexicalComposerBeforeInput({\n disabled: props.disabled,\n event,\n isComposing: isComposingRef.current,\n publishSnapshot,\n snapshotReader: readComposerSnapshot,\n });\n }}\n onCompositionEnd={(event) => {\n isComposingRef.current = false;\n const nativeEvent = event.nativeEvent as CompositionEvent;\n handleLexicalComposerCompositionEnd({\n data: typeof nativeEvent.data === 'string' ? nativeEvent.data : '',\n fallbackSnapshot: () => {\n const editor = editorRef.current;\n return editor\n ? readChatComposerSnapshotFromEditorState(editor.getEditorState())\n : readComposerSnapshot();\n },\n publishSnapshot,\n snapshotReader: readComposerSnapshot,\n });\n }}\n onCompositionStart={() => {\n isComposingRef.current = true;\n }}\n onPaste={(event: ClipboardEvent<HTMLDivElement>) => {\n const files = Array.from(event.clipboardData.files ?? []);\n if (files.length > 0 && props.onFilesAdd) {\n event.preventDefault();\n void props.onFilesAdd(files);\n }\n }}\n />\n }\n placeholder={\n <div className=\"pointer-events-none absolute left-3 top-2 select-none text-sm leading-6 text-gray-400 sm:left-4 sm:top-2.5\">\n {props.placeholder}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n </div>\n </div>\n <EditorRefPlugin editorRef={editorRef} />\n <ChatComposerBindingsPlugin\n disabled={props.disabled}\n editorRef={editorRef}\n editorSignatureRef={editorSignatureRef}\n isApplyingExternalUpdateRef={isApplyingExternalUpdateRef}\n isComposingRef={isComposingRef}\n lastPublishedSignatureRef={lastPublishedSignatureRef}\n nodes={props.nodes}\n onBlur={() => {\n props.onSlashQueryChange?.(null);\n props.onSlashOpenChange(false);\n }}\n onKeyDown={(event) => {\n const editor = editorRef.current;\n if (!editor) {\n return false;\n }\n\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n selectionRef.current = snapshot.selection;\n return handleLexicalComposerKeyboardCommand({\n actions: props.actions,\n activeSlashIndex: props.activeSlashIndex,\n nativeEvent: event,\n onSlashActiveIndexChange: props.onSlashActiveIndexChange,\n onSlashItemSelect: props.onSlashItemSelect,\n onSlashOpenChange: props.onSlashOpenChange,\n onSlashQueryChange: props.onSlashQueryChange,\n publishSnapshot,\n slashItems: props.slashItems,\n snapshot,\n });\n }}\n onNodesChange={props.onNodesChange}\n pendingSelectionRef={pendingSelectionRef}\n selectionRef={selectionRef}\n shouldFocusAfterSyncRef={shouldFocusAfterSyncRef}\n syncSlashState={syncSlashState}\n />\n </LexicalComposer>\n );\n});\n\nChatInputBarTokenizedComposer.displayName = 'LexicalChatInputBarTokenizedComposer';\n","import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport type { ChatInputBarProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { ChatSlashMenu } from './chat-slash-menu';\nimport { ChatInputBarToolbar } from './chat-input-bar-toolbar';\nimport { ChatInputBarTokenizedComposer, type ChatInputBarTokenizedComposerHandle } from './chat-input-bar-tokenized-composer';\n\nfunction InputBarHint({ hint }: { hint: ChatInputBarProps['hint'] }) {\n if (!hint) {\n return null;\n }\n\n if (hint.loading) {\n return (\n <div className=\"px-4 pb-2\">\n <div className=\"inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2\">\n <span className=\"h-3 w-28 animate-pulse rounded bg-gray-200\" />\n <span className=\"h-3 w-16 animate-pulse rounded bg-gray-200\" />\n </div>\n </div>\n );\n }\n\n const toneClassName =\n hint.tone === 'warning'\n ? 'border-amber-200 bg-amber-50 text-amber-800'\n : 'border-gray-200 bg-gray-50 text-gray-700';\n\n return (\n <div className=\"px-4 pb-2\">\n <div className={`inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs ${toneClassName}`}>\n {hint.text ? <span>{hint.text}</span> : null}\n {hint.actionLabel && hint.onAction ? (\n <button\n type=\"button\"\n onClick={hint.onAction}\n className=\"font-semibold underline-offset-2 hover:underline\"\n >\n {hint.actionLabel}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport type ChatInputBarHandle = {\n insertFileToken: (tokenKey: string, label: string) => void;\n insertFileTokens: (tokens: Array<{ tokenKey: string; label: string }>) => void;\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n};\n\nexport const ChatInputBar = forwardRef<ChatInputBarHandle, ChatInputBarProps>(function ChatInputBar(props, ref) {\n const composerRef = useRef<ChatInputBarTokenizedComposerHandle | null>(null);\n const isSlashMenuInteractionRef = useRef(false);\n const [activeSlashIndex, setActiveSlashIndex] = useState(0);\n const [activeSlashTriggerStart, setActiveSlashTriggerStart] = useState<number | null>(null);\n const [dismissedSlashTriggerStart, setDismissedSlashTriggerStart] = useState<number | null>(null);\n const isSlashPanelOpen = activeSlashTriggerStart !== null && dismissedSlashTriggerStart !== activeSlashTriggerStart;\n const activeSlashItem = props.slashMenu.items[activeSlashIndex] ?? null;\n const dismissSlashTrigger = () => activeSlashTriggerStart !== null && !isSlashMenuInteractionRef.current\n ? setDismissedSlashTriggerStart(activeSlashTriggerStart)\n : undefined;\n\n useEffect(() => {\n setActiveSlashIndex((current) => {\n if (props.slashMenu.items.length === 0) {\n return 0;\n }\n return Math.min(current, props.slashMenu.items.length - 1);\n });\n }, [props.slashMenu.items.length]);\n\n useEffect(() => {\n if (activeSlashTriggerStart === null && dismissedSlashTriggerStart !== null) {\n setDismissedSlashTriggerStart(null);\n }\n }, [activeSlashTriggerStart, dismissedSlashTriggerStart]);\n\n const toolbar = useMemo(() => {\n if (!props.toolbar.skillPicker) {\n return props.toolbar;\n }\n return {\n ...props.toolbar,\n skillPicker: {\n ...props.toolbar.skillPicker,\n onSelectedKeysChange: (nextKeys: string[]) => {\n composerRef.current?.syncSelectedSkills(nextKeys, props.toolbar.skillPicker?.options ?? []);\n props.toolbar.skillPicker?.onSelectedKeysChange(nextKeys);\n }\n }\n };\n }, [props.toolbar]);\n\n useImperativeHandle(ref, () => ({\n insertFileToken: (tokenKey, label) => composerRef.current?.insertFileToken(tokenKey, label),\n insertFileTokens: (tokens) => composerRef.current?.insertFileTokens(tokens),\n focusComposer: () => composerRef.current?.focusComposer(),\n focusComposerAtEnd: () => composerRef.current?.focusComposerAtEnd(),\n }), []);\n\n return (\n <div className=\"border-t border-gray-200/80 bg-white px-3 py-3 sm:px-4 sm:py-4\">\n <div className=\"nextclaw-chat-input-bar-shell mx-auto w-full max-w-[min(1120px,100%)] [container:nextclaw-chat-input-bar/inline-size]\">\n <div className=\"overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-card\">\n <div className=\"relative\">\n <ChatInputBarTokenizedComposer\n ref={composerRef}\n nodes={props.composer.nodes}\n placeholder={props.composer.placeholder}\n disabled={props.composer.disabled}\n slashItems={props.slashMenu.items}\n onSlashItemSelect={props.slashMenu.onSelectItem}\n actions={props.toolbar.actions}\n activeSlashIndex={activeSlashIndex}\n onNodesChange={props.composer.onNodesChange}\n onFilesAdd={props.composer.onFilesAdd}\n onSlashQueryChange={(query) => {\n if (query === null && isSlashMenuInteractionRef.current) return;\n if (query !== null) setActiveSlashIndex(0);\n props.composer.onSlashQueryChange?.(query);\n }}\n onSlashTriggerChange={(trigger) => {\n setActiveSlashTriggerStart(trigger?.start ?? null);\n }}\n onSlashOpenChange={(open) => {\n if (!open) dismissSlashTrigger();\n }}\n onSlashActiveIndexChange={setActiveSlashIndex}\n />\n <ChatSlashMenu\n isOpen={isSlashPanelOpen}\n isLoading={props.slashMenu.isLoading}\n items={props.slashMenu.items}\n activeIndex={activeSlashIndex}\n activeItem={activeSlashItem}\n texts={props.slashMenu.texts}\n onSelectItem={(item) => {\n setDismissedSlashTriggerStart(null);\n composerRef.current?.insertSlashItem(item);\n }}\n onOpenChange={(open) => {\n if (!open) dismissSlashTrigger();\n }}\n onDetailsPointerDown={() => {\n isSlashMenuInteractionRef.current = true;\n requestAnimationFrame(() => { isSlashMenuInteractionRef.current = false; });\n }}\n onSetActiveIndex={setActiveSlashIndex}\n />\n </div>\n\n <InputBarHint hint={props.hint} />\n <ChatInputBarToolbar {...toolbar} />\n </div>\n </div>\n </div>\n );\n});\n\nChatInputBar.displayName = 'ChatInputBar';\n","import type { ChatMessageRole } from '../../view-models/chat-ui.types';\nimport { Bot, User, Wrench } from 'lucide-react';\n\nexport function ChatMessageAvatar({ role }: { role: ChatMessageRole }) {\n if (role === 'user') {\n return (\n <div\n data-testid=\"chat-message-avatar-user\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-white shadow-sm\"\n >\n <User className=\"h-4 w-4\" />\n </div>\n );\n }\n if (role === 'tool') {\n return (\n <div\n data-testid=\"chat-message-avatar-tool\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-amber-100 text-amber-700 shadow-sm\"\n >\n <Wrench className=\"h-4 w-4\" />\n </div>\n );\n }\n return (\n <div\n data-testid=\"chat-message-avatar-assistant\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-gray-700 to-gray-950 text-white shadow-md ring-1 ring-inset ring-white/20\"\n >\n <Bot className=\"h-[18px] w-[18px] text-white/95\" strokeWidth={2.5} />\n </div>\n );\n}\n","function canUseClipboardApi(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n typeof navigator.clipboard?.writeText === 'function'\n );\n}\n\nfunction restoreSelection(ranges: Range[]) {\n if (typeof document === 'undefined') {\n return;\n }\n\n const selection = document.getSelection();\n if (!selection) {\n return;\n }\n\n selection.removeAllRanges();\n ranges.forEach((range) => selection.addRange(range));\n}\n\nfunction fallbackCopyText(text: string): boolean {\n if (typeof document === 'undefined' || !document.body) {\n return false;\n }\n\n const activeElement = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const activeInput = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement\n ? activeElement\n : null;\n const activeSelection = activeInput\n ? {\n start: activeInput.selectionStart,\n end: activeInput.selectionEnd\n }\n : null;\n const selection = document.getSelection();\n const ranges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) => selection.getRangeAt(index).cloneRange())\n : [];\n\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.setAttribute('readonly', '');\n textarea.setAttribute('aria-hidden', 'true');\n textarea.style.position = 'fixed';\n textarea.style.top = '0';\n textarea.style.left = '-9999px';\n textarea.style.opacity = '0';\n textarea.style.pointerEvents = 'none';\n textarea.style.fontSize = '12pt';\n\n document.body.appendChild(textarea);\n\n try {\n textarea.focus({ preventScroll: true });\n } catch {\n textarea.focus();\n }\n\n textarea.select();\n textarea.setSelectionRange(0, textarea.value.length);\n\n let copied = false;\n try {\n copied = typeof document.execCommand === 'function' && document.execCommand('copy');\n } catch {\n copied = false;\n }\n\n textarea.remove();\n\n if (activeElement) {\n try {\n activeElement.focus({ preventScroll: true });\n } catch {\n activeElement.focus();\n }\n }\n\n if (activeInput && activeSelection) {\n activeInput.setSelectionRange(activeSelection.start, activeSelection.end);\n } else {\n restoreSelection(ranges);\n }\n\n return copied;\n}\n\nexport async function copyText(text: string): Promise<boolean> {\n if (!text) {\n return false;\n }\n\n if (canUseClipboardApi()) {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return fallbackCopyText(text);\n }\n }\n\n return fallbackCopyText(text);\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { copyText } from '../utils/copy-text';\n\ntype UseCopyFeedbackParams = {\n text: string;\n resetDelayMs?: number;\n};\n\ntype UseCopyFeedbackResult = {\n copied: boolean;\n copy: () => Promise<void>;\n};\n\nconst DEFAULT_RESET_DELAY_MS = 1300;\n\nexport function useCopyFeedback(params: UseCopyFeedbackParams): UseCopyFeedbackResult {\n const [copied, setCopied] = useState(false);\n\n const copy = useCallback(async () => {\n if (!params.text) {\n return;\n }\n\n const didCopy = await copyText(params.text);\n if (didCopy) {\n setCopied(true);\n } else {\n setCopied(false);\n }\n }, [params.text]);\n\n useEffect(() => {\n if (!copied || typeof window === 'undefined') {\n return;\n }\n\n const timer = window.setTimeout(() => setCopied(false), params.resetDelayMs ?? DEFAULT_RESET_DELAY_MS);\n return () => window.clearTimeout(timer);\n }, [copied, params.resetDelayMs]);\n\n return {\n copied,\n copy\n };\n}\n","import hljs from 'highlight.js/lib/core';\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport diff from 'highlight.js/lib/languages/diff';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport shell from 'highlight.js/lib/languages/shell';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport type { HLJSApi, LanguageFn } from 'highlight.js';\n\nconst PLAIN_TEXT_LANGUAGES = new Set([\n 'text',\n 'txt',\n 'plain',\n 'plaintext',\n 'none',\n 'output',\n]);\n\nconst AUTO_DETECT_LANGUAGES = [\n 'typescript',\n 'javascript',\n 'json',\n 'bash',\n 'shell',\n 'python',\n 'css',\n 'xml',\n 'markdown',\n 'yaml',\n 'sql',\n 'diff',\n];\n\nconst AUTO_DETECT_MIN_RELEVANCE = 4;\n\ntype RegisteredLanguage = {\n name: string;\n language: LanguageFn;\n aliases?: string[];\n};\n\nconst REGISTERED_LANGUAGES: RegisteredLanguage[] = [\n { name: 'typescript', language: typescript, aliases: ['ts', 'tsx'] },\n { name: 'javascript', language: javascript, aliases: ['js', 'jsx', 'mjs', 'cjs'] },\n { name: 'json', language: json, aliases: ['jsonc'] },\n { name: 'bash', language: bash, aliases: ['sh', 'zsh'] },\n { name: 'shell', language: shell, aliases: ['console', 'terminal'] },\n { name: 'python', language: python, aliases: ['py'] },\n { name: 'css', language: css },\n { name: 'xml', language: xml, aliases: ['html', 'svg'] },\n { name: 'markdown', language: markdown, aliases: ['md', 'mdx'] },\n { name: 'yaml', language: yaml, aliases: ['yml'] },\n { name: 'sql', language: sql },\n { name: 'diff', language: diff, aliases: ['patch'] },\n];\n\nexport type ChatCodeHighlightResult = {\n html: string;\n language: string;\n highlighted: boolean;\n};\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction normalizeLanguage(value: string): string {\n return value.trim().toLowerCase();\n}\n\nexport class ChatCodeSyntaxHighlighter {\n private readonly engine: HLJSApi;\n\n constructor() {\n this.engine = hljs.newInstance();\n REGISTERED_LANGUAGES.forEach((entry) => {\n this.engine.registerLanguage(entry.name, entry.language);\n if (entry.aliases) {\n this.engine.registerAliases(entry.aliases, { languageName: entry.name });\n }\n });\n }\n\n highlight = (code: string, language: string): ChatCodeHighlightResult => {\n const normalizedLanguage = normalizeLanguage(language);\n if (!code || PLAIN_TEXT_LANGUAGES.has(normalizedLanguage)) {\n return this.createPlainTextResult(code, normalizedLanguage || 'text');\n }\n\n if (this.engine.getLanguage(normalizedLanguage)) {\n const result = this.engine.highlight(code, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n });\n return {\n html: result.value,\n language: result.language ?? normalizedLanguage,\n highlighted: true,\n };\n }\n\n const autoDetected = this.engine.highlightAuto(code, AUTO_DETECT_LANGUAGES);\n if (autoDetected.language && autoDetected.relevance >= AUTO_DETECT_MIN_RELEVANCE) {\n return {\n html: autoDetected.value,\n language: autoDetected.language,\n highlighted: true,\n };\n }\n\n return this.createPlainTextResult(code, normalizedLanguage || 'text');\n };\n\n private createPlainTextResult = (code: string, language: string): ChatCodeHighlightResult => ({\n html: escapeHtml(code),\n language,\n highlighted: false,\n });\n}\n\nexport const chatCodeSyntaxHighlighter = new ChatCodeSyntaxHighlighter();\n","import { useMemo, type ReactNode } from 'react';\nimport { useCopyFeedback } from '../../hooks/use-copy-feedback';\nimport type { ChatMessageTexts } from '../../view-models/chat-ui.types';\nimport { Check, Copy } from 'lucide-react';\nimport { cn } from '../../internal/cn';\nimport { chatCodeSyntaxHighlighter } from './code-block/chat-code-syntax-highlighter';\n\nconst CODE_LANGUAGE_REGEX = /language-([a-z0-9-]+)/i;\n\nfunction flattenNodeText(value: ReactNode): string {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map(flattenNodeText).join('');\n }\n return '';\n}\n\nfunction normalizeCodeText(value: ReactNode): string {\n const content = flattenNodeText(value);\n return content.endsWith('\\n') ? content.slice(0, -1) : content;\n}\n\nfunction resolveCodeLanguage(className?: string): string {\n const match = className ? CODE_LANGUAGE_REGEX.exec(className) : null;\n return match?.[1]?.toLowerCase() || 'text';\n}\n\ntype ChatCodeBlockProps = {\n className?: string;\n children: ReactNode;\n texts: Pick<ChatMessageTexts, 'copyCodeLabel' | 'copiedCodeLabel'>;\n};\n\nexport function ChatCodeBlock({ className, children, texts }: ChatCodeBlockProps) {\n const language = useMemo(() => resolveCodeLanguage(className), [className]);\n const codeText = useMemo(() => normalizeCodeText(children), [children]);\n const highlightedCode = useMemo(\n () => chatCodeSyntaxHighlighter.highlight(codeText, language),\n [codeText, language],\n );\n const codeClassName = useMemo(() => {\n const highlightedLanguageClass = `language-${highlightedCode.language}`;\n return cn(\n 'hljs',\n className,\n className?.includes('language-') ? undefined : highlightedLanguageClass,\n );\n }, [className, highlightedCode.language]);\n const { copied, copy } = useCopyFeedback({ text: codeText });\n\n return (\n <div className=\"chat-codeblock\">\n <div className=\"chat-codeblock-toolbar\">\n <span className=\"chat-codeblock-language\">{language}</span>\n <button\n type=\"button\"\n className=\"chat-codeblock-copy\"\n onClick={() => void copy()}\n aria-label={copied ? texts.copiedCodeLabel : texts.copyCodeLabel}\n >\n {copied ? <Check className=\"h-3.5 w-3.5\" /> : <Copy className=\"h-3.5 w-3.5\" />}\n <span>{copied ? texts.copiedCodeLabel : texts.copyCodeLabel}</span>\n </button>\n </div>\n <pre>\n <code\n className={codeClassName}\n data-highlighted={highlightedCode.highlighted ? 'true' : 'false'}\n dangerouslySetInnerHTML={{ __html: highlightedCode.html }}\n />\n </pre>\n </div>\n );\n}\n","import { useMemo, type MouseEvent, type ReactNode } from 'react';\nimport type { Components } from 'react-markdown';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { cn } from '../../internal/cn';\nimport { ChatCodeBlock } from './chat-code-block';\nimport type {\n ChatFileOpenActionViewModel,\n ChatMessageRole,\n ChatMessageTexts,\n} from '../../view-models/chat-ui.types';\n\nconst MARKDOWN_MAX_CHARS = 140_000;\nconst SAFE_LINK_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\nfunction trimMarkdown(value: string): string {\n if (value.length <= MARKDOWN_MAX_CHARS) {\n return value;\n }\n return `${value.slice(0, MARKDOWN_MAX_CHARS)}\\n\\n...`;\n}\n\nfunction resolveSafeHref(href?: string): string | null {\n if (!href) {\n return null;\n }\n if (href.startsWith('#') || href.startsWith('/') || href.startsWith('./') || href.startsWith('../')) {\n return href;\n }\n try {\n const url = new URL(href);\n return SAFE_LINK_PROTOCOLS.has(url.protocol) ? href : null;\n } catch {\n return null;\n }\n}\n\nfunction isExternalHref(href: string): boolean {\n return /^https?:\\/\\//i.test(href);\n}\n\nfunction looksLikeLocalFileHref(href: string): boolean {\n return (\n href.startsWith('./') ||\n href.startsWith('../') ||\n href.startsWith('/Users/') ||\n href.startsWith('/home/') ||\n href.startsWith('/tmp/') ||\n href.startsWith('/var/') ||\n /^\\/.+\\.[A-Za-z0-9_-]+(?::\\d+(?::\\d+)?)?$/.test(href)\n );\n}\n\nfunction parseLocalFileAction(href: string): ChatFileOpenActionViewModel | null {\n const normalizedHref = href.split('#')[0]?.split('?')[0] ?? href;\n const decodedHref = decodeURIComponent(normalizedHref);\n if (!looksLikeLocalFileHref(decodedHref)) {\n return null;\n }\n const lineMatch = /^(.*?)(?::(\\d+)(?::(\\d+))?)$/.exec(decodedHref);\n const rawPath = lineMatch?.[1] ?? decodedHref;\n const line = lineMatch?.[2] ? Number(lineMatch[2]) : undefined;\n const column = lineMatch?.[3] ? Number(lineMatch[3]) : undefined;\n return {\n path: rawPath,\n label: rawPath.split('/').filter(Boolean).pop() ?? rawPath,\n viewMode: 'preview',\n ...(typeof line === 'number' ? { line } : {}),\n ...(typeof column === 'number' ? { column } : {}),\n };\n}\n\ntype ChatMessageMarkdownProps = {\n text: string;\n role: ChatMessageRole;\n texts: Pick<ChatMessageTexts, 'copyCodeLabel' | 'copiedCodeLabel'>;\n inline?: boolean;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n};\n\nexport function ChatMessageMarkdown({\n text,\n role,\n texts,\n inline = false,\n onFileOpen,\n}: ChatMessageMarkdownProps) {\n const isUser = role === 'user';\n const markdownComponents = useMemo<Components>(() => ({\n p: ({ children }) => (inline ? <>{children}</> : <p>{children}</p>),\n a: ({ href, children, ...rest }) => {\n const safeHref = resolveSafeHref(href);\n if (!safeHref) {\n return <span className=\"chat-link-invalid\">{children}</span>;\n }\n const external = isExternalHref(safeHref);\n const localFileAction = external ? null : parseLocalFileAction(safeHref);\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (!onFileOpen || !localFileAction) {\n return;\n }\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) {\n return;\n }\n event.preventDefault();\n onFileOpen(localFileAction);\n };\n return (\n <a\n {...rest}\n href={safeHref}\n onClick={handleClick}\n target={external ? '_blank' : undefined}\n rel={external ? 'noreferrer noopener' : undefined}\n >\n {children}\n </a>\n );\n },\n table: ({ children, ...rest }) => (\n <div className=\"chat-table-wrap\">\n <table {...rest}>{children}</table>\n </div>\n ),\n input: ({ type, checked, ...rest }) => {\n if (type !== 'checkbox') {\n return <input {...rest} type={type} />;\n }\n return <input {...rest} type=\"checkbox\" checked={checked} readOnly disabled className=\"chat-task-checkbox\" />;\n },\n img: ({ src, alt, ...rest }) => {\n const safeSrc = resolveSafeHref(src);\n if (!safeSrc) {\n return null;\n }\n return <img {...rest} src={safeSrc} alt={alt || ''} loading=\"lazy\" decoding=\"async\" />;\n },\n code: ({ className, children, ...rest }) => {\n const plainText = String(children ?? '');\n const isInlineCode = !className && !plainText.includes('\\n');\n if (isInlineCode) {\n return (\n <code {...rest} className={cn('chat-inline-code', className)}>\n {children}\n </code>\n );\n }\n return (\n <ChatCodeBlock className={className} texts={texts}>\n {children as ReactNode}\n </ChatCodeBlock>\n );\n }\n }), [inline, onFileOpen, texts]);\n\n const WrapperTag = inline ? 'span' : 'div';\n\n return (\n <WrapperTag className={cn('chat-markdown', isUser ? 'chat-markdown-user' : 'chat-markdown-assistant')}>\n <ReactMarkdown skipHtml remarkPlugins={[remarkGfm]} components={markdownComponents}>\n {trimMarkdown(text)}\n </ReactMarkdown>\n </WrapperTag>\n );\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatInlineContentSegmentViewModel,\n ChatMessageRole,\n ChatMessageTexts,\n} from \"../../view-models/chat-ui.types\";\nimport { cn } from \"../../internal/cn\";\nimport { ChatMessageMarkdown } from \"./chat-message-markdown\";\n\ntype ChatMessageInlineContentProps = {\n segments: ChatInlineContentSegmentViewModel[];\n role: ChatMessageRole;\n texts: Pick<ChatMessageTexts, \"copyCodeLabel\" | \"copiedCodeLabel\">;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n};\n\nfunction hasVisibleInlineText(value: string): boolean {\n return value\n .split(\"\\u200B\")\n .join(\"\")\n .split(\"\\u200C\")\n .join(\"\")\n .split(\"\\u200D\")\n .join(\"\")\n .split(\"\\u2060\")\n .join(\"\")\n .split(\"\\uFEFF\")\n .join(\"\").length > 0;\n}\n\nfunction ChatInlineSkillIcon() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M8.5 2.75 2.75 6l5.75 3.25L14.25 6 8.5 2.75Z\" />\n <path d=\"M2.75 10 8.5 13.25 14.25 10\" />\n <path d=\"M2.75 6v4l5.75 3.25V9.25L2.75 6Z\" />\n <path d=\"M14.25 6v4L8.5 13.25V9.25L14.25 6Z\" />\n </svg>\n );\n}\n\nfunction ChatInlineTokenBadge({\n kind,\n label,\n isUser,\n}: {\n kind: string;\n label: string;\n isUser: boolean;\n}) {\n const isSkill = kind === \"skill\";\n return (\n <span\n className={cn(\n \"mx-[2px] inline-flex h-7 max-w-full items-center gap-1.5 rounded-xl border px-2.5 align-baseline text-[11px] font-medium shadow-[0_0_0_1px_rgba(15,23,42,0.03)]\",\n isSkill\n ? isUser\n ? \"border-emerald-200/35 bg-emerald-400/18 text-emerald-50/95\"\n : \"border-emerald-200/70 bg-emerald-50 text-emerald-700\"\n : isUser\n ? \"border-white/30 bg-white/18 text-white\"\n : \"border-slate-200/80 bg-slate-100 text-slate-700\",\n )}\n title={label}\n >\n <span\n className={cn(\n \"inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center\",\n isSkill\n ? isUser\n ? \"text-emerald-100/90\"\n : \"text-emerald-600\"\n : isUser\n ? \"text-white/70\"\n : \"text-slate-500\",\n )}\n >\n <ChatInlineSkillIcon />\n </span>\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n\nexport function ChatMessageInlineContent({\n segments,\n role,\n texts,\n onFileOpen,\n}: ChatMessageInlineContentProps) {\n const isUser = role === \"user\";\n\n return (\n <div className=\"whitespace-pre-wrap break-words leading-6\">\n {segments.map((segment, index) => {\n if (segment.type === \"token\") {\n return (\n <ChatInlineTokenBadge\n key={`token-${index}-${segment.token.kind}-${segment.token.key}`}\n kind={segment.token.kind}\n label={segment.token.label}\n isUser={isUser}\n />\n );\n }\n if (!hasVisibleInlineText(segment.text)) {\n return (\n <span key={`space-${index}`} className=\"whitespace-pre-wrap\">\n {segment.text}\n </span>\n );\n }\n return (\n <ChatMessageMarkdown\n key={`markdown-${index}`}\n text={segment.text}\n role={role}\n texts={texts}\n inline\n onFileOpen={onFileOpen}\n />\n );\n })}\n </div>\n );\n}\n","import type {\n ChatAttachmentCategory,\n ChatMessagePartViewModel,\n} from \"../../../view-models/chat-ui.types\";\n\nexport type ChatMessageFileView = Extract<\n ChatMessagePartViewModel,\n { type: \"file\" }\n>[\"file\"];\n\nexport type FileCategory = ChatAttachmentCategory;\n\nexport const FILE_CATEGORY_TILE_CLASSES: Record<FileCategory, string> = {\n archive: \"border-amber-200/80 bg-amber-50 text-amber-700\",\n audio: \"border-fuchsia-200/80 bg-fuchsia-50 text-fuchsia-700\",\n code: \"border-cyan-200/80 bg-cyan-50 text-cyan-700\",\n data: \"border-slate-200/80 bg-slate-50 text-slate-700\",\n document: \"border-blue-200/80 bg-blue-50 text-blue-700\",\n generic: \"border-slate-200/80 bg-slate-50 text-slate-700\",\n image: \"border-emerald-200/80 bg-emerald-50 text-emerald-700\",\n pdf: \"border-rose-200/80 bg-rose-50 text-rose-700\",\n sheet: \"border-lime-200/80 bg-lime-50 text-lime-700\",\n video: \"border-violet-200/80 bg-violet-50 text-violet-700\",\n};\n\nconst CODE_EXTENSIONS = new Set([\n \"c\",\n \"cpp\",\n \"css\",\n \"go\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"md\",\n \"php\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"svg\",\n \"ts\",\n \"tsx\",\n]);\n\nconst DATA_EXTENSIONS = new Set([\n \"graphql\",\n \"json\",\n \"toml\",\n \"xml\",\n \"yaml\",\n \"yml\",\n]);\nconst IMAGE_EXTENSIONS = new Set([\n \"avif\",\n \"bmp\",\n \"gif\",\n \"heic\",\n \"heif\",\n \"ico\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"tif\",\n \"tiff\",\n \"webp\",\n]);\nconst AUDIO_EXTENSIONS = new Set([\n \"aac\",\n \"flac\",\n \"m4a\",\n \"mp3\",\n \"ogg\",\n \"opus\",\n \"wav\",\n \"weba\",\n]);\nconst VIDEO_EXTENSIONS = new Set([\n \"avi\",\n \"m4v\",\n \"mov\",\n \"mp4\",\n \"mkv\",\n \"webm\",\n \"wmv\",\n]);\nconst DOCUMENT_EXTENSIONS = new Set([\n \"doc\",\n \"docx\",\n \"odt\",\n \"pages\",\n \"rtf\",\n \"txt\",\n]);\nconst SHEET_EXTENSIONS = new Set([\n \"csv\",\n \"numbers\",\n \"ods\",\n \"tsv\",\n \"xls\",\n \"xlsx\",\n]);\nconst ARCHIVE_EXTENSIONS = new Set([\n \"7z\",\n \"bz2\",\n \"gz\",\n \"rar\",\n \"tar\",\n \"tgz\",\n \"zip\",\n]);\n\nfunction formatFileSize(sizeBytes?: number): string | null {\n if (!Number.isFinite(sizeBytes) || sizeBytes == null || sizeBytes < 0) {\n return null;\n }\n if (sizeBytes === 0) {\n return \"0 B\";\n }\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let value = sizeBytes;\n let unitIndex = 0;\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n const digits = value >= 10 || unitIndex === 0 ? 0 : 1;\n return `${value.toFixed(digits).replace(/\\.0$/, \"\")} ${units[unitIndex]}`;\n}\n\nfunction getFileExtension(label: string, mimeType: string): string {\n const extension = readFileExtension(label);\n if (extension) {\n return extension.toUpperCase();\n }\n const subtype = mimeType.split(\"/\")[1] ?? \"\";\n const cleaned = subtype.split(/[+.;-]/)[0]?.trim();\n if (!cleaned) {\n return \"FILE\";\n }\n return cleaned.slice(0, 6).toUpperCase();\n}\n\nfunction readFileExtension(label: string): string {\n return /\\.([a-z0-9]{1,12})$/i.exec(label.trim())?.[1]?.toLowerCase() ?? \"\";\n}\n\nfunction truncateDisplayCode(value: string): string {\n return value.trim().slice(0, 4).toUpperCase();\n}\n\nfunction isImageDataUrl(dataUrl?: string): boolean {\n return typeof dataUrl === \"string\" && /^data:image\\//i.test(dataUrl.trim());\n}\n\nfunction inferMimeTypeFromExtension(extension: string): string | null {\n if (IMAGE_EXTENSIONS.has(extension)) {\n if (extension === \"jpg\" || extension === \"jpeg\") {\n return \"image/jpeg\";\n }\n if (extension === \"svg\") {\n return \"image/svg+xml\";\n }\n return `image/${extension}`;\n }\n if (AUDIO_EXTENSIONS.has(extension)) {\n if (extension === \"mp3\") {\n return \"audio/mpeg\";\n }\n if (extension === \"m4a\") {\n return \"audio/mp4\";\n }\n if (extension === \"weba\") {\n return \"audio/webm\";\n }\n return `audio/${extension}`;\n }\n if (VIDEO_EXTENSIONS.has(extension)) {\n if (extension === \"mov\") {\n return \"video/quicktime\";\n }\n if (extension === \"m4v\") {\n return \"video/mp4\";\n }\n return `video/${extension}`;\n }\n if (extension === \"pdf\") {\n return \"application/pdf\";\n }\n return null;\n}\n\nexport function inferMimeTypeFromFileName(fileName: string): string | null {\n const extension = readFileExtension(fileName);\n if (!extension) {\n return null;\n }\n return inferMimeTypeFromExtension(extension);\n}\n\nexport function resolveRenderableMimeType(file: ChatMessageFileView): string | null {\n const normalizedMimeType = file.mimeType.trim().toLowerCase();\n if (\n normalizedMimeType.length > 0 &&\n normalizedMimeType !== \"application/octet-stream\"\n ) {\n return normalizedMimeType;\n }\n return inferMimeTypeFromFileName(file.label);\n}\n\nexport function isImageFileLike(file: ChatMessageFileView): boolean {\n const normalizedMimeType = file.mimeType.trim().toLowerCase();\n const extension = readFileExtension(file.label);\n return (\n file.isImage ||\n normalizedMimeType.startsWith(\"image/\") ||\n IMAGE_EXTENSIONS.has(extension) ||\n isImageDataUrl(file.dataUrl)\n );\n}\n\nfunction resolveFileCategory(label: string, mimeType: string): FileCategory {\n const extension = readFileExtension(label);\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedMimeType.startsWith(\"image/\") || IMAGE_EXTENSIONS.has(extension)) {\n return \"image\";\n }\n if (normalizedMimeType.startsWith(\"audio/\") || AUDIO_EXTENSIONS.has(extension)) {\n return \"audio\";\n }\n if (normalizedMimeType.startsWith(\"video/\") || VIDEO_EXTENSIONS.has(extension)) {\n return \"video\";\n }\n if (normalizedMimeType.includes(\"pdf\") || extension === \"pdf\") {\n return \"pdf\";\n }\n if (\n ARCHIVE_EXTENSIONS.has(extension) ||\n /(zip|tar|gzip|rar|compressed|archive)/.test(normalizedMimeType)\n ) {\n return \"archive\";\n }\n if (\n SHEET_EXTENSIONS.has(extension) ||\n /(spreadsheet|sheet|excel|csv)/.test(normalizedMimeType)\n ) {\n return \"sheet\";\n }\n if (\n DATA_EXTENSIONS.has(extension) ||\n /(json|xml|yaml|toml)/.test(normalizedMimeType)\n ) {\n return \"data\";\n }\n if (\n CODE_EXTENSIONS.has(extension) ||\n /(javascript|typescript|jsx|tsx|css|html)/.test(normalizedMimeType)\n ) {\n return \"code\";\n }\n if (\n DOCUMENT_EXTENSIONS.has(extension) ||\n /(msword|document|opendocument|rtf|text\\/)/.test(normalizedMimeType)\n ) {\n return \"document\";\n }\n return \"generic\";\n}\n\nexport function buildChatMessageFileMeta(file: ChatMessageFileView): {\n category: FileCategory;\n extension: string;\n sizeLabel: string | null;\n} {\n const category = resolveFileCategory(file.label, file.mimeType);\n const sizeLabel = formatFileSize(file.sizeBytes);\n return {\n category,\n extension: getFileExtension(file.label, file.mimeType),\n sizeLabel,\n };\n}\n\nexport function getFileCategoryDisplayCode(\n category: FileCategory,\n extension: string,\n): string {\n if (category === \"image\") {\n return \"IMG\";\n }\n if (category === \"video\") {\n return \"VID\";\n }\n if (category === \"audio\") {\n return \"AUD\";\n }\n if (category === \"generic\") {\n return truncateDisplayCode(extension || \"FILE\");\n }\n return truncateDisplayCode(extension);\n}\n","import { cn } from \"../../../internal/cn\";\nimport {\n File,\n FileArchive,\n FileAudio2,\n FileCode2,\n FileImage,\n FileJson2,\n FileSpreadsheet,\n FileText,\n FileVideo2,\n} from \"lucide-react\";\nimport {\n buildChatMessageFileMeta,\n FILE_CATEGORY_TILE_CLASSES,\n isImageFileLike,\n resolveRenderableMimeType,\n type FileCategory,\n type ChatMessageFileView,\n} from \"./meta\";\nimport type { ChatMessageTexts } from \"../../../view-models/chat-ui.types\";\n\ntype ChatMessageFileProps = {\n file: ChatMessageFileView;\n isUser?: boolean;\n texts?: Pick<\n ChatMessageTexts,\n \"attachmentOpenLabel\" | \"attachmentAttachedLabel\" | \"attachmentCategoryLabels\"\n >;\n};\n\nconst DEFAULT_FILE_CATEGORY_LABELS: Record<FileCategory, string> = {\n archive: \"Archive\",\n audio: \"Audio\",\n code: \"Code file\",\n data: \"Data file\",\n document: \"Document\",\n generic: \"File\",\n image: \"Image\",\n pdf: \"PDF document\",\n sheet: \"Spreadsheet\",\n video: \"Video\",\n};\n\nconst FILE_CATEGORY_ICONS: Record<FileCategory, typeof File> = {\n archive: FileArchive,\n audio: FileAudio2,\n code: FileCode2,\n data: FileJson2,\n document: FileText,\n generic: File,\n image: FileImage,\n pdf: FileText,\n sheet: FileSpreadsheet,\n video: FileVideo2,\n};\n\nfunction readFileCategoryLabel(\n category: FileCategory,\n texts?: ChatMessageFileProps[\"texts\"],\n): string {\n return (\n texts?.attachmentCategoryLabels?.[category] ??\n DEFAULT_FILE_CATEGORY_LABELS[category]\n );\n}\n\nfunction renderMetaLine(\n categoryLabel: string,\n sizeLabel: string | null,\n isUser: boolean,\n) {\n return (\n <div\n className={cn(\n \"mt-1 text-xs leading-5\",\n isUser ? \"text-white/70\" : \"text-slate-500\",\n )}\n >\n {sizeLabel ? `${categoryLabel} · ${sizeLabel}` : categoryLabel}\n </div>\n );\n}\n\nfunction renderActionPill(\n label: string,\n isUser: boolean,\n isInteractive: boolean,\n) {\n return (\n <span\n className={cn(\n \"inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium\",\n isInteractive\n ? isUser\n ? \"border-white/14 bg-white/12 text-white\"\n : \"border-slate-200/80 bg-white text-slate-700\"\n : isUser\n ? \"border-white/10 bg-white/6 text-white/62\"\n : \"border-slate-200/70 bg-slate-100/80 text-slate-500\",\n )}\n >\n {label}\n </span>\n );\n}\n\nfunction renderActionLink(\n label: string,\n href: string,\n isUser: boolean,\n) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n \"inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium transition duration-200\",\n isUser\n ? \"border-white/14 bg-white/12 text-white hover:border-white/20 hover:bg-white/16\"\n : \"border-slate-200/80 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50\",\n )}\n >\n {label}\n </a>\n );\n}\n\nfunction FileCategoryGlyph({\n category,\n isUser,\n}: {\n category: FileCategory;\n isUser: boolean;\n}) {\n const Icon = FILE_CATEGORY_ICONS[category];\n\n return (\n <div\n className={cn(\n \"flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border\",\n isUser\n ? \"border-white/12 bg-white/10 text-white\"\n : FILE_CATEGORY_TILE_CLASSES[category],\n )}\n >\n <Icon\n className={cn(\n \"h-7 w-7\",\n isUser ? \"text-white/92\" : \"text-current\",\n )}\n strokeWidth={2.2}\n />\n </div>\n );\n}\n\nfunction renderImagePreview(params: {\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n}) {\n const { file, categoryLabel, sizeLabel, isUser } = params;\n if (!file.dataUrl) {\n return null;\n }\n return (\n <a\n href={file.dataUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"group block\"\n >\n <div\n className={cn(\n \"relative overflow-hidden rounded-[1rem]\",\n isUser\n ? \"ring-1 ring-white/10\"\n : \"bg-slate-100/80 ring-1 ring-slate-200/80\",\n )}\n >\n <img\n src={file.dataUrl}\n alt={file.label}\n className=\"block h-auto max-h-[26rem] w-full rounded-[1rem] bg-transparent object-contain transition duration-300 group-hover:scale-[1.01]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-3 flex items-center gap-2\">\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-1 text-[10px] font-semibold tracking-[0.18em] text-white backdrop-blur-sm\",\n isUser ? \"bg-slate-950/36\" : \"bg-slate-950/58\",\n )}\n >\n {categoryLabel}\n </span>\n {sizeLabel ? (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-1 text-[10px] font-medium text-white/92 backdrop-blur-sm\",\n isUser ? \"bg-slate-950/28\" : \"bg-slate-950/46\",\n )}\n >\n {sizeLabel}\n </span>\n ) : null}\n </div>\n </div>\n </a>\n );\n}\n\nfunction renderFileCardHeader(params: {\n category: FileCategory;\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n action: React.ReactNode;\n}) {\n const { category, file, categoryLabel, sizeLabel, isUser, action } = params;\n return (\n <div className=\"flex items-center gap-3 p-3.5\">\n <FileCategoryGlyph\n category={category}\n isUser={isUser}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[15px] font-semibold leading-5\">\n {file.label}\n </div>\n {renderMetaLine(categoryLabel, sizeLabel, isUser)}\n </div>\n {action}\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderInlineMediaCard(params: {\n category: FileCategory;\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n shellClasses: string;\n actionLabel: string;\n}) {\n const { category, file, categoryLabel, sizeLabel, isUser, shellClasses, actionLabel } = params;\n if (!file.dataUrl || (category !== \"audio\" && category !== \"video\")) {\n return null;\n }\n const mediaMimeType = resolveRenderableMimeType(file);\n return (\n <div className={shellClasses}>\n {renderFileCardHeader({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n action: renderActionLink(actionLabel, file.dataUrl, isUser),\n })}\n <div className=\"px-3.5 pb-3.5\">\n {category === \"audio\" ? (\n <audio\n controls\n preload=\"metadata\"\n aria-label={file.label}\n className=\"block w-full\"\n >\n <source\n src={file.dataUrl}\n {...(mediaMimeType ? { type: mediaMimeType } : {})}\n />\n </audio>\n ) : (\n <div\n className={cn(\n \"overflow-hidden rounded-[1rem] border\",\n isUser\n ? \"border-white/10 bg-slate-950/26\"\n : \"border-slate-200/80 bg-slate-100/80\",\n )}\n >\n <video\n controls\n preload=\"metadata\"\n playsInline\n aria-label={file.label}\n className=\"block max-h-[28rem] w-full bg-black\"\n >\n <source\n src={file.dataUrl}\n {...(mediaMimeType ? { type: mediaMimeType } : {})}\n />\n </video>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport function ChatMessageFile({\n file,\n isUser = false,\n texts,\n}: ChatMessageFileProps) {\n const { category, sizeLabel } = buildChatMessageFileMeta(file);\n const renderAsImage = isImageFileLike(file) && Boolean(file.dataUrl);\n const renderAsAudio = category === \"audio\" && Boolean(file.dataUrl);\n const renderAsVideo = category === \"video\" && Boolean(file.dataUrl);\n const isInteractive = Boolean(file.dataUrl);\n const actionLabel = isInteractive\n ? texts?.attachmentOpenLabel ?? \"Open\"\n : texts?.attachmentAttachedLabel ?? \"Attached\";\n const categoryLabel = readFileCategoryLabel(category, texts);\n const shellClasses = cn(\n \"block overflow-hidden rounded-[1.25rem] border transition duration-200\",\n isUser\n ? \"border-white/12 bg-white/10 text-white\"\n : \"border-slate-200/80 bg-white/95 text-slate-900\",\n isInteractive &&\n (isUser\n ? \"hover:border-white/18 hover:bg-white/13\"\n : \"hover:border-slate-300 hover:bg-white\"),\n );\n\n if (renderAsImage) {\n return renderImagePreview({ file, categoryLabel, sizeLabel, isUser });\n }\n\n if (renderAsAudio || renderAsVideo) {\n return renderInlineMediaCard({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n shellClasses,\n actionLabel,\n });\n }\n\n const content = renderFileCardHeader({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n action: renderActionPill(actionLabel, isUser, isInteractive),\n });\n\n if (!isInteractive || !file.dataUrl) {\n return <div className={shellClasses}>{content}</div>;\n }\n\n return (\n <a\n href={file.dataUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(shellClasses, \"group\")}\n >\n {content}\n </a>\n );\n}\n","import { useEffect, useRef, useState, type MouseEvent } from \"react\";\n\ntype UseReasoningBlockOpenStateParams = {\n isInProgress: boolean;\n};\n\ntype UseReasoningBlockOpenStateResult = {\n isOpen: boolean;\n onSummaryClick: (event: MouseEvent<HTMLElement>) => void;\n};\n\nexport function useReasoningBlockOpenState(\n params: UseReasoningBlockOpenStateParams,\n): UseReasoningBlockOpenStateResult {\n const { isInProgress } = params;\n const [isOpen, setIsOpen] = useState(isInProgress);\n const [keepOpenAfterCompletion, setKeepOpenAfterCompletion] = useState(false);\n const previousInProgressRef = useRef(isInProgress);\n\n useEffect(() => {\n const wasInProgress = previousInProgressRef.current;\n if (!wasInProgress && isInProgress) {\n setIsOpen(true);\n setKeepOpenAfterCompletion(false);\n } else if (wasInProgress && !isInProgress && !keepOpenAfterCompletion) {\n setIsOpen(false);\n }\n previousInProgressRef.current = isInProgress;\n }, [isInProgress, keepOpenAfterCompletion]);\n\n function onSummaryClick(event: MouseEvent<HTMLElement>) {\n event.preventDefault();\n const nextOpen = !isOpen;\n setIsOpen(nextOpen);\n\n if (!nextOpen) {\n setKeepOpenAfterCompletion(false);\n return;\n }\n\n if (isInProgress) {\n setKeepOpenAfterCompletion(true);\n }\n }\n\n return {\n isOpen,\n onSummaryClick,\n };\n}\n","import { useEffect, useLayoutEffect, useRef, type RefObject } from \"react\";\n\ntype UseStickyBottomScrollParams = {\n scrollRef: RefObject<HTMLElement>;\n resetKey: string | null;\n isLoading: boolean;\n hasContent: boolean;\n contentVersion: unknown;\n stickyThresholdPx?: number;\n};\n\ntype UseStickyBottomScrollResult = {\n onScroll: () => void;\n};\n\nconst DEFAULT_STICKY_THRESHOLD_PX = 10;\n\nfunction scrollElementToBottom(element: HTMLElement) {\n element.scrollTop = element.scrollHeight;\n}\n\nfunction queueScrollToBottom(params: {\n scrollRef: RefObject<HTMLElement>;\n scheduledScrollFrameRef: { current: number | null };\n isProgrammaticScrollRef: { current: boolean };\n}) {\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n if (params.scheduledScrollFrameRef.current !== null) {\n cancelAnimationFrame(params.scheduledScrollFrameRef.current);\n }\n\n params.scheduledScrollFrameRef.current = requestAnimationFrame(() => {\n params.scheduledScrollFrameRef.current = null;\n const currentElement = params.scrollRef.current;\n if (!currentElement) {\n return;\n }\n\n params.isProgrammaticScrollRef.current = true;\n scrollElementToBottom(currentElement);\n });\n}\n\nexport function useStickyBottomScroll(\n params: UseStickyBottomScrollParams,\n): UseStickyBottomScrollResult {\n const isStickyRef = useRef(true);\n const isProgrammaticScrollRef = useRef(false);\n const previousResetKeyRef = useRef<string | null>(null);\n const pendingInitialScrollRef = useRef(false);\n const scheduledScrollFrameRef = useRef<number | null>(null);\n\n const onScroll = () => {\n if (isProgrammaticScrollRef.current) {\n isProgrammaticScrollRef.current = false;\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n const distanceFromBottom =\n element.scrollHeight - element.scrollTop - element.clientHeight;\n isStickyRef.current =\n distanceFromBottom <=\n (params.stickyThresholdPx ?? DEFAULT_STICKY_THRESHOLD_PX);\n };\n\n useEffect(() => {\n if (previousResetKeyRef.current === params.resetKey) {\n return;\n }\n\n previousResetKeyRef.current = params.resetKey;\n isStickyRef.current = true;\n pendingInitialScrollRef.current = true;\n }, [params.resetKey]);\n\n useEffect(() => {\n const scheduledScrollFrame = scheduledScrollFrameRef.current;\n return () => {\n if (scheduledScrollFrame !== null) {\n cancelAnimationFrame(scheduledScrollFrame);\n }\n };\n }, []);\n\n useLayoutEffect(() => {\n if (\n !pendingInitialScrollRef.current ||\n params.isLoading ||\n !params.hasContent\n ) {\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n pendingInitialScrollRef.current = false;\n queueScrollToBottom({\n scrollRef: params.scrollRef,\n scheduledScrollFrameRef,\n isProgrammaticScrollRef,\n });\n }, [params.hasContent, params.isLoading, params.scrollRef]);\n\n useLayoutEffect(() => {\n if (!isStickyRef.current || !params.hasContent) {\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n queueScrollToBottom({\n scrollRef: params.scrollRef,\n scheduledScrollFrameRef,\n isProgrammaticScrollRef,\n });\n }, [params.contentVersion, params.hasContent, params.scrollRef]);\n\n return { onScroll };\n}\n","import { useRef } from \"react\";\nimport { useReasoningBlockOpenState } from \"../../hooks/use-reasoning-block-open-state\";\nimport { useStickyBottomScroll } from \"../../hooks/use-sticky-bottom-scroll\";\nimport { cn } from \"../../internal/cn\";\n\ntype ChatReasoningBlockProps = {\n label: string;\n text: string;\n isUser: boolean;\n isInProgress: boolean;\n};\n\nfunction normalizeReasoningLabel(label: string): string {\n const normalizedLabel = label.trim().toLowerCase();\n if (\n normalizedLabel === \"reasoning\" ||\n normalizedLabel === \"thinking\" ||\n normalizedLabel === \"推理\" ||\n normalizedLabel === \"推理过程\" ||\n normalizedLabel === \"思考过程\" ||\n normalizedLabel === \"思考\"\n ) {\n return \"思考\";\n }\n return label;\n}\n\nexport function ChatReasoningBlock({ label, text, isUser, isInProgress }: ChatReasoningBlockProps) {\n const { isOpen, onSummaryClick } = useReasoningBlockOpenState({\n isInProgress,\n });\n const scrollRef = useRef<HTMLDivElement>(null);\n const displayLabel = normalizeReasoningLabel(label);\n const { onScroll } = useStickyBottomScroll({\n scrollRef,\n resetKey: `${displayLabel}:${isInProgress ? \"streaming\" : \"idle\"}`,\n isLoading: false,\n hasContent: text.length > 0,\n contentVersion: text,\n stickyThresholdPx: 20,\n });\n\n return (\n <details className=\"mt-2\" open={isOpen}>\n <summary\n className={cn(\"cursor-pointer text-xs\", isUser ? \"text-primary-100\" : \"text-gray-500\")}\n onClick={onSummaryClick}\n >\n {displayLabel}\n </summary>\n <div\n ref={scrollRef}\n onScroll={onScroll}\n data-reasoning-scroll=\"true\"\n className={cn(\n \"mt-2 w-fit max-w-[500px] max-h-56 overflow-y-auto rounded-lg custom-scrollbar-amber\",\n isUser ? \"bg-primary-700/60\" : \"bg-gray-100\",\n )}\n >\n <pre className=\"min-w-0 whitespace-pre-wrap break-all p-2 text-[11px]\">{text}</pre>\n </div>\n </details>\n );\n}\n","import { cn } from '../../../internal/cn';\nimport type { ReactNode } from 'react';\n\nexport function ToolCardRoot({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <div \n className={cn(\n \"my-2 rounded-lg border border-amber-200/50 bg-amber-100/30 shadow-sm overflow-hidden text-[12px]\",\n \"w-[280px] sm:w-[360px] md:w-[480px] min-w-full max-w-full transition-all flex flex-col\",\n className\n )}\n >\n {children}\n </div>\n );\n}\n\nexport function ToolCardContent({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <div className={cn(\"border-t border-amber-200/15 bg-amber-50/50 px-3 pt-1 pb-2 w-full overflow-hidden\", className)}>\n {children}\n </div>\n );\n}\n","import { Check, Loader2, AlertTriangle, Minus } from 'lucide-react';\nimport { cn } from '../../../internal/cn';\nimport type { ChatToolPartViewModel } from '../../../view-models/chat-ui.types';\n\nexport const STATUS_STYLES = {\n running: { text: 'text-amber-500/80', icon: Loader2, spin: true },\n success: { text: 'text-amber-500/80', icon: Check, spin: false },\n error: { text: 'text-amber-500/80', icon: AlertTriangle, spin: false },\n cancelled: { text: 'text-amber-500/80', icon: Minus, spin: false }\n} as const;\n\nexport function ToolStatusLabel({ card }: { card: ChatToolPartViewModel }) {\n const style = STATUS_STYLES[card.statusTone] || STATUS_STYLES.cancelled;\n const Icon = style.icon;\n\n return (\n <span className={cn('inline-flex items-center gap-1.5 text-[11px] font-medium leading-none shrink-0', style.text)}>\n <Icon className={cn(\"h-3.5 w-3.5\", style.spin && \"animate-spin\")} strokeWidth={3} />\n {card.statusTone === 'running' ? card.statusLabel : null}\n </span>\n );\n}\n","import { ArrowUpRight, ChevronDown, ChevronRight, type LucideIcon } from 'lucide-react';\nimport type { MouseEvent, ReactNode } from 'react';\nimport { cn } from '../../../internal/cn';\nimport { ToolStatusLabel } from './tool-card-status';\nimport type {\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../../view-models/chat-ui.types';\n\nfunction ToolCardSessionActionButton({\n action,\n onAction,\n}: {\n action: ChatToolActionViewModel;\n onAction: (action: ChatToolActionViewModel) => void;\n}) {\n const isChildSession = action.sessionKind === 'child';\n const label = isChildSession ? 'Open child session' : 'Open session';\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onAction(action);\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.08em] transition-colors',\n 'border-amber-200/80 bg-white/80 text-amber-800 hover:bg-amber-50',\n )}\n aria-label={label}\n title={label}\n >\n <ArrowUpRight className=\"h-3 w-3\" strokeWidth={2.5} />\n </button>\n );\n}\n\nexport function ToolCardHeader({ \n card, \n icon: Icon, \n expanded, \n canExpand,\n hideSummary = false,\n actionSlot,\n onToggle \n}: { \n card: ChatToolPartViewModel; \n icon: LucideIcon; \n expanded: boolean; \n canExpand: boolean;\n hideSummary?: boolean;\n actionSlot?: ReactNode;\n onToggle: () => void; \n}) {\n const summaryPart = hideSummary\n ? ''\n : card.summary?.replace(/^(command|path|args|query|input):\\s*/i, '') ?? '';\n\n return (\n <div \n className={cn(\n \"flex items-center gap-3 px-3 py-2.5 transition-colors bg-transparent\", \n canExpand ? \"cursor-pointer hover:bg-amber-100/30\" : \"\"\n )}\n onClick={onToggle}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-2 overflow-hidden font-mono text-amber-950/80\">\n <Icon className=\"h-4 w-4 text-amber-600/80 shrink-0\" strokeWidth={3} />\n <div className=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden\">\n <span className=\"font-bold shrink-0 tracking-tight\">{card.toolName}</span>\n {summaryPart && (\n <>\n <span className=\"text-amber-300 font-bold select-none shrink-0\">›</span>\n <span className=\"block min-w-0 flex-1 truncate font-normal\" title={summaryPart}>\n {summaryPart}\n </span>\n </>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 shrink-0\">\n {actionSlot}\n <ToolStatusLabel card={card} />\n {canExpand && (\n expanded ? (\n <ChevronDown className=\"h-4 w-4 text-amber-400/80\" strokeWidth={3} />\n ) : (\n <ChevronRight className=\"h-4 w-4 text-amber-400/80\" strokeWidth={3} />\n )\n )}\n </div>\n </div>\n );\n}\n\nexport function ToolCardHeaderSessionAction({\n action,\n onAction,\n}: {\n action: ChatToolActionViewModel;\n onAction: (action: ChatToolActionViewModel) => void;\n}) {\n return <ToolCardSessionActionButton action={action} onAction={onAction} />;\n}\n","import type {\n ChatFileOperationBlockViewModel,\n ChatFileOperationLineViewModel,\n} from \"../../../view-models/chat-ui.types\";\nimport { cn } from \"../../../internal/cn\";\n\nconst FILE_TEXT_CLASS_NAME = \"font-mono text-[11px] leading-5\";\nconst FILE_ROW_CLASS_NAME = `flex h-5 w-full ${FILE_TEXT_CLASS_NAME}`;\nconst FILE_LINE_NUMBER_CELL_CLASS_NAME =\n \"flex h-5 items-center justify-center px-2.5 tabular-nums select-none\";\n\nfunction readVisibleLineNumber(line: ChatFileOperationLineViewModel): string {\n const value = line.newLineNumber ?? line.oldLineNumber;\n return typeof value === \"number\" ? String(value) : \"\";\n}\n\nfunction readLineKey(\n prefix: string,\n line: ChatFileOperationLineViewModel,\n index: number,\n): string {\n return `${prefix}-${index}-${line.oldLineNumber ?? \"x\"}-${line.newLineNumber ?? \"x\"}`;\n}\n\nfunction hasVisibleLineNumber(line: ChatFileOperationLineViewModel): boolean {\n return (\n typeof line.newLineNumber === \"number\" ||\n typeof line.oldLineNumber === \"number\"\n );\n}\n\nfunction readHasBlockLineNumbers(block: ChatFileOperationBlockViewModel): boolean {\n return block.lines.some(hasVisibleLineNumber);\n}\n\nfunction readLineNumberColumnWidth(\n block: ChatFileOperationBlockViewModel,\n): string {\n const maxDigits = block.lines.reduce((currentMax, line) => {\n if (!hasVisibleLineNumber(line)) {\n return currentMax;\n }\n return Math.max(currentMax, readVisibleLineNumber(line).length);\n }, 0);\n const width = Math.max(6.5, Math.min(8, maxDigits + 3.5));\n return `${width}ch`;\n}\n\nfunction readCodeColumnWidth(block: ChatFileOperationBlockViewModel): string {\n const maxColumns = block.lines.reduce(\n (currentMax, line) => Math.max(currentMax, Math.max(1, line.text.length)),\n 1,\n );\n return `calc(${maxColumns}ch + 1.25rem)`;\n}\n\nfunction getLineNumberTone(line: ChatFileOperationLineViewModel): string {\n if (line.kind === \"remove\") {\n return \"border-r border-rose-200 bg-rose-50 text-rose-700\";\n }\n if (line.kind === \"add\") {\n return \"border-r border-emerald-200 bg-emerald-50 text-emerald-700\";\n }\n return \"border-r border-stone-200 bg-stone-100 text-stone-500\";\n}\n\nfunction getCodeRowTone(line: ChatFileOperationLineViewModel): string {\n if (line.kind === \"remove\") {\n return \"bg-rose-50 text-rose-950\";\n }\n if (line.kind === \"add\") {\n return \"bg-emerald-50 text-emerald-950\";\n }\n return \"bg-white text-amber-950/80\";\n}\n\nfunction FileOperationLineNumberCell({\n layout,\n line,\n lineNumberColumnWidth,\n}: {\n layout: \"compact\" | \"workspace\";\n line: ChatFileOperationLineViewModel;\n lineNumberColumnWidth: string;\n}) {\n return (\n <span\n data-file-line-number-cell=\"true\"\n style={layout === \"compact\" ? { width: lineNumberColumnWidth, minWidth: lineNumberColumnWidth } : undefined}\n className={cn(\n FILE_LINE_NUMBER_CELL_CLASS_NAME,\n layout === \"compact\" ? \"sticky left-0 z-[1]\" : \"w-full shrink-0\",\n getLineNumberTone(line),\n )}\n >\n {readVisibleLineNumber(line)}\n </span>\n );\n}\n\nfunction FileOperationCodeCell({\n line,\n}: {\n line: ChatFileOperationLineViewModel;\n}) {\n return (\n <span\n data-file-code-row=\"true\"\n className={cn(\n \"block min-w-0 flex-1 whitespace-pre px-2.5\",\n getCodeRowTone(line),\n )}\n >\n {line.text || \" \"}\n </span>\n );\n}\n\nfunction FileOperationLineRow({\n line,\n showLineNumbers,\n lineNumberColumnWidth,\n}: {\n line: ChatFileOperationLineViewModel;\n showLineNumbers: boolean;\n lineNumberColumnWidth: string;\n}) {\n return (\n <div data-file-line-row=\"true\" className={FILE_ROW_CLASS_NAME}>\n {showLineNumbers ? (\n <FileOperationLineNumberCell\n layout=\"compact\"\n line={line}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ) : null}\n <FileOperationCodeCell line={line} />\n </div>\n );\n}\n\nfunction FileOperationWorkspaceSurface({\n block,\n}: {\n block: ChatFileOperationBlockViewModel;\n}) {\n const showLineNumbers = readHasBlockLineNumbers(block);\n const lineNumberColumnWidth = readLineNumberColumnWidth(block);\n const codeColumnWidth = readCodeColumnWidth(block);\n\n return (\n <div\n data-file-code-surface=\"true\"\n data-file-code-surface-layout=\"workspace\"\n className=\"flex h-full min-h-full min-w-full bg-white\"\n >\n {showLineNumbers ? (\n <div\n data-file-code-gutter=\"true\"\n style={{\n width: lineNumberColumnWidth,\n minWidth: lineNumberColumnWidth,\n }}\n className={cn(\n \"flex h-full min-h-full shrink-0 flex-col\",\n FILE_TEXT_CLASS_NAME,\n )}\n >\n {block.lines.map((line, index) => (\n <FileOperationLineNumberCell\n key={readLineKey(\"gutter\", line, index)}\n layout=\"workspace\"\n line={line}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ))}\n <div className=\"min-h-0 flex-1 border-r border-stone-200 bg-stone-100\" />\n </div>\n ) : null}\n\n <div\n data-file-code-canvas=\"true\"\n className=\"flex h-full min-h-full min-w-0 flex-1 flex-col bg-white\"\n >\n <div\n data-file-code-stack=\"true\"\n className=\"min-w-full\"\n style={{ minWidth: codeColumnWidth }}\n >\n {block.lines.map((line, index) => (\n <div\n key={readLineKey(\"code\", line, index)}\n data-file-code-canvas-row=\"true\"\n className={FILE_ROW_CLASS_NAME}\n >\n <FileOperationCodeCell line={line} />\n </div>\n ))}\n </div>\n <div className=\"min-h-0 flex-1 bg-white\" />\n </div>\n </div>\n );\n}\n\nexport function FileOperationCodeSurface({\n block,\n layout = \"compact\",\n}: {\n block: ChatFileOperationBlockViewModel;\n layout?: \"compact\" | \"workspace\";\n}) {\n if (layout === \"workspace\") {\n return <FileOperationWorkspaceSurface block={block} />;\n }\n\n const showLineNumbers = readHasBlockLineNumbers(block);\n const lineNumberColumnWidth = readLineNumberColumnWidth(block);\n const codeColumnWidth = readCodeColumnWidth(block);\n const surfaceMinWidth = showLineNumbers\n ? `calc(${lineNumberColumnWidth} + ${codeColumnWidth})`\n : codeColumnWidth;\n\n return (\n <div\n data-file-code-surface=\"true\"\n data-file-code-surface-layout=\"compact\"\n className=\"overflow-x-auto custom-scrollbar-amber bg-white\"\n >\n <div\n data-file-code-stack=\"true\"\n className=\"min-w-full\"\n style={{ minWidth: surfaceMinWidth }}\n >\n {block.lines.map((line, index) => (\n <FileOperationLineRow\n key={readLineKey(\"row\", line, index)}\n line={line}\n showLineNumbers={showLineNumbers}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ))}\n </div>\n </div>\n );\n}\n\nexport function FileOperationLinesGrid({\n block,\n}: {\n block: ChatFileOperationBlockViewModel;\n}) {\n return <FileOperationCodeSurface block={block} layout=\"compact\" />;\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatFileOperationBlockViewModel,\n ChatToolPartViewModel,\n} from \"../../../view-models/chat-ui.types\";\nimport { cn } from \"../../../internal/cn\";\nimport { useStickyBottomScroll } from \"../../../hooks/use-sticky-bottom-scroll\";\nimport { Fragment, type ReactNode, useRef } from \"react\";\nimport { ChatUiPrimitives } from \"../../primitives/chat-ui-primitives\";\nimport { FileOperationLinesGrid } from \"./tool-card-file-operation-lines\";\n\nfunction isPreviewBlock(block: ChatFileOperationBlockViewModel): boolean {\n return block.display === \"preview\";\n}\n\nfunction readFileOperationContentVersion(\n block: Pick<ChatFileOperationBlockViewModel, \"lines\" | \"rawText\">,\n): string {\n if (block.rawText) {\n return block.rawText;\n }\n return block.lines\n .map((line) =>\n [\n line.kind,\n line.oldLineNumber ?? \"\",\n line.newLineNumber ?? \"\",\n line.text,\n ].join(\":\"),\n )\n .join(\"\\n\");\n}\n\nfunction getCaptionTone(part: string): string {\n if (/^\\+\\d+$/.test(part)) {\n return \"text-emerald-700\";\n }\n if (/^-\\d+$/.test(part)) {\n return \"text-rose-700\";\n }\n return \"text-stone-500\";\n}\n\nfunction renderCaption(caption: string) {\n const parts = caption\n .split(\"·\")\n .map((part) => part.trim())\n .filter((part) => /^\\+\\d+$/.test(part) || /^-\\d+$/.test(part));\n if (parts.length === 0) {\n return null;\n }\n return (\n <div className=\"flex shrink-0 items-center gap-x-1 whitespace-nowrap text-[10px] font-medium uppercase tracking-[0.08em]\">\n {parts.map((part, index) => (\n <Fragment key={`${part}-${index}`}>\n {index > 0 ? <span className=\"text-stone-300\">·</span> : null}\n <span className={cn(getCaptionTone(part))}>{part}</span>\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction buildFileOpenAction(\n block: ChatFileOperationBlockViewModel,\n): ChatFileOpenActionViewModel {\n return {\n path: block.path,\n label: block.path.split(\"/\").filter(Boolean).pop() ?? block.path,\n viewMode: block.display === \"diff\" ? \"diff\" : \"preview\",\n ...(block.rawText ? { rawText: block.rawText } : {}),\n ...(block.beforeText ? { beforeText: block.beforeText } : {}),\n ...(block.afterText ? { afterText: block.afterText } : {}),\n ...(block.patchText ? { patchText: block.patchText } : {}),\n ...(typeof block.oldStartLine === \"number\"\n ? { oldStartLine: block.oldStartLine }\n : {}),\n ...(typeof block.newStartLine === \"number\"\n ? { newStartLine: block.newStartLine }\n : {}),\n fullLines: block.fullLines ?? block.lines,\n };\n}\n\nfunction StickyFileOperationScrollArea({\n children,\n contentVersion,\n resetKey,\n className,\n scrollKind,\n}: {\n children: ReactNode;\n contentVersion: unknown;\n resetKey: string;\n className?: string;\n scrollKind: \"block\" | \"raw\" | \"output\";\n}) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const { onScroll } = useStickyBottomScroll({\n scrollRef,\n resetKey,\n isLoading: false,\n hasContent: true,\n contentVersion,\n stickyThresholdPx: 20,\n });\n\n return (\n <div\n ref={scrollRef}\n onScroll={onScroll}\n data-file-scroll-kind={scrollKind}\n className={cn(\n \"overflow-y-auto bg-white custom-scrollbar-amber\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nfunction FileOperationBlock({\n block,\n showPathRow,\n isFirst,\n onFileOpen,\n}: {\n block: ChatFileOperationBlockViewModel;\n showPathRow: boolean;\n isFirst: boolean;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } =\n ChatUiPrimitives;\n const previewBlock = isPreviewBlock(block);\n const showMetaRow = showPathRow || Boolean(block.caption);\n\n const handlePathClick = () => {\n if (!onFileOpen) {\n return;\n }\n onFileOpen(buildFileOpenAction(block));\n };\n\n return (\n <section\n className={cn(\n \"overflow-hidden bg-white\",\n !isFirst && \"border-t border-stone-200/80\",\n )}\n >\n {showMetaRow ? (\n <div\n className={cn(\n \"flex items-center justify-between gap-4 border-b border-stone-200/80 px-4 text-stone-700\",\n showPathRow ? \"py-2\" : \"py-1.5\",\n )}\n >\n <div className=\"min-w-0 flex-1\">\n {showPathRow ? (\n <TooltipProvider delayDuration={250}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={handlePathClick}\n className={cn(\n \"w-full truncate whitespace-nowrap text-left font-mono text-[12px] font-medium text-stone-700\",\n onFileOpen &&\n \"transition-colors hover:text-amber-900 hover:underline\",\n )}\n title={block.path}\n >\n {block.path}\n </button>\n </TooltipTrigger>\n <TooltipContent\n side=\"top\"\n className=\"max-w-[420px] text-xs font-mono break-all\"\n >\n {block.path}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : null}\n </div>\n {block.caption ? renderCaption(block.caption) : null}\n </div>\n ) : null}\n\n {block.lines.length > 0 ? (\n <StickyFileOperationScrollArea\n resetKey={`block:${block.key}`}\n contentVersion={readFileOperationContentVersion(block)}\n className=\"max-h-72\"\n scrollKind=\"block\"\n >\n <FileOperationLinesGrid block={block} />\n </StickyFileOperationScrollArea>\n ) : block.rawText ? (\n <StickyFileOperationScrollArea\n resetKey={`raw:${block.key}`}\n contentVersion={block.rawText}\n className=\"max-h-72\"\n scrollKind=\"raw\"\n >\n <div className=\"overflow-x-auto custom-scrollbar-amber\">\n <pre className=\"min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80\">\n {block.rawText}\n </pre>\n </div>\n </StickyFileOperationScrollArea>\n ) : null}\n\n {block.truncated && !previewBlock ? (\n <div className=\"border-t border-stone-200/85 bg-stone-50 px-4 py-2 text-[10px] text-stone-500\">\n Showing a shortened diff preview.\n </div>\n ) : null}\n </section>\n );\n}\n\nexport function ToolCardFileOperationContent({\n card,\n className,\n onFileOpen,\n}: {\n card: ChatToolPartViewModel;\n className?: string;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const blocks = card.fileOperation?.blocks ?? [];\n const output = card.output?.trim() ?? \"\";\n if (blocks.length === 0 && !output) {\n return null;\n }\n\n return (\n <div className={cn(\"overflow-hidden bg-white\", className)}>\n {blocks.map((block, index) => {\n return (\n <FileOperationBlock\n key={block.key}\n block={block}\n showPathRow={true}\n isFirst={index === 0}\n onFileOpen={onFileOpen}\n />\n );\n })}\n\n {output ? (\n <StickyFileOperationScrollArea\n resetKey={`output:${card.toolName}:${card.summary ?? \"none\"}`}\n contentVersion={output}\n className={cn(\n \"max-h-56\",\n blocks.length > 0 && \"border-t border-stone-200/80\",\n )}\n scrollKind=\"output\"\n >\n <div className=\"overflow-x-auto custom-scrollbar-amber\">\n <pre className=\"min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80\">\n {output}\n </pre>\n </div>\n </StickyFileOperationScrollArea>\n ) : null}\n </div>\n );\n}\n","import { Terminal, FileText, Code2, Search, Globe } from 'lucide-react';\nimport { useState, useEffect, useRef, type ReactNode } from 'react';\nimport type {\n ChatFileOpenActionViewModel,\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../../view-models/chat-ui.types';\nimport { ToolCardRoot, ToolCardContent } from './tool-card-root';\nimport { ToolCardHeader, ToolCardHeaderSessionAction } from './tool-card-header';\nimport { ToolCardFileOperationContent } from './tool-card-file-operation';\nimport { cn } from '../../../internal/cn';\n\nconst TOOL_CARD_AUTO_EXPAND_DELAY_MS = 200;\nconst ANSI_ESCAPE_PREFIX = String.fromCharCode(27);\nconst ANSI_ESCAPE_PATTERN = new RegExp(`${ANSI_ESCAPE_PREFIX}\\\\[[0-?]*[ -/]*[@-~]`, 'g');\n\nfunction readNonEmptyString(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n return value.length > 0 ? value : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction stripAnsi(value: string): string {\n return value.replace(ANSI_ESCAPE_PATTERN, '');\n}\n\nfunction isStructuredTerminalRecord(record: Record<string, unknown>): boolean {\n return (\n 'command' in record ||\n 'workingDir' in record ||\n 'exitCode' in record ||\n 'durationMs' in record ||\n 'stdout' in record ||\n 'stderr' in record ||\n 'aggregated_output' in record ||\n 'combinedOutput' in record\n );\n}\n\nfunction extractTerminalOutputFromRecord(record: Record<string, unknown>): string | null {\n const aggregatedOutput =\n readNonEmptyString(record.aggregated_output) ??\n readNonEmptyString(record.combinedOutput) ??\n readNonEmptyString(record.output);\n if (aggregatedOutput) {\n return aggregatedOutput;\n }\n\n const stdout = readNonEmptyString(record.stdout);\n const stderr = readNonEmptyString(record.stderr);\n if (!stdout && !stderr) {\n return null;\n }\n return [stdout, stderr].filter((value): value is string => Boolean(value)).join('\\n');\n}\n\nfunction normalizeTerminalOutput(rawOutput?: string, structuredOutput?: unknown): string {\n if (isRecord(structuredOutput)) {\n const terminalOutput = extractTerminalOutputFromRecord(structuredOutput);\n if (terminalOutput) {\n return stripAnsi(terminalOutput);\n }\n if (isStructuredTerminalRecord(structuredOutput)) {\n return '';\n }\n }\n if (!rawOutput) {\n return '';\n }\n const trimmed = rawOutput.trim();\n if (!trimmed.startsWith('{')) {\n return stripAnsi(rawOutput);\n }\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!isRecord(parsed)) {\n return stripAnsi(rawOutput);\n }\n const terminalOutput = extractTerminalOutputFromRecord(parsed);\n if (terminalOutput) {\n return stripAnsi(terminalOutput);\n }\n if (isStructuredTerminalRecord(parsed)) {\n return '';\n }\n return stripAnsi(rawOutput);\n } catch {\n return stripAnsi(rawOutput);\n }\n}\n\nfunction shouldAutoExpandRunningFileOperation(toolName: string): boolean {\n return toolName === 'write_file' || toolName === 'edit_file';\n}\n\nfunction useToolCardExpandedState({\n canExpand,\n isRunning,\n autoExpandWhileRunning = true,\n expandOnError = false,\n statusTone,\n}: {\n canExpand: boolean;\n isRunning: boolean;\n autoExpandWhileRunning?: boolean;\n expandOnError?: boolean;\n statusTone: ChatToolPartViewModel['statusTone'];\n}) {\n const [expanded, setExpanded] = useState(false);\n const [hasUserToggled, setHasUserToggled] = useState(false);\n const expandTimerRef = useRef<number | null>(null);\n const prevRunningRef = useRef(isRunning);\n const isFirstRenderRef = useRef(true);\n\n useEffect(() => {\n return () => {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n }\n };\n }, []);\n\n useEffect(() => {\n if (expandOnError && statusTone === 'error' && canExpand && !hasUserToggled) {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n setExpanded(true);\n prevRunningRef.current = isRunning;\n isFirstRenderRef.current = false;\n return;\n }\n\n if (\n autoExpandWhileRunning &&\n isRunning &&\n canExpand &&\n !hasUserToggled &&\n !expanded &&\n (isFirstRenderRef.current || !prevRunningRef.current)\n ) {\n expandTimerRef.current = window.setTimeout(() => {\n setExpanded(true);\n expandTimerRef.current = null;\n }, TOOL_CARD_AUTO_EXPAND_DELAY_MS);\n }\n\n if (!isRunning) {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n if (prevRunningRef.current && !hasUserToggled) {\n setExpanded(false);\n }\n }\n\n prevRunningRef.current = isRunning;\n isFirstRenderRef.current = false;\n }, [autoExpandWhileRunning, canExpand, expandOnError, expanded, hasUserToggled, isRunning, statusTone]);\n\n const onToggle = () => {\n if (!canExpand) {\n return;\n }\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n setExpanded((current) => !current);\n setHasUserToggled(true);\n };\n\n return { expanded, onToggle };\n}\n\nfunction GenericToolSection({\n label,\n tone,\n children,\n}: {\n label: string;\n tone: 'input' | 'output' | 'error';\n children: ReactNode;\n}) {\n const tones = {\n input: {\n shell: 'border-stone-200/80 bg-stone-50/90',\n header: 'border-stone-200/80 bg-stone-100/85 text-stone-500',\n dot: 'bg-stone-400/80',\n body: 'text-stone-700',\n },\n output: {\n shell: 'border-amber-200/70 bg-white/90',\n header: 'border-amber-200/70 bg-amber-50/90 text-amber-700',\n dot: 'bg-amber-500/80',\n body: 'text-amber-950/80',\n },\n error: {\n shell: 'border-rose-200/80 bg-rose-50/85',\n header: 'border-rose-200/80 bg-rose-100/80 text-rose-700',\n dot: 'bg-rose-500/80',\n body: 'text-rose-950/85',\n },\n } as const;\n const style = tones[tone];\n\n return (\n <section\n className={cn(\n 'overflow-hidden rounded-md border shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]',\n style.shell,\n )}\n >\n <div\n className={cn(\n 'flex items-center gap-2 border-b px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.16em]',\n style.header,\n )}\n >\n <span className={cn('h-1.5 w-1.5 rounded-full', style.dot)} />\n <span>{label}</span>\n </div>\n <div className=\"w-full overflow-hidden\">\n <pre\n className={cn(\n 'w-full max-w-full min-w-0 max-h-64 overflow-x-auto overflow-y-auto px-3 py-2.5 font-mono text-[12px] leading-relaxed whitespace-pre custom-scrollbar-amber',\n style.body,\n )}\n >\n {children}\n </pre>\n </div>\n </section>\n );\n}\n\n// -------------------------------------------------------------\n// 1. Terminal View\n// -------------------------------------------------------------\nexport function TerminalExecutionView({ card }: { card: ChatToolPartViewModel }) {\n const output = normalizeTerminalOutput(card.output, card.outputData);\n const isRunning = card.statusTone === 'running';\n const hasContent = !!(card.summary?.trim() || output.trim().length > 0);\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: output.trim().length > 0 || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n expandOnError: hasContent,\n statusTone: card.statusTone,\n });\n\n const commandPart = card.summary?.replace(/^(command|path|args|query|input):\\s*/i, '');\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Terminal} \n expanded={expanded} \n canExpand={output.trim().length > 0 || isRunning} \n onToggle={onToggle} \n />\n {expanded && (\n <>\n <div className=\"px-3 pb-2 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar-amber min-h-0 text-[12px]\">\n <div className=\"flex items-start gap-2 leading-relaxed\">\n <span className=\"text-amber-500/50 font-medium shrink-0 select-none mt-[1px]\">$</span>\n <div className=\"flex-1 min-w-0\">\n {commandPart ? (\n <div className=\"text-amber-950/80 break-words whitespace-pre-wrap tracking-tight font-medium inline-block\">\n {commandPart}\n {isRunning && !output && (\n <span className=\"inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle\" />\n )}\n </div>\n ) : (\n <div className=\"h-3 w-32 bg-amber-200/30 rounded animate-pulse mt-2\" />\n )}\n </div>\n </div>\n </div>\n {output && (\n <ToolCardContent>\n <pre className=\"font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber leading-relaxed px-0\">\n {output}\n {isRunning && <span className=\"inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle\" />}\n </pre>\n </ToolCardContent>\n )}\n </>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 2. File Operation View\n// -------------------------------------------------------------\nexport function FileOperationView({\n card,\n onFileOpen,\n}: {\n card: ChatToolPartViewModel;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const output = card.output?.trim() ?? '';\n const isRunning = card.statusTone === 'running';\n const hasStructuredPreview = Boolean(card.fileOperation?.blocks.length);\n const hasContent = hasStructuredPreview || Boolean(output);\n const previewBlocks = card.fileOperation?.blocks ?? [];\n const previewLineCount = previewBlocks.reduce((count, block) => count + block.lines.length, 0);\n const previewCharCount = previewBlocks.reduce((count, block) => {\n if (block.rawText) {\n return count + block.rawText.length;\n }\n return count + block.lines.reduce((lineCount, line) => lineCount + line.text.length + 1, 0);\n }, 0);\n const shouldAutoExpandWhileRunning =\n shouldAutoExpandRunningFileOperation(card.toolName) &&\n !(\n isRunning &&\n card.toolName === 'write_file' &&\n (previewLineCount > 24 || previewCharCount > 1_200)\n );\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: hasContent || isRunning,\n isRunning,\n autoExpandWhileRunning: shouldAutoExpandWhileRunning,\n expandOnError: hasContent,\n statusTone: card.statusTone,\n });\n\n const isEdit = card.toolName === 'edit_file' || card.toolName === 'write_file' || card.toolName === 'apply_patch' || card.toolName === 'file_change';\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={isEdit ? Code2 : FileText} \n expanded={expanded} \n canExpand={hasContent || isRunning} \n hideSummary={expanded && hasStructuredPreview}\n onToggle={onToggle} \n />\n {expanded && hasContent && (\n <ToolCardContent className=\"border-t border-amber-200/20 bg-transparent px-0 pt-0 pb-0\">\n <ToolCardFileOperationContent card={card} onFileOpen={onFileOpen} />\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 3. Search View\n// -------------------------------------------------------------\nexport function SearchSnippetView({ card }: { card: ChatToolPartViewModel }) {\n const isRunning = card.statusTone === 'running';\n const output = card.output?.trim() ?? '';\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: !!output || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n statusTone: card.statusTone,\n });\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Search} \n expanded={expanded} \n canExpand={!!output || isRunning} \n onToggle={onToggle} \n />\n {expanded && output && (\n <ToolCardContent>\n <pre className=\"font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber leading-relaxed\">\n {output}\n </pre>\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 4. Generic View\n// -------------------------------------------------------------\nexport function GenericToolCard({\n card,\n onToolAction,\n renderToolAgent,\n}: {\n card: ChatToolPartViewModel;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n}) {\n const input = card.input?.trim() ?? '';\n const output = card.output?.trim() ?? '';\n const isRunning = card.statusTone === 'running';\n const hasInputSection = input.length > 0;\n const hasOutputSection = output.length > 0;\n const hasContent = hasInputSection || hasOutputSection;\n const inputLabel = card.inputLabel?.trim() || 'Input';\n const outputLabel = card.outputLabel?.trim() || 'Output';\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: hasContent || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n statusTone: card.statusTone,\n });\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Globe} \n expanded={expanded} \n canExpand={hasContent || isRunning} \n actionSlot={\n card.agentId || (card.action && onToolAction) ? (\n <>\n {card.agentId && renderToolAgent ? renderToolAgent(card.agentId) : null}\n {card.action && onToolAction ? (\n <ToolCardHeaderSessionAction\n action={card.action}\n onAction={onToolAction}\n />\n ) : null}\n </>\n ) : undefined\n }\n onToggle={onToggle} \n />\n {expanded && hasContent && (\n <ToolCardContent className=\"bg-transparent px-2.5 py-2.5\">\n {hasInputSection && (\n <GenericToolSection label={inputLabel} tone=\"input\">\n {input}\n </GenericToolSection>\n )}\n {hasInputSection && hasOutputSection && (\n <div className=\"h-2\" />\n )}\n {hasOutputSection && (\n <GenericToolSection\n label={outputLabel}\n tone={card.statusTone === 'error' ? 'error' : 'output'}\n >\n {output}\n </GenericToolSection>\n )}\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../view-models/chat-ui.types';\nimport type { ReactNode } from 'react';\nimport { TerminalExecutionView, FileOperationView, SearchSnippetView, GenericToolCard } from './chat-tool-specialized';\n\nfunction isTerminalTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'exec' || lowered === 'exec_command' || lowered === 'execute_command' || lowered === 'command_execution' || lowered === 'bash' || lowered === 'shell' || lowered.includes('run_');\n}\n\nfunction isFileEditTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'read_file' || lowered === 'write_file' || lowered === 'edit_file' || lowered === 'apply_patch' || lowered === 'file_change';\n}\n\nfunction isSearchTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'grep_search' || lowered === 'find_files' || lowered.includes('search');\n}\n\nexport function ChatToolCard({\n card,\n onToolAction,\n onFileOpen,\n renderToolAgent,\n}: {\n card: ChatToolPartViewModel;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n}) {\n if (isTerminalTool(card.toolName)) {\n return <TerminalExecutionView card={card} />;\n }\n if (isFileEditTool(card.toolName)) {\n return <FileOperationView card={card} onFileOpen={onFileOpen} />;\n }\n if (isSearchTool(card.toolName)) {\n return <SearchSnippetView card={card} />;\n }\n\n // Fallback minimalist card for read_url_content, multi_replace, etc.\n return (\n <GenericToolCard\n card={card}\n onToolAction={onToolAction}\n renderToolAgent={renderToolAgent}\n />\n );\n}\n","type ChatUnknownPartProps = {\n label: string;\n rawType: string;\n text?: string;\n};\n\nexport function ChatUnknownPart(props: ChatUnknownPartProps) {\n return (\n <div className=\"rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600\">\n <div className=\"font-semibold text-gray-700\">\n {props.label}: {props.rawType}\n </div>\n {props.text ? <pre className=\"mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500\">{props.text}</pre> : null}\n </div>\n );\n}\n","import { memo, type ReactNode } from \"react\";\nimport type {\n ChatFileOpenActionViewModel,\n ChatMessageTexts,\n ChatToolActionViewModel,\n ChatMessageViewModel,\n} from \"../../view-models/chat-ui.types\";\nimport { cn } from \"../../internal/cn\";\nimport { ChatMessageMarkdown } from \"./chat-message-markdown\";\nimport { ChatMessageInlineContent } from \"./chat-message-inline-content\";\nimport { ChatMessageFile } from \"./chat-message-file\";\nimport { ChatReasoningBlock } from \"./chat-reasoning-block\";\nimport { ChatToolCard } from \"./chat-tool-card\";\nimport { ChatUnknownPart } from \"./chat-unknown-part\";\n\ntype ChatMessageProps = {\n message: ChatMessageViewModel;\n texts: Pick<\n ChatMessageTexts,\n | \"copyCodeLabel\"\n | \"copiedCodeLabel\"\n | \"attachmentOpenLabel\"\n | \"attachmentAttachedLabel\"\n | \"attachmentCategoryLabels\"\n >;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n};\n\nexport const ChatMessage = memo(function ChatMessage(props: ChatMessageProps) {\n const { message, texts, onToolAction, onFileOpen, renderToolAgent } = props;\n const { role } = message;\n const isUser = role === \"user\";\n const isMessageInProgress =\n message.status === \"pending\" || message.status === \"streaming\";\n\n return (\n <div\n className={cn(\n \"inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm\",\n isUser\n ? \"border-primary bg-primary py-3 text-white\"\n : role === \"assistant\"\n ? \"border-gray-200 bg-white pb-3 pt-4 text-gray-900\"\n : \"border-orange-200/80 bg-orange-50/70 py-3 text-gray-900\",\n )}\n >\n <div className=\"space-y-2\">\n {message.parts.map((part, index) => {\n const { type } = part;\n\n if (type === \"markdown\") {\n return (\n <ChatMessageMarkdown\n key={`markdown-${index}`}\n text={part.text}\n role={role}\n texts={texts}\n onFileOpen={onFileOpen}\n />\n );\n }\n if (type === \"inline-content\") {\n return (\n <ChatMessageInlineContent\n key={`inline-content-${index}`}\n segments={part.segments}\n role={role}\n texts={texts}\n onFileOpen={onFileOpen}\n />\n );\n }\n if (type === \"reasoning\") {\n return (\n <ChatReasoningBlock\n key={`reasoning-${index}`}\n label={part.label}\n text={part.text}\n isUser={isUser}\n isInProgress={\n isMessageInProgress && index === message.parts.length - 1\n }\n />\n );\n }\n if (type === \"tool-card\") {\n return (\n <div key={`tool-${index}`} className=\"mt-0.5\">\n <ChatToolCard\n card={part.card}\n onToolAction={onToolAction}\n onFileOpen={onFileOpen}\n renderToolAgent={renderToolAgent}\n />\n </div>\n );\n }\n if (type === \"file\") {\n return (\n <ChatMessageFile\n key={`file-${index}`}\n file={part.file}\n isUser={isUser}\n texts={texts}\n />\n );\n }\n if (type === \"unknown\") {\n return (\n <ChatUnknownPart\n key={`unknown-${index}`}\n label={part.label}\n rawType={part.rawType}\n text={part.text}\n />\n );\n }\n return null;\n })}\n </div>\n </div>\n );\n});\n","import { cn } from '../../internal/cn';\n\ntype ChatMessageMetaProps = {\n roleLabel: string;\n timestampLabel: string;\n isUser: boolean;\n};\n\nexport function ChatMessageMeta(props: ChatMessageMetaProps) {\n return (\n <div\n className={cn(\n 'px-1 text-[11px] leading-4 text-gray-400',\n props.isUser ? 'text-right' : 'text-left'\n )}\n >\n {props.roleLabel} · {props.timestampLabel}\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport { useCopyFeedback } from '../../hooks/use-copy-feedback';\nimport { Check, Copy } from 'lucide-react';\nimport type { ChatMessageViewModel, ChatMessageTexts } from '../../view-models/chat-ui.types';\n\nexport function ChatMessageActionCopy({\n message,\n texts,\n}: {\n message: ChatMessageViewModel;\n texts: Pick<ChatMessageTexts, 'copyMessageLabel' | 'copiedMessageLabel'>;\n}) {\n const messageText = useMemo(() => {\n return message.parts\n .map((part) => {\n if (part.type === 'markdown') return part.text;\n if (part.type === 'unknown') return part.text;\n return '';\n })\n .filter((text) => !!text && text.trim().length > 0)\n .join('\\n\\n');\n }, [message.parts]);\n\n const { copied, copy } = useCopyFeedback({ text: messageText });\n\n if (!messageText) return null;\n\n return (\n <button\n type=\"button\"\n onClick={() => void copy()}\n className=\"text-gray-400 hover:text-gray-600 transition-colors p-1 rounded-md hover:bg-gray-100 flex items-center justify-center\"\n aria-label={copied ? texts.copiedMessageLabel : texts.copyMessageLabel}\n title={copied ? texts.copiedMessageLabel : texts.copyMessageLabel}\n >\n {copied ? <Check className=\"h-3.5 w-3.5\" /> : <Copy className=\"h-3.5 w-3.5\" />}\n </button>\n );\n}\n","import type { ChatMessageListProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { cn } from '@agent-chat-ui/components/chat/internal/cn';\nimport { ChatMessageAvatar } from './chat-message-avatar';\nimport { ChatMessage } from './chat-message';\nimport { ChatMessageMeta } from './chat-message-meta';\nimport { ChatMessageActionCopy } from './chat-message-action-copy';\n\nconst INVISIBLE_ONLY_TEXT_PATTERN = /\\u200B|\\u200C|\\u200D|\\u2060|\\uFEFF/g;\nconst TYPING_TEXT_SHEEN_CSS = `\n@keyframes nextclaw-chat-typing-text-sheen {\n 0% {\n background-position: 160% 0;\n }\n 100% {\n background-position: -60% 0;\n }\n}\n\n.nextclaw-chat-typing-indicator__text {\n background-image: linear-gradient(\n 100deg,\n #6b7280 0%,\n #6b7280 34%,\n #a6adba 43%,\n #f8fafc 50%,\n #a6adba 57%,\n #6b7280 66%,\n #6b7280 100%\n );\n background-size: 240% 100%;\n background-position: 160% 0;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n -webkit-text-fill-color: transparent;\n animation: nextclaw-chat-typing-text-sheen 2.5s linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .nextclaw-chat-typing-indicator__text {\n animation: none;\n background-image: none;\n color: #6b7280;\n -webkit-text-fill-color: currentColor;\n }\n}\n`;\n\nfunction hasRenderableText(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed) {\n return false;\n }\n return trimmed.replace(INVISIBLE_ONLY_TEXT_PATTERN, '').trim().length > 0;\n}\n\nfunction hasRenderableMessageContent(message: ChatMessageListProps['messages'][number]): boolean {\n return message.parts.some((part) => {\n if (part.type === 'markdown' || part.type === 'reasoning') {\n return hasRenderableText(part.text);\n }\n return true;\n });\n}\n\nfunction ChatMessageTypingFooter() {\n return (\n <div className=\"flex items-center gap-2 px-1 py-0.5 text-[11px] text-gray-400\">\n <div className=\"flex space-x-1 items-center h-full\">\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse\"></div>\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:200ms]\"></div>\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:400ms]\"></div>\n </div>\n </div>\n );\n}\n\nfunction ChatTypingIndicator({ label }: { label: string }) {\n return (\n <div className=\"rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-gray-500 shadow-sm\">\n <style>{TYPING_TEXT_SHEEN_CSS}</style>\n <span className=\"nextclaw-chat-typing-indicator__text\">{label}</span>\n </div>\n );\n}\n\nexport function ChatMessageList(props: ChatMessageListProps) {\n const visibleMessages = props.messages.filter(hasRenderableMessageContent);\n const hasRenderableAssistantDraft = visibleMessages.some(\n (message) =>\n message.role === 'assistant' &&\n (message.status === 'streaming' || message.status === 'pending')\n );\n\n return (\n <div className={cn('space-y-5', props.className)}>\n {visibleMessages.map((message) => {\n const isUser = message.role === 'user';\n const isGenerating = !isUser && (message.status === 'streaming' || message.status === 'pending');\n\n return (\n <div key={message.id} className={cn('flex gap-3', isUser ? 'justify-end' : 'justify-start')}>\n {!isUser ? <ChatMessageAvatar role={message.role} /> : null}\n <div className={cn('w-fit max-w-[92%] space-y-2', isUser && 'flex flex-col items-end')}>\n <ChatMessage\n message={message}\n texts={props.texts}\n onToolAction={props.onToolAction}\n onFileOpen={props.onFileOpen}\n renderToolAgent={props.renderToolAgent}\n />\n <div className={cn('flex items-center gap-2', isUser && 'justify-end')}>\n {isGenerating ? (\n <ChatMessageTypingFooter />\n ) : (\n <>\n <ChatMessageMeta roleLabel={message.roleLabel} timestampLabel={message.timestampLabel} isUser={isUser} />\n {!isUser ? <ChatMessageActionCopy message={message} texts={props.texts} /> : null}\n </>\n )}\n </div>\n </div>\n {isUser ? <ChatMessageAvatar role={message.role} /> : null}\n </div>\n );\n })}\n\n {props.isSending && !hasRenderableAssistantDraft ? (\n <div className=\"flex justify-start gap-3\">\n <ChatMessageAvatar role=\"assistant\" />\n <ChatTypingIndicator label={props.texts.typingLabel} />\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["DefaultPopover","DefaultPopoverAnchor","DefaultPopoverContent","DefaultPopoverTrigger","DefaultInput","DefaultSelect","DefaultSelectContent","DefaultSelectGroup","DefaultSelectItem","DefaultSelectLabel","DefaultSelectSeparator","DefaultSelectTrigger","DefaultSelectValue","DefaultTooltip","DefaultTooltipContent","DefaultTooltipProvider","DefaultTooltipTrigger"],"sources":["../src/components/chat/hooks/use-active-item-scroll.ts","../src/components/chat/hooks/use-element-width.ts","../src/components/chat/internal/cn.ts","../src/components/chat/default-skin/input.tsx","../src/components/chat/default-skin/popover.tsx","../src/components/chat/default-skin/select.tsx","../src/components/chat/default-skin/tooltip.tsx","../src/components/chat/ui/primitives/chat-ui-primitives.tsx","../src/components/chat/ui/chat-input-bar/chat-slash-menu.tsx","../src/components/chat/default-skin/button.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-actions.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-skill-picker.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar-toolbar.tsx","../src/components/chat/ui/chat-input-bar/chat-composer.utils.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-token-node.tsx","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-editor-state.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-operations.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-lexical-controller.ts","../src/components/chat/ui/chat-input-bar/lexical/chat-composer-plugins.tsx","../src/components/chat/ui/chat-input-bar/lexical/chat-input-bar-tokenized-composer.tsx","../src/components/chat/ui/chat-input-bar/chat-input-bar.tsx","../src/components/chat/ui/chat-message-list/chat-message-avatar.tsx","../src/components/chat/utils/copy-text.ts","../src/components/chat/hooks/use-copy-feedback.ts","../src/components/chat/ui/chat-message-list/code-block/chat-code-syntax-highlighter.ts","../src/components/chat/ui/chat-message-list/chat-code-block.tsx","../src/components/chat/ui/chat-message-list/chat-message-markdown.tsx","../src/components/chat/ui/chat-message-list/chat-message-inline-content.tsx","../src/components/chat/ui/chat-message-list/chat-message-file/meta.ts","../src/components/chat/ui/chat-message-list/chat-message-file/index.tsx","../src/components/chat/hooks/use-reasoning-block-open-state.ts","../src/components/chat/hooks/use-sticky-bottom-scroll.ts","../src/components/chat/ui/chat-message-list/chat-reasoning-block.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-root.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-status.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-header.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation-lines.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-file-operation.tsx","../src/components/chat/ui/chat-message-list/tool-card/tool-card-views.tsx","../src/components/chat/ui/chat-message-list/chat-tool-card.tsx","../src/components/chat/ui/chat-message-list/chat-unknown-part.tsx","../src/components/chat/ui/chat-message-list/chat-message.tsx","../src/components/chat/ui/chat-message-list/chat-message-meta.tsx","../src/components/chat/ui/chat-message-list/chat-message-action-copy.tsx","../src/components/chat/ui/chat-message-list/chat-message-list.tsx"],"sourcesContent":["import { useEffect, type RefObject } from 'react';\n\ntype UseActiveItemScrollParams = {\n containerRef: RefObject<HTMLElement>;\n activeIndex: number;\n itemCount: number;\n isEnabled: boolean;\n getItemSelector?: (index: number) => string;\n};\n\nconst defaultGetItemSelector = (index: number) => `[data-item-index=\"${index}\"]`;\n\nexport function useActiveItemScroll(params: UseActiveItemScrollParams) {\n const { activeIndex, containerRef, getItemSelector: customGetItemSelector, isEnabled, itemCount } =\n params;\n const getItemSelector = customGetItemSelector ?? defaultGetItemSelector;\n\n useEffect(() => {\n if (!isEnabled || itemCount === 0) {\n return;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n const activeItem = container.querySelector<HTMLElement>(getItemSelector(activeIndex));\n if (typeof activeItem?.scrollIntoView === 'function') {\n activeItem.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n }, [activeIndex, containerRef, getItemSelector, isEnabled, itemCount]);\n}\n","import { useEffect, useRef, useState, type RefObject } from 'react';\n\ntype UseElementWidthResult<T extends HTMLElement> = {\n elementRef: RefObject<T>;\n width: number | null;\n};\n\nexport function useElementWidth<T extends HTMLElement>(): UseElementWidthResult<T> {\n const elementRef = useRef<T | null>(null);\n const [width, setWidth] = useState<number | null>(null);\n\n useEffect(() => {\n const element = elementRef.current;\n if (!element || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n const updateWidth = () => {\n setWidth(element.getBoundingClientRect().width);\n };\n\n updateWidth();\n\n const observer = new ResizeObserver(() => updateWidth());\n observer.observe(element);\n\n return () => observer.disconnect();\n }, []);\n\n return {\n elementRef,\n width\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from 'react';\nimport { cn } from '../internal/cn';\n\nexport type ChatInputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst ChatInput = React.forwardRef<HTMLInputElement, ChatInputProps>(({ className, type, ...props }, ref) => (\n <input\n type={type}\n className={cn(\n 'flex h-9 w-full rounded-xl border border-gray-200/80 bg-white px-3.5 py-2 text-sm text-gray-900 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-gray-300 placeholder:font-normal focus:outline-none focus:ring-1 focus:ring-primary/40 focus:border-primary/40 transition-colors disabled:cursor-not-allowed disabled:opacity-50',\n className\n )}\n ref={ref}\n {...props}\n />\n));\n\nChatInput.displayName = 'ChatInput';\n\nexport { ChatInput };\n","import * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '../internal/cn';\n\nconst ChatPopover = PopoverPrimitive.Root;\nconst ChatPopoverTrigger = PopoverPrimitive.Trigger;\nconst ChatPopoverAnchor = PopoverPrimitive.Anchor;\n\nconst ChatPopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, sideOffset = 8, align = 'start', ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n align={align}\n className={cn(\n 'z-[var(--z-popover,50)] w-72 overflow-hidden rounded-2xl border border-gray-200/50 bg-white p-4 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\n\nChatPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { ChatPopover, ChatPopoverTrigger, ChatPopoverContent, ChatPopoverAnchor };\n","import * as React from 'react';\nimport * as SelectPrimitive from '@radix-ui/react-select';\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react';\nimport { cn } from '../internal/cn';\n\nconst ChatSelect = SelectPrimitive.Root;\nconst ChatSelectGroup = SelectPrimitive.Group;\nconst ChatSelectValue = SelectPrimitive.Value;\n\nconst ChatSelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-gray-200/80 bg-white px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary/40 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\n\nChatSelectTrigger.displayName = SelectPrimitive.Trigger.displayName;\n\nconst ChatSelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton ref={ref} className={cn('flex cursor-default items-center justify-center py-1', className)} {...props}>\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n));\n\nChatSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;\n\nconst ChatSelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton ref={ref} className={cn('flex cursor-default items-center justify-center py-1', className)} {...props}>\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n));\n\nChatSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;\n\nconst ChatSelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md bg-white text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <ChatSelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn('p-1', position === 'popper' && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]')}\n >\n {children}\n </SelectPrimitive.Viewport>\n <ChatSelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n));\n\nChatSelectContent.displayName = SelectPrimitive.Content.displayName;\n\nconst ChatSelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label ref={ref} className={cn('px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-gray-500', className)} {...props} />\n));\n\nChatSelectLabel.displayName = SelectPrimitive.Label.displayName;\n\nconst ChatSelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-gray-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-gray-100',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n));\n\nChatSelectItem.displayName = SelectPrimitive.Item.displayName;\n\nconst ChatSelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator ref={ref} className={cn('-mx-1 my-1 h-px bg-gray-100', className)} {...props} />\n));\n\nChatSelectSeparator.displayName = SelectPrimitive.Separator.displayName;\n\nexport {\n ChatSelect,\n ChatSelectContent,\n ChatSelectGroup,\n ChatSelectItem,\n ChatSelectLabel,\n ChatSelectSeparator,\n ChatSelectTrigger,\n ChatSelectValue\n};\n","import * as React from 'react';\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport { cn } from '../internal/cn';\n\nconst ChatTooltipProvider = TooltipPrimitive.Provider;\nconst ChatTooltip = TooltipPrimitive.Root;\nconst ChatTooltipTrigger = TooltipPrimitive.Trigger;\n\nconst ChatTooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-[var(--z-tooltip)] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n));\n\nChatTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { ChatTooltip, ChatTooltipTrigger, ChatTooltipContent, ChatTooltipProvider };\n","import { ChatInput as DefaultInput } from '../../default-skin/input';\nimport {\n ChatPopover as DefaultPopover,\n ChatPopoverAnchor as DefaultPopoverAnchor,\n ChatPopoverContent as DefaultPopoverContent,\n ChatPopoverTrigger as DefaultPopoverTrigger\n} from '../../default-skin/popover';\nimport {\n ChatSelect as DefaultSelect,\n ChatSelectContent as DefaultSelectContent,\n ChatSelectGroup as DefaultSelectGroup,\n ChatSelectItem as DefaultSelectItem,\n ChatSelectLabel as DefaultSelectLabel,\n ChatSelectSeparator as DefaultSelectSeparator,\n ChatSelectTrigger as DefaultSelectTrigger,\n ChatSelectValue as DefaultSelectValue\n} from '../../default-skin/select';\nimport {\n ChatTooltip as DefaultTooltip,\n ChatTooltipContent as DefaultTooltipContent,\n ChatTooltipProvider as DefaultTooltipProvider,\n ChatTooltipTrigger as DefaultTooltipTrigger\n} from '../../default-skin/tooltip';\n\n// Centralized primitive adapter layer for chat UI.\nexport const ChatUiPrimitives = {\n Popover: DefaultPopover,\n PopoverAnchor: DefaultPopoverAnchor,\n PopoverContent: DefaultPopoverContent,\n PopoverTrigger: DefaultPopoverTrigger,\n Input: DefaultInput,\n Select: DefaultSelect,\n SelectContent: DefaultSelectContent,\n SelectGroup: DefaultSelectGroup,\n SelectItem: DefaultSelectItem,\n SelectLabel: DefaultSelectLabel,\n SelectSeparator: DefaultSelectSeparator,\n SelectTrigger: DefaultSelectTrigger,\n SelectValue: DefaultSelectValue,\n Tooltip: DefaultTooltip,\n TooltipContent: DefaultTooltipContent,\n TooltipProvider: DefaultTooltipProvider,\n TooltipTrigger: DefaultTooltipTrigger\n};\n","import { useMemo, useRef } from 'react';\nimport { useActiveItemScroll } from '../../hooks/use-active-item-scroll';\nimport { useElementWidth } from '../../hooks/use-element-width';\nimport { ChatUiPrimitives } from '../primitives/chat-ui-primitives';\nimport type { ChatSlashMenuProps } from '../../view-models/chat-ui.types';\n\nconst SLASH_PANEL_MAX_WIDTH = 680;\nconst SLASH_PANEL_DESKTOP_SHRINK_RATIO = 0.82;\nconst SLASH_PANEL_DESKTOP_MIN_WIDTH = 560;\n\nexport function ChatSlashMenu(props: ChatSlashMenuProps) {\n const { Popover, PopoverAnchor, PopoverContent } = ChatUiPrimitives;\n const { elementRef: anchorRef, width: panelWidth } = useElementWidth<HTMLDivElement>();\n const listRef = useRef<HTMLDivElement | null>(null);\n const {\n isOpen,\n isLoading,\n items,\n activeIndex,\n activeItem,\n texts,\n onSelectItem,\n onOpenChange,\n onDetailsPointerDown,\n onSetActiveIndex\n } = props;\n\n const resolvedWidth = useMemo(() => {\n if (!panelWidth) {\n return undefined;\n }\n return Math.min(\n panelWidth > SLASH_PANEL_DESKTOP_MIN_WIDTH ? panelWidth * SLASH_PANEL_DESKTOP_SHRINK_RATIO : panelWidth,\n SLASH_PANEL_MAX_WIDTH\n );\n }, [panelWidth]);\n\n useActiveItemScroll({\n containerRef: listRef,\n activeIndex,\n itemCount: items.length,\n isEnabled: isOpen && !isLoading,\n getItemSelector: (index) => `[data-slash-index=\"${index}\"]`\n });\n\n return (\n <Popover open={isOpen} onOpenChange={onOpenChange}>\n <PopoverAnchor asChild>\n <div ref={anchorRef} className=\"pointer-events-none absolute bottom-full left-3 right-3 h-0\" />\n </PopoverAnchor>\n <PopoverContent\n side=\"top\"\n align=\"start\"\n sideOffset={10}\n className=\"z-[70] max-w-[calc(100vw-1.5rem)] overflow-hidden rounded-2xl border border-gray-200 bg-white/95 p-0 shadow-2xl backdrop-blur-md\"\n onOpenAutoFocus={(event) => event.preventDefault()}\n style={resolvedWidth ? { width: `${resolvedWidth}px` } : undefined}\n >\n <div className=\"grid min-h-[240px] grid-cols-[minmax(220px,300px)_minmax(0,1fr)]\">\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label={texts.slashSectionLabel}\n className=\"custom-scrollbar max-h-[320px] overflow-y-auto border-r border-gray-200 p-2.5\"\n >\n {isLoading ? (\n <div className=\"p-2 text-xs text-gray-500\">{texts.slashLoadingLabel}</div>\n ) : (\n <>\n <div className=\"mb-2 px-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500\">\n {texts.slashSectionLabel}\n </div>\n {items.length === 0 ? (\n <div className=\"px-2 text-xs text-gray-400\">{texts.slashEmptyLabel}</div>\n ) : (\n <div className=\"space-y-1\">\n {items.map((item, index) => {\n const isActive = index === activeIndex;\n return (\n <button\n key={item.key}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-slash-index={index}\n onMouseEnter={() => onSetActiveIndex(index)}\n onClick={() => onSelectItem(item)}\n className={`flex w-full items-start gap-2 rounded-lg px-2 py-1.5 text-left transition ${\n isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-700 hover:bg-gray-50'\n }`}\n >\n <span className=\"truncate text-xs font-semibold\">{item.title}</span>\n <span className=\"truncate text-xs text-gray-500\">{item.subtitle}</span>\n </button>\n );\n })}\n </div>\n )}\n </>\n )}\n </div>\n <div className=\"min-w-0 p-2.5\" onPointerDown={onDetailsPointerDown}>\n {activeItem ? (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <span className=\"inline-flex rounded-full bg-primary/10 px-2 py-0.5 text-[11px] font-semibold text-primary\">\n {activeItem.subtitle}\n </span>\n <span className=\"text-sm font-semibold text-gray-900\">{activeItem.title}</span>\n </div>\n <p className=\"text-xs leading-5 text-gray-600\">{activeItem.description}</p>\n <div className=\"space-y-1\">\n {activeItem.detailLines.map((line) => (\n <div\n key={line}\n className=\"min-w-0 break-all rounded-md bg-gray-50 px-2 py-1 text-[11px] leading-5 text-gray-600\"\n >\n {line}\n </div>\n ))}\n </div>\n <div className=\"pt-1 text-[11px] text-gray-500\">{texts.slashSkillHintLabel}</div>\n </div>\n ) : (\n <div className=\"text-xs text-gray-500\">{texts.slashHintLabel}</div>\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../internal/cn';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-full text-sm font-medium ring-offset-background transition-all duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-gray-200 bg-white hover:bg-gray-50 hover:text-gray-800 text-gray-600',\n secondary: 'bg-gray-100 text-gray-700 hover:bg-gray-200/80',\n ghost: 'hover:bg-gray-100/80 hover:text-gray-800',\n link: 'text-primary underline-offset-4 hover:underline',\n primary: 'bg-primary text-primary-foreground hover:bg-primary-600 active:bg-primary-700 shadow-sm',\n subtle: 'bg-gray-100 text-gray-600 hover:bg-gray-200/80',\n 'primary-outline': 'border border-primary/30 text-primary hover:bg-primary hover:text-primary-foreground'\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 px-3 text-xs',\n lg: 'h-11 px-5 text-[14px]',\n xl: 'h-12 px-6 text-[15px]',\n icon: 'h-9 w-9'\n }\n },\n defaultVariants: {\n variant: 'default',\n size: 'default'\n }\n }\n);\n\nexport interface ChatButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst ChatButton = React.forwardRef<HTMLButtonElement, ChatButtonProps>(\n ({ className, variant, size, ...props }, ref) => (\n <button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />\n )\n);\n\nChatButton.displayName = 'ChatButton';\n\nexport { ChatButton, buttonVariants };\n","import { ChatButton } from '../../default-skin/button';\nimport { ChatUiPrimitives } from '../primitives/chat-ui-primitives';\nimport type { ChatContextWindowIndicator, ChatInputBarActionsProps } from '../../view-models/chat-ui.types';\nimport { ArrowUp } from 'lucide-react';\n\nconst SEND_ERROR_PREVIEW_MAX_CHARS = 120;\n\nfunction buildSendErrorPreview(value: string): string {\n const compact = value.replace(/\\s+/g, ' ').trim();\n if (compact.length <= SEND_ERROR_PREVIEW_MAX_CHARS) {\n return compact;\n }\n return `${compact.slice(0, SEND_ERROR_PREVIEW_MAX_CHARS - 1)}…`;\n}\n\nfunction StopIcon() {\n return (\n <span\n aria-hidden=\"true\"\n data-testid=\"chat-stop-icon\"\n className=\"block h-3 w-3 rounded-[2px] bg-gray-700 shadow-[inset_0_0_0_1px_rgba(17,24,39,0.06)]\"\n />\n );\n}\n\nfunction ContextWindowIndicator({ contextWindow }: { contextWindow: ChatContextWindowIndicator }) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;\n const clampedRatio = Math.max(0, Math.min(1, contextWindow.ratio));\n const angle = Math.round(clampedRatio * 360);\n const ringColor = '#9ca3af';\n\n return (\n <TooltipProvider delayDuration={0}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700\"\n aria-label={contextWindow.label}\n title={contextWindow.label}\n >\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-[7px] rounded-full\"\n style={{ background: `conic-gradient(${ringColor} ${angle}deg, #e5e7eb 0deg)` }}\n />\n <span aria-hidden=\"true\" className=\"absolute inset-[10px] rounded-full bg-white\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[18rem]\">\n <div className=\"space-y-1.5 text-xs\">\n <div className=\"flex items-center justify-between gap-5 font-semibold text-gray-800\">\n <span>{contextWindow.label}</span>\n <span>{contextWindow.percentLabel}</span>\n </div>\n {contextWindow.details.map((detail) => (\n <div key={detail.label} className=\"flex items-center justify-between gap-5 text-gray-600\">\n <span>{detail.label}</span>\n <span className=\"font-medium text-gray-800\">{detail.value}</span>\n </div>\n ))}\n </div>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n\nexport function ChatInputBarActions({\n sendError,\n sendErrorDetailsLabel,\n isSending,\n canStopGeneration,\n sendDisabled,\n stopDisabled,\n stopHint,\n sendButtonLabel,\n stopButtonLabel,\n contextWindow,\n onSend,\n onStop\n}: ChatInputBarActionsProps) {\n const {\n Popover,\n PopoverContent,\n PopoverTrigger,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger\n } = ChatUiPrimitives;\n const normalizedSendError = sendError?.trim() ?? '';\n const sendErrorPreview = normalizedSendError\n ? buildSendErrorPreview(normalizedSendError)\n : '';\n const resolvedSendErrorDetailsLabel = sendErrorDetailsLabel?.trim() || 'Details';\n\n return (\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n {normalizedSendError ? (\n <div className=\"flex max-w-[420px] items-start justify-end gap-2 text-right\">\n <div className=\"min-w-0 flex-1 text-[11px] text-red-600\">\n <span\n className=\"block truncate\"\n title={normalizedSendError}\n >\n {sendErrorPreview}\n </span>\n </div>\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"shrink-0 rounded-full border border-red-200/80 bg-red-50 px-2 py-0.5 text-[10px] font-semibold text-red-700 transition-colors hover:bg-red-100\"\n >\n {resolvedSendErrorDetailsLabel}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"w-[min(32rem,calc(100vw-1.5rem))] border-red-100/80 p-0\"\n >\n <div className=\"border-b border-red-100 bg-red-50/80 px-4 py-2 text-xs font-semibold text-red-700\">\n {resolvedSendErrorDetailsLabel}\n </div>\n <pre className=\"max-h-80 overflow-auto whitespace-pre-wrap break-words px-4 py-3 text-xs leading-relaxed text-red-700\">\n {normalizedSendError}\n </pre>\n </PopoverContent>\n </Popover>\n </div>\n ) : null}\n <div className=\"flex items-center gap-2\">\n {contextWindow ? <ContextWindowIndicator contextWindow={contextWindow} /> : null}\n {isSending ? (\n canStopGeneration ? (\n <ChatButton\n size=\"icon\"\n variant=\"outline\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={stopButtonLabel}\n onClick={() => void onStop()}\n disabled={stopDisabled}\n >\n <StopIcon />\n </ChatButton>\n ) : (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <span>\n <ChatButton\n size=\"icon\"\n variant=\"outline\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={stopButtonLabel}\n disabled\n >\n <StopIcon />\n </ChatButton>\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n <p className=\"text-xs\">{stopHint}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n ) : (\n <ChatButton\n size=\"icon\"\n className=\"h-8 w-8 rounded-full\"\n aria-label={sendButtonLabel}\n onClick={() => void onSend()}\n disabled={sendDisabled}\n >\n <ArrowUp className=\"h-5 w-5\" />\n </ChatButton>\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useId, useMemo, useRef, useState, type KeyboardEventHandler } from 'react';\nimport { BrainCircuit, Check, ExternalLink, Puzzle, Search } from 'lucide-react';\nimport { useActiveItemScroll } from '@agent-chat-ui/components/chat/hooks/use-active-item-scroll';\nimport { ChatUiPrimitives } from '@agent-chat-ui/components/chat/ui/primitives/chat-ui-primitives';\nimport type { ChatSkillPickerOption, ChatSkillPickerOptionGroup, ChatSkillPickerProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\n\nfunction filterOptions(options: ChatSkillPickerOption[], query: string): ChatSkillPickerOption[] {\n const keyword = query.trim().toLowerCase();\n if (!keyword) {\n return options;\n }\n return options.filter((option) => {\n const haystack = [option.label, option.key, option.description]\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n .join(' ')\n .toLowerCase();\n return haystack.includes(keyword);\n });\n}\n\nexport function ChatInputBarSkillPicker(props: { picker: ChatSkillPickerProps }) {\n const { Input, Popover, PopoverContent, PopoverTrigger } = ChatUiPrimitives;\n const { picker } = props;\n const listRef = useRef<HTMLDivElement | null>(null);\n const listId = useId();\n const [query, setQuery] = useState('');\n const [activeIndex, setActiveIndex] = useState(0);\n const selectedSet = useMemo(() => new Set(picker.selectedKeys), [picker.selectedKeys]);\n const selectedCount = picker.selectedKeys.length;\n const isSearchActive = query.trim().length > 0;\n const groupedOptions = useMemo<ChatSkillPickerOptionGroup[] | null>(() => {\n if (isSearchActive) {\n return null;\n }\n const groups = picker.groups?.filter((group) => group.options.length > 0) ?? [];\n return groups.length > 0 ? groups : null;\n }, [isSearchActive, picker.groups]);\n const visibleOptions = useMemo(() => {\n if (groupedOptions) {\n return groupedOptions.flatMap((group) => group.options);\n }\n return filterOptions(picker.options, query);\n }, [groupedOptions, picker.options, query]);\n\n useEffect(() => {\n setActiveIndex(0);\n }, [query]);\n\n useEffect(() => {\n setActiveIndex((current) => {\n if (visibleOptions.length === 0) {\n return 0;\n }\n return Math.min(current, visibleOptions.length - 1);\n });\n }, [visibleOptions.length]);\n\n useActiveItemScroll({\n containerRef: listRef,\n activeIndex,\n itemCount: visibleOptions.length,\n isEnabled: visibleOptions.length > 0,\n getItemSelector: (index) => `[data-skill-index=\"${index}\"]`\n });\n\n const onToggleOption = (optionKey: string) => {\n if (selectedSet.has(optionKey)) {\n picker.onSelectedKeysChange(picker.selectedKeys.filter((item) => item !== optionKey));\n return;\n }\n picker.onSelectedKeysChange([...picker.selectedKeys, optionKey]);\n };\n\n const onSearchKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {\n if (visibleOptions.length === 0) {\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setActiveIndex((current) => Math.min(current + 1, visibleOptions.length - 1));\n return;\n }\n\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n setActiveIndex((current) => Math.max(current - 1, 0));\n return;\n }\n\n if (event.key === 'Enter') {\n event.preventDefault();\n const activeOption = visibleOptions[activeIndex];\n if (activeOption) {\n onToggleOption(activeOption.key);\n }\n }\n };\n\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-label={picker.title}\n className=\"relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg px-0 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 sm:w-auto sm:gap-1.5 sm:px-3\"\n >\n <BrainCircuit className=\"h-4 w-4\" />\n <span className=\"nextclaw-chat-skill-picker-label hidden sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{picker.title}</span>\n {selectedCount > 0 ? (\n <span className=\"absolute -right-1 -top-1 flex h-[18px] min-w-[18px] items-center justify-center rounded-full bg-primary px-1 text-[10px] font-semibold leading-none text-white shadow-sm sm:static sm:ml-0.5 sm:bg-primary/10 sm:text-primary sm:shadow-none\">\n {selectedCount}\n </span>\n ) : null}\n </button>\n </PopoverTrigger>\n <PopoverContent side=\"top\" align=\"start\" className=\"w-[360px] p-0\">\n <div className=\"space-y-2 border-b border-gray-100 px-4 py-3\">\n <div className=\"text-sm font-semibold text-gray-900\">{picker.title}</div>\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-3 top-2.5 h-3.5 w-3.5 text-gray-400\" />\n <Input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onSearchKeyDown}\n placeholder={picker.searchPlaceholder}\n role=\"combobox\"\n aria-controls={listId}\n aria-expanded=\"true\"\n aria-autocomplete=\"list\"\n aria-activedescendant={visibleOptions[activeIndex] ? `${listId}-option-${activeIndex}` : undefined}\n className=\"h-8 rounded-lg pl-8 text-xs\"\n />\n </div>\n </div>\n\n <div\n ref={listRef}\n id={listId}\n role=\"listbox\"\n aria-multiselectable=\"true\"\n className=\"custom-scrollbar max-h-[320px] overflow-y-auto\"\n >\n {picker.isLoading ? (\n <div className=\"p-4 text-xs text-gray-500\">{picker.loadingLabel}</div>\n ) : visibleOptions.length === 0 ? (\n <div className=\"p-4 text-center text-xs text-gray-500\">{picker.emptyLabel}</div>\n ) : (\n <div className=\"py-1\">\n {(() => {\n const groups = groupedOptions ?? [{ key: 'all-skills', options: visibleOptions }];\n let visibleIndex = 0;\n return groups.map((group) => (\n <div key={group.key}>\n {group.label ? (\n <div className=\"px-4 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-gray-500\">\n {group.label}\n </div>\n ) : null}\n {group.options.map((option) => {\n const index = visibleIndex;\n visibleIndex += 1;\n const isSelected = selectedSet.has(option.key);\n const isActive = index === activeIndex;\n return (\n <div\n key={option.key}\n id={`${listId}-option-${index}`}\n role=\"option\"\n aria-selected={isSelected}\n data-skill-index={index}\n onMouseEnter={() => setActiveIndex(index)}\n className={`flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors ${\n isActive ? 'bg-gray-50' : 'hover:bg-gray-50'\n }`}\n >\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 text-gray-500\">\n <Puzzle className=\"h-4 w-4\" />\n </div>\n <div className=\"min-w-0 flex-1 select-text\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"truncate text-sm text-gray-900\">{option.label}</span>\n {option.badgeLabel ? (\n <span className=\"shrink-0 rounded-full bg-primary/10 px-1.5 py-0.5 text-[10px] font-medium text-primary\">\n {option.badgeLabel}\n </span>\n ) : null}\n </div>\n <div className=\"mt-0.5 truncate text-xs text-gray-500\">{option.description || option.key}</div>\n </div>\n <div className=\"ml-3 shrink-0\">\n <button\n type=\"button\"\n aria-label={`${isSelected ? 'Remove' : 'Add'} ${option.label}`}\n onClick={() => onToggleOption(option.key)}\n className={\n isSelected\n ? 'inline-flex h-5 w-5 items-center justify-center rounded-full bg-primary text-white'\n : 'inline-flex h-5 w-5 items-center justify-center rounded-full border border-gray-300 bg-white'\n }\n >\n {isSelected ? <Check className=\"h-3 w-3\" /> : null}\n </button>\n </div>\n </div>\n );\n })}\n </div>\n ));\n })()}\n </div>\n )}\n </div>\n\n {picker.manageHref && picker.manageLabel ? (\n <div className=\"border-t border-gray-100 px-4 py-2.5\">\n <a\n href={picker.manageHref}\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-colors hover:text-primary/80\"\n >\n {picker.manageLabel}\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n}\n","import { ChatUiPrimitives } from '@agent-chat-ui/components/chat/ui/primitives/chat-ui-primitives';\nimport type {\n ChatInputBarToolbarProps,\n ChatToolbarAccessoryIcon,\n ChatToolbarIcon,\n ChatToolbarSelect\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { Brain, Paperclip, Sparkles } from 'lucide-react';\nimport { ChatInputBarActions } from './chat-input-bar-actions';\nimport { ChatInputBarSkillPicker } from './chat-input-bar-skill-picker';\n\nfunction ToolbarIcon({ icon }: { icon?: ChatToolbarIcon }) {\n return icon === 'sparkles'\n ? <Sparkles className=\"h-3.5 w-3.5 shrink-0 text-primary\" />\n : icon === 'brain'\n ? <Brain className=\"h-3.5 w-3.5 shrink-0 text-gray-500\" />\n : null;\n}\n\nfunction AccessoryIcon({ icon }: { icon?: ChatToolbarAccessoryIcon }) {\n return icon === 'paperclip' ? <Paperclip className=\"h-4 w-4\" /> : <ToolbarIcon icon={icon} />;\n}\n\nconst TRIGGER_WIDTH_BY_KEY: Record<string, string> = {\n model: 'min-w-0 max-w-full flex-1 basis-[12rem] sm:max-w-[320px]',\n 'session-type': 'shrink-0',\n thinking: 'shrink-0'\n};\n\nconst CONTENT_WIDTH_BY_KEY: Record<string, string> = {\n model: 'w-[min(18rem,calc(100vw-1rem))] sm:w-[320px]',\n 'session-type': 'w-[220px]',\n thinking: 'w-[180px]'\n};\n\nfunction resolveMobileSelectedLabel(item: ChatToolbarSelect): string | undefined {\n return item.key === 'model' && item.selectedLabel\n ? item.selectedLabel.split('/').slice(1).join('/').trim() || item.selectedLabel\n : item.selectedLabel;\n}\n\nfunction ToolbarSelect({ item }: { item: ChatToolbarSelect }) {\n const { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } =\n ChatUiPrimitives;\n const groups =\n item.groups?.filter((group) => group.options.length > 0) ??\n (item.options.length > 0 ? [{ key: `${item.key}-default`, options: item.options }] : []);\n const hasOptions = groups.some((group) => group.options.length > 0);\n const mobileSelectedLabel = resolveMobileSelectedLabel(item);\n\n return (\n <Select value={item.value} onValueChange={item.onValueChange} disabled={item.disabled}>\n <SelectTrigger\n aria-label={item.selectedLabel ? `${item.placeholder}: ${item.selectedLabel}` : item.placeholder}\n title={item.selectedLabel}\n className={`nextclaw-chat-toolbar-select-trigger h-8 w-auto rounded-lg border-0 bg-transparent px-2 text-xs font-medium text-gray-600 shadow-none hover:bg-gray-100 focus:ring-0 sm:px-3 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!basis-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!justify-center [@container_nextclaw-chat-input-bar_(max-width:440px)]:!max-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!min-w-8 [@container_nextclaw-chat-input-bar_(max-width:440px)]:!px-0 ${TRIGGER_WIDTH_BY_KEY[item.key] ?? ''}`}\n >\n {item.selectedLabel ? (\n <div className=\"flex min-w-0 items-center gap-2 text-left\">\n <ToolbarIcon icon={item.icon} />\n <span className=\"nextclaw-chat-toolbar-mobile-label truncate text-xs font-semibold text-gray-700 sm:hidden [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{mobileSelectedLabel}</span>\n <span className=\"nextclaw-chat-toolbar-label hidden truncate text-xs font-semibold text-gray-700 sm:inline [@container_nextclaw-chat-input-bar_(max-width:440px)]:hidden\">{item.selectedLabel}</span>\n </div>\n ) : item.loading ? (\n <div className=\"h-3 w-24 animate-pulse rounded bg-gray-200\" />\n ) : (\n <SelectValue placeholder={item.placeholder} />\n )}\n </SelectTrigger>\n <SelectContent className={CONTENT_WIDTH_BY_KEY[item.key] ?? ''}>\n {!hasOptions ? (\n item.loading ? (\n <div className=\"space-y-2 px-3 py-2\">\n <div className=\"h-3 w-36 animate-pulse rounded bg-gray-200\" />\n <div className=\"h-3 w-28 animate-pulse rounded bg-gray-200\" />\n <div className=\"h-3 w-32 animate-pulse rounded bg-gray-200\" />\n </div>\n ) : item.emptyLabel ? (\n <div className=\"px-3 py-2 text-xs text-gray-500\">{item.emptyLabel}</div>\n ) : null\n ) : null}\n {groups.map((group, groupIndex) => (\n <div key={group.key}>\n {groupIndex > 0 ? <SelectSeparator /> : null}\n <SelectGroup>\n {group.label ? <SelectLabel>{group.label}</SelectLabel> : null}\n {group.options.map((option) => (\n <SelectItem key={option.value} value={option.value} className=\"py-2\">\n {option.description ? (\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n <span className=\"truncate text-xs font-semibold text-gray-800\">{option.label}</span>\n <span className=\"truncate text-[11px] text-gray-500\">{option.description}</span>\n </div>\n ) : (\n <span className=\"truncate text-xs font-semibold text-gray-800\">{option.label}</span>\n )}\n </SelectItem>\n ))}\n </SelectGroup>\n </div>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nexport function ChatInputBarToolbar({ actions, accessories, selects, skillPicker }: ChatInputBarToolbarProps) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } = ChatUiPrimitives;\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-2 px-3 pb-3\">\n <div className=\"flex min-w-[12rem] flex-1 flex-wrap items-center gap-1 overflow-hidden\">\n {skillPicker ? <ChatInputBarSkillPicker picker={skillPicker} /> : null}\n {selects.map((item) => (\n <ToolbarSelect key={item.key} item={item} />\n ))}\n {accessories?.map((item) => {\n const button = (\n <button\n type=\"button\"\n className={`inline-flex items-center rounded-lg py-1.5 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 disabled:cursor-not-allowed disabled:text-gray-400 ${\n item.iconOnly ? 'h-8 w-8 justify-center px-0' : 'gap-1.5 px-3'\n }`}\n onClick={item.onClick}\n disabled={item.disabled}\n aria-label={item.label}\n >\n <AccessoryIcon icon={item.icon} />\n {item.iconOnly ? null : <span>{item.label}</span>}\n </button>\n );\n if (!item.tooltip) {\n return <div key={item.key}>{button}</div>;\n }\n const trigger = item.disabled ? <span className=\"inline-flex\">{button}</span> : button;\n return (\n <TooltipProvider key={item.key}>\n <Tooltip>\n <TooltipTrigger asChild>{trigger}</TooltipTrigger>\n <TooltipContent side=\"top\">\n <p className=\"text-xs\">{item.tooltip}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n })}\n </div>\n <ChatInputBarActions {...actions} />\n </div>\n );\n}\n","import type { ChatComposerNode, ChatComposerSelection, ChatComposerTextNode, ChatComposerTokenKind, ChatComposerTokenNode } from '../../view-models/chat-ui.types';\n\nexport const CHAT_COMPOSER_TOKEN_PLACEHOLDER = '\\uFFFC';\n\nfunction createComposerNodeId(): string {\n return `composer-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport function createChatComposerTextNode(text = ''): ChatComposerTextNode {\n return {\n id: createComposerNodeId(),\n type: 'text',\n text\n };\n}\n\nexport function createChatComposerTokenNode(params: {\n tokenKind: ChatComposerTokenKind;\n tokenKey: string;\n label: string;\n}): ChatComposerTokenNode {\n return {\n id: createComposerNodeId(),\n type: 'token',\n tokenKind: params.tokenKind,\n tokenKey: params.tokenKey,\n label: params.label\n };\n}\n\nexport function getChatComposerNodeLength(node: ChatComposerNode): number {\n return node.type === 'text' ? node.text.length : 1;\n}\n\nexport function createEmptyChatComposerNodes(): ChatComposerNode[] {\n return [createChatComposerTextNode('')];\n}\n\nexport function createChatComposerNodesFromText(text: string): ChatComposerNode[] {\n return [createChatComposerTextNode(text)];\n}\n\nexport function normalizeChatComposerNodes(nodes: ChatComposerNode[]): ChatComposerNode[] {\n const normalized: ChatComposerNode[] = [];\n for (const node of nodes) {\n if (node.type === 'text') {\n if (node.text.length === 0) {\n continue;\n }\n const previous = normalized[normalized.length - 1];\n if (previous?.type === 'text') {\n normalized[normalized.length - 1] = {\n ...previous,\n text: previous.text + node.text\n };\n continue;\n }\n }\n normalized.push(node);\n }\n if (normalized.length === 0) {\n return createEmptyChatComposerNodes();\n }\n return normalized;\n}\n\nexport function serializeChatComposerDocument(nodes: ChatComposerNode[]): string {\n return nodes.map((node) => (node.type === 'text' ? node.text : CHAT_COMPOSER_TOKEN_PLACEHOLDER)).join('');\n}\n\nexport function serializeChatComposerPlainText(nodes: ChatComposerNode[]): string {\n return nodes.filter((node): node is ChatComposerTextNode => node.type === 'text').map((node) => node.text).join('');\n}\n\nexport function extractChatComposerTokenKeys(\n nodes: ChatComposerNode[],\n tokenKind: ChatComposerTokenKind\n): string[] {\n const keys: string[] = [];\n const keySet = new Set<string>();\n for (const node of nodes) {\n if (node.type !== 'token' || node.tokenKind !== tokenKind || keySet.has(node.tokenKey)) {\n continue;\n }\n keySet.add(node.tokenKey);\n keys.push(node.tokenKey);\n }\n return keys;\n}\n\nfunction buildTrimmedTextEdges(\n node: ChatComposerTextNode,\n nodeStart: number,\n rangeStart: number,\n rangeEnd: number\n): ChatComposerTextNode[] {\n const prefixLength = Math.max(0, rangeStart - nodeStart);\n const suffixLength = Math.max(0, nodeStart + node.text.length - rangeEnd);\n const edges: ChatComposerTextNode[] = [];\n\n if (prefixLength > 0) {\n edges.push({\n ...node,\n text: node.text.slice(0, prefixLength)\n });\n }\n if (suffixLength > 0) {\n edges.push({\n ...node,\n text: node.text.slice(node.text.length - suffixLength)\n });\n }\n\n return edges;\n}\n\nfunction isNodeOutsideComposerRange(\n nodeStart: number,\n nodeEnd: number,\n boundedStart: number,\n boundedEnd: number\n): boolean {\n return nodeEnd <= boundedStart || nodeStart >= boundedEnd;\n}\n\nfunction appendReplacementBeforeNode(\n nextNodes: ChatComposerNode[],\n replacement: ChatComposerNode[],\n inserted: boolean,\n nodeStart: number,\n boundedEnd: number\n): boolean {\n if (!inserted && nodeStart >= boundedEnd) {\n nextNodes.push(...replacement);\n return true;\n }\n return inserted;\n}\n\nfunction appendTextNodeWithReplacement(\n nextNodes: ChatComposerNode[],\n node: ChatComposerTextNode,\n nodeStart: number,\n boundedStart: number,\n boundedEnd: number,\n replacement: ChatComposerNode[],\n inserted: boolean\n): boolean {\n const edges = buildTrimmedTextEdges(node, nodeStart, boundedStart, boundedEnd);\n if (edges[0]) {\n nextNodes.push(edges[0]);\n }\n let didInsert = inserted;\n if (!didInsert) {\n nextNodes.push(...replacement);\n didInsert = true;\n }\n if (edges[1]) {\n nextNodes.push(edges[1]);\n }\n return didInsert;\n}\n\nfunction appendTokenNodeWithReplacement(\n nextNodes: ChatComposerNode[],\n node: ChatComposerNode,\n replacement: ChatComposerNode[],\n inserted: boolean,\n boundedStart: number,\n nodeStart: number\n): boolean {\n if (!inserted && boundedStart <= nodeStart) {\n nextNodes.push(...replacement);\n return true;\n }\n nextNodes.push(node);\n return inserted;\n}\n\nexport function replaceChatComposerRange(\n nodes: ChatComposerNode[],\n start: number,\n end: number,\n replacement: ChatComposerNode[]\n): ChatComposerNode[] {\n const boundedStart = Math.max(0, start);\n const boundedEnd = Math.max(boundedStart, end);\n const nextNodes: ChatComposerNode[] = [];\n let cursor = 0;\n let inserted = false;\n\n for (const node of nodes) {\n const nodeLength = getChatComposerNodeLength(node);\n const nodeStart = cursor;\n const nodeEnd = cursor + nodeLength;\n const isOutsideRange = isNodeOutsideComposerRange(nodeStart, nodeEnd, boundedStart, boundedEnd);\n\n if (isOutsideRange) {\n inserted = appendReplacementBeforeNode(nextNodes, replacement, inserted, nodeStart, boundedEnd);\n nextNodes.push(node);\n cursor = nodeEnd;\n continue;\n }\n\n if (node.type === 'text') {\n inserted = appendTextNodeWithReplacement(\n nextNodes,\n node,\n nodeStart,\n boundedStart,\n boundedEnd,\n replacement,\n inserted\n );\n } else {\n inserted = appendTokenNodeWithReplacement(nextNodes, node, replacement, inserted, boundedStart, nodeStart);\n }\n\n cursor = nodeEnd;\n }\n\n if (!inserted) {\n nextNodes.push(...replacement);\n }\n\n return normalizeChatComposerNodes(nextNodes);\n}\n\nexport function removeChatComposerTokenNodes(\n nodes: ChatComposerNode[],\n predicate: (node: ChatComposerTokenNode) => boolean\n): ChatComposerNode[] {\n return normalizeChatComposerNodes(\n nodes.filter((node) => node.type !== 'token' || !predicate(node))\n );\n}\n\nexport function resolveChatComposerSlashTrigger(\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null\n): { query: string; start: number; end: number } | null {\n if (!selection || selection.start !== selection.end) {\n return null;\n }\n\n const documentText = serializeChatComposerDocument(nodes);\n const caret = selection.end;\n const prefix = documentText.slice(0, caret);\n const match = /(?:^|\\s)\\/([^\\s\\uFFFC]*)$/.exec(prefix);\n if (!match) {\n return null;\n }\n\n const slashStart = caret - match[0].length + (match[0].startsWith('/') ? 0 : 1);\n return {\n query: (match[1] ?? '').trim().toLowerCase(),\n start: slashStart,\n end: caret\n };\n}\n\nexport function isChatComposerSelectionInsideRange(\n selection: ChatComposerSelection | null,\n start: number,\n end: number\n): boolean {\n if (!selection) {\n return false;\n }\n return selection.start < end && selection.end > start;\n}\n","import {\n $applyNodeReplacement,\n DecoratorNode,\n type EditorConfig,\n type LexicalEditor,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n} from 'lexical';\nimport type { ReactElement } from 'react';\nimport { CHAT_COMPOSER_TOKEN_PLACEHOLDER } from '../chat-composer.utils';\nimport type { ChatComposerTokenKind } from '../../../view-models/chat-ui.types';\n\ntype SerializedChatComposerTokenNode = SerializedLexicalNode & {\n composerId: string;\n label: string;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n type: 'chat-composer-token';\n version: 1;\n};\n\nfunction buildTokenClassName(tokenKind: ChatComposerTokenKind): string {\n if (tokenKind === 'file') {\n return [\n 'mx-[2px]',\n 'inline-flex',\n 'h-7',\n 'max-w-[min(100%,17rem)]',\n 'items-center',\n 'gap-1.5',\n 'rounded-lg',\n 'border',\n 'border-slate-200/80',\n 'bg-slate-50',\n 'px-2',\n 'align-baseline',\n 'text-slate-700',\n 'transition-[border-color,background-color,box-shadow,color]',\n 'duration-150',\n ].join(' ');\n }\n\n return [\n 'mx-[2px]',\n 'inline-flex',\n 'h-7',\n 'max-w-full',\n 'items-center',\n 'gap-1.5',\n 'rounded-lg',\n 'border',\n 'border-primary/12',\n 'bg-primary/8',\n 'px-2',\n 'align-baseline',\n 'text-[11px]',\n 'font-medium',\n 'text-primary',\n 'transition',\n ].join(' ');\n}\n\nfunction ChatComposerTokenChip(props: {\n label: string;\n tokenKind: ChatComposerTokenKind;\n}): ReactElement {\n return (\n <>\n <span\n className={\n props.tokenKind === 'file'\n ? 'inline-flex h-4.5 w-4.5 shrink-0 items-center justify-center rounded-md bg-white text-slate-500 ring-1 ring-black/5'\n : 'inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center text-primary/70'\n }\n >\n {props.tokenKind === 'file' ? (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M3.25 4.25A1.5 1.5 0 0 1 4.75 2.75h6.5a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-6.5a1.5 1.5 0 0 1-1.5-1.5v-7.5Z\" />\n <path d=\"m4.75 10 2.25-2.5 1.75 1.75 1.25-1.25 2 2\" />\n <path d=\"M9.75 6.25h.01\" />\n </svg>\n ) : (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M8.5 2.75 2.75 6l5.75 3.25L14.25 6 8.5 2.75Z\" />\n <path d=\"M2.75 10 8.5 13.25 14.25 10\" />\n <path d=\"M2.75 6v4l5.75 3.25V9.25L2.75 6Z\" />\n <path d=\"M14.25 6v4L8.5 13.25V9.25L14.25 6Z\" />\n </svg>\n )}\n </span>\n <span\n className={\n props.tokenKind === 'file'\n ? 'min-w-0 flex-1 truncate text-[12px] font-medium text-slate-700'\n : 'truncate'\n }\n >\n {props.label}\n </span>\n </>\n );\n}\n\nexport class ChatComposerTokenNode extends DecoratorNode<ReactElement> {\n __composerId: string;\n __tokenKind: ChatComposerTokenKind;\n __tokenKey: string;\n __label: string;\n\n static getType(): string {\n return 'chat-composer-token';\n }\n\n static clone(node: ChatComposerTokenNode): ChatComposerTokenNode {\n return new ChatComposerTokenNode(\n node.__composerId,\n node.__tokenKind,\n node.__tokenKey,\n node.__label,\n node.__key,\n );\n }\n\n static importJSON(serializedNode: SerializedChatComposerTokenNode): ChatComposerTokenNode {\n return $createChatComposerTokenNode({\n composerId: serializedNode.composerId,\n label: serializedNode.label,\n tokenKey: serializedNode.tokenKey,\n tokenKind: serializedNode.tokenKind,\n });\n }\n\n constructor(\n composerId: string,\n tokenKind: ChatComposerTokenKind,\n tokenKey: string,\n label: string,\n key?: NodeKey,\n ) {\n super(key);\n this.__composerId = composerId;\n this.__tokenKind = tokenKind;\n this.__tokenKey = tokenKey;\n this.__label = label;\n }\n\n private readonly applyTokenDom = (element: HTMLElement): void => {\n element.contentEditable = 'false';\n element.dataset.composerNodeId = this.__composerId;\n element.dataset.composerNodeType = 'token';\n element.dataset.composerTokenKind = this.__tokenKind;\n element.dataset.composerTokenKey = this.__tokenKey;\n element.dataset.composerLabel = this.__label;\n element.title = this.__label;\n element.className = buildTokenClassName(this.__tokenKind);\n };\n\n createDOM = (_config: EditorConfig, _editor: LexicalEditor): HTMLElement => {\n const element = document.createElement('span');\n this.applyTokenDom(element);\n return element;\n };\n\n updateDOM = (_prevNode: ChatComposerTokenNode, dom: HTMLElement): false => {\n this.applyTokenDom(dom);\n return false;\n };\n\n decorate = (): ReactElement => {\n return <ChatComposerTokenChip label={this.__label} tokenKind={this.__tokenKind} />;\n };\n\n exportJSON = (): SerializedChatComposerTokenNode => {\n return {\n composerId: this.__composerId,\n label: this.__label,\n tokenKey: this.__tokenKey,\n tokenKind: this.__tokenKind,\n type: 'chat-composer-token',\n version: 1,\n };\n };\n\n getComposerId = (): string => {\n return this.getLatest().__composerId;\n };\n\n getTokenKind = (): ChatComposerTokenKind => {\n return this.getLatest().__tokenKind;\n };\n\n getTokenKey = (): string => {\n return this.getLatest().__tokenKey;\n };\n\n getLabel = (): string => {\n return this.getLatest().__label;\n };\n\n getTextContent = (): string => {\n return CHAT_COMPOSER_TOKEN_PLACEHOLDER;\n };\n\n isInline = (): true => {\n return true;\n };\n\n isIsolated = (): true => {\n return true;\n };\n\n isKeyboardSelectable = (): boolean => {\n return false;\n };\n}\n\nexport function $createChatComposerTokenNode(params: {\n composerId: string;\n label: string;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n}): ChatComposerTokenNode {\n const { composerId, label, tokenKey, tokenKind } = params;\n return $applyNodeReplacement(\n new ChatComposerTokenNode(composerId, tokenKind, tokenKey, label),\n );\n}\n\nexport function $isChatComposerTokenNode(\n node: LexicalNode | null | undefined,\n): node is ChatComposerTokenNode {\n return node instanceof ChatComposerTokenNode;\n}\n","import {\n $createLineBreakNode,\n $createParagraphNode,\n $createRangeSelection,\n $createTextNode,\n $getRoot,\n $getSelection,\n $isElementNode,\n $isRangeSelection,\n $isTextNode,\n $setSelection,\n type EditorState,\n type ElementPoint,\n type LexicalEditor,\n type LexicalNode,\n type NodeKey,\n type PointType,\n} from 'lexical';\nimport type { ChatComposerNode, ChatComposerSelection } from '../../../view-models/chat-ui.types';\nimport { normalizeChatComposerNodes } from '../chat-composer.utils';\nimport {\n $createChatComposerTokenNode,\n $isChatComposerTokenNode,\n type ChatComposerTokenNode,\n} from './chat-composer-token-node';\n\ntype LeafDescriptor =\n | {\n index: number;\n key: NodeKey;\n length: number;\n node: LexicalNode;\n start: number;\n type: 'linebreak' | 'token';\n }\n | {\n index: number;\n key: NodeKey;\n length: number;\n node: LexicalNode;\n start: number;\n text: string;\n type: 'text';\n };\n\ntype SelectionPointDescriptor = {\n key: NodeKey;\n offset: number;\n type: 'element' | 'text';\n};\n\nexport type ChatComposerEditorSnapshot = {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n};\n\nfunction getComposerLeafDescriptors(): {\n descriptors: LeafDescriptor[];\n paragraphKey: NodeKey;\n paragraphSize: number;\n totalLength: number;\n} {\n const root = $getRoot();\n const paragraph = root.getFirstChild();\n if (!$isElementNode(paragraph)) {\n return {\n descriptors: [],\n paragraphKey: root.getKey(),\n paragraphSize: 0,\n totalLength: 0,\n };\n }\n\n const children = paragraph.getChildren();\n const descriptors: LeafDescriptor[] = [];\n let cursor = 0;\n\n for (const [index, child] of children.entries()) {\n if ($isTextNode(child)) {\n const text = child.getTextContent();\n descriptors.push({\n index,\n key: child.getKey(),\n length: text.length,\n node: child,\n start: cursor,\n text,\n type: 'text',\n });\n cursor += text.length;\n continue;\n }\n\n if ($isChatComposerTokenNode(child)) {\n descriptors.push({\n index,\n key: child.getKey(),\n length: 1,\n node: child,\n start: cursor,\n type: 'token',\n });\n cursor += 1;\n continue;\n }\n\n descriptors.push({\n index,\n key: child.getKey(),\n length: child.getTextContent().length,\n node: child,\n start: cursor,\n type: 'linebreak',\n });\n cursor += child.getTextContent().length;\n }\n\n return {\n descriptors,\n paragraphKey: paragraph.getKey(),\n paragraphSize: children.length,\n totalLength: cursor,\n };\n}\n\nfunction buildSelectionPointFromOffset(offset: number): SelectionPointDescriptor {\n const { descriptors, paragraphKey, paragraphSize, totalLength } = getComposerLeafDescriptors();\n const boundedOffset = Math.max(0, Math.min(offset, totalLength));\n\n if (descriptors.length === 0) {\n return {\n key: paragraphKey,\n offset: 0,\n type: 'element',\n };\n }\n\n for (const descriptor of descriptors) {\n const end = descriptor.start + descriptor.length;\n\n if (descriptor.type === 'text' && boundedOffset >= descriptor.start && boundedOffset <= end) {\n return {\n key: descriptor.key,\n offset: boundedOffset - descriptor.start,\n type: 'text',\n };\n }\n\n if (descriptor.type !== 'text') {\n if (boundedOffset === descriptor.start) {\n return {\n key: paragraphKey,\n offset: descriptor.index,\n type: 'element',\n };\n }\n\n if (boundedOffset === end) {\n const nextDescriptor = descriptors[descriptor.index + 1];\n if (nextDescriptor?.type === 'text' && nextDescriptor.length === 0) {\n return {\n key: nextDescriptor.key,\n offset: 0,\n type: 'text',\n };\n }\n return {\n key: paragraphKey,\n offset: descriptor.index + 1,\n type: 'element',\n };\n }\n }\n }\n\n return {\n key: paragraphKey,\n offset: paragraphSize,\n type: 'element',\n };\n}\n\nfunction getOffsetFromElementPoint(point: ElementPoint): number {\n const { descriptors, paragraphKey, totalLength } = getComposerLeafDescriptors();\n\n if (point.key === paragraphKey) {\n const previous = descriptors[point.offset - 1];\n return previous ? previous.start + previous.length : 0;\n }\n\n const descriptor = descriptors.find((item) => item.key === point.key);\n if (!descriptor) {\n return totalLength;\n }\n\n return descriptor.start + Math.min(point.offset, descriptor.length);\n}\n\nfunction getOffsetFromPoint(point: PointType): number {\n if (point.type === 'element') {\n return getOffsetFromElementPoint(point);\n }\n\n const { descriptors, totalLength } = getComposerLeafDescriptors();\n const descriptor = descriptors.find((item) => item.key === point.key);\n if (!descriptor) {\n return totalLength;\n }\n\n return descriptor.start + Math.min(point.offset, descriptor.length);\n}\n\nfunction readNodesFromEditor(): ChatComposerNode[] {\n const { descriptors } = getComposerLeafDescriptors();\n const nextNodes: ChatComposerNode[] = [];\n let textBuffer = '';\n let textId = '';\n\n const flushTextBuffer = (): void => {\n if (textBuffer.length === 0) {\n return;\n }\n nextNodes.push({\n id: textId,\n type: 'text',\n text: textBuffer,\n });\n textBuffer = '';\n textId = '';\n };\n\n for (const descriptor of descriptors) {\n if (descriptor.type === 'text') {\n if (textBuffer.length === 0) {\n textId = descriptor.key;\n }\n textBuffer += descriptor.text;\n continue;\n }\n\n if (descriptor.type === 'linebreak') {\n if (textBuffer.length === 0) {\n textId = descriptor.key;\n }\n textBuffer += '\\n';\n continue;\n }\n\n flushTextBuffer();\n const tokenNode = descriptor.node as ChatComposerTokenNode;\n nextNodes.push({\n id: tokenNode.getComposerId(),\n label: tokenNode.getLabel(),\n tokenKey: tokenNode.getTokenKey(),\n tokenKind: tokenNode.getTokenKind(),\n type: 'token',\n });\n }\n\n flushTextBuffer();\n return normalizeChatComposerNodes(nextNodes);\n}\n\nexport function readChatComposerSnapshotFromEditorState(\n editorState: EditorState,\n): ChatComposerEditorSnapshot {\n return editorState.read(() => {\n const selection = $getSelection();\n const nodes = readNodesFromEditor();\n\n if (!$isRangeSelection(selection)) {\n return {\n nodes,\n selection: null,\n };\n }\n\n return {\n nodes,\n selection: {\n start: Math.min(getOffsetFromPoint(selection.anchor), getOffsetFromPoint(selection.focus)),\n end: Math.max(getOffsetFromPoint(selection.anchor), getOffsetFromPoint(selection.focus)),\n },\n };\n });\n}\n\nexport function writeChatComposerStateToLexicalRoot(\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null,\n): void {\n const root = $getRoot();\n root.clear();\n\n const paragraph = $createParagraphNode();\n root.append(paragraph);\n\n for (const node of normalizeChatComposerNodes(nodes)) {\n if (node.type === 'token') {\n paragraph.append(\n $createChatComposerTokenNode({\n composerId: node.id,\n label: node.label,\n tokenKey: node.tokenKey,\n tokenKind: node.tokenKind,\n }),\n );\n continue;\n }\n\n const parts = node.text.split('\\n');\n for (const [index, part] of parts.entries()) {\n if (part.length > 0) {\n paragraph.append($createTextNode(part));\n }\n if (index < parts.length - 1) {\n paragraph.append($createLineBreakNode());\n }\n }\n }\n\n if ($isChatComposerTokenNode(paragraph.getLastChild())) {\n paragraph.append($createTextNode(''));\n }\n\n if (!selection) {\n return;\n }\n\n const nextSelection = $createRangeSelection();\n const anchor = buildSelectionPointFromOffset(selection.start);\n const focus = buildSelectionPointFromOffset(selection.end);\n nextSelection.anchor.set(anchor.key, anchor.offset, anchor.type);\n nextSelection.focus.set(focus.key, focus.offset, focus.type);\n $setSelection(nextSelection);\n}\n\nexport function syncLexicalEditorFromChatComposerState(\n editor: LexicalEditor,\n nodes: ChatComposerNode[],\n selection: ChatComposerSelection | null,\n): void {\n editor.update(() => {\n writeChatComposerStateToLexicalRoot(nodes, selection);\n });\n}\n\nexport function syncLexicalSelectionFromChatComposerSelection(\n editor: LexicalEditor,\n selection: ChatComposerSelection,\n): void {\n editor.update(() => {\n const nextSelection = $createRangeSelection();\n const anchor = buildSelectionPointFromOffset(selection.start);\n const focus = buildSelectionPointFromOffset(selection.end);\n nextSelection.anchor.set(anchor.key, anchor.offset, anchor.type);\n nextSelection.focus.set(focus.key, focus.offset, focus.type);\n $setSelection(nextSelection);\n });\n}\n","import type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatComposerTokenKind,\n ChatSkillPickerOption,\n} from '../../../view-models/chat-ui.types';\nimport {\n createChatComposerTextNode,\n createChatComposerTokenNode,\n extractChatComposerTokenKeys,\n getChatComposerNodeLength,\n normalizeChatComposerNodes,\n removeChatComposerTokenNodes,\n replaceChatComposerRange,\n resolveChatComposerSlashTrigger,\n} from '../chat-composer.utils';\nimport type { ChatComposerEditorSnapshot } from './chat-composer-lexical-editor-state';\n\nfunction getDocumentLength(nodes: ChatComposerNode[]): number {\n return nodes.reduce((sum, node) => sum + getChatComposerNodeLength(node), 0);\n}\n\nfunction insertToken(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n tokenKind: ChatComposerTokenKind;\n trigger?: { end: number; query: string; start: number } | null;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey, tokenKind, trigger } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = selection ? [Math.min(selection.start, selection.end), Math.max(selection.start, selection.end)] : [documentLength, documentLength];\n const replaceStart = trigger?.start ?? selectionStart;\n const replaceEnd = trigger?.end ?? selectionEnd;\n\n return {\n nodes: replaceChatComposerRange(\n nodes,\n replaceStart,\n replaceEnd,\n [\n createChatComposerTokenNode({\n label,\n tokenKey,\n tokenKind,\n }),\n ],\n ),\n selection: {\n start: replaceStart + 1,\n end: replaceStart + 1,\n },\n };\n}\n\nexport function getChatComposerNodesSignature(nodes: ChatComposerNode[]): string {\n return nodes\n .map((node) =>\n node.type === 'text'\n ? `text:${node.id}:${node.text}`\n : `token:${node.id}:${node.tokenKind}:${node.tokenKey}:${node.label}`,\n )\n .join('\\u001f');\n}\n\nexport function replaceChatComposerSelectionWithText(params: {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n text: string;\n}): ChatComposerEditorSnapshot {\n const { nodes, selection, text } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = selection ? [Math.min(selection.start, selection.end), Math.max(selection.start, selection.end)] : [documentLength, documentLength];\n const nextOffset = selectionStart + text.length;\n\n return {\n nodes: replaceChatComposerRange(\n nodes,\n selectionStart,\n selectionEnd,\n [createChatComposerTextNode(text)],\n ),\n selection: {\n start: nextOffset,\n end: nextOffset,\n },\n };\n}\n\nexport function insertFileTokenIntoChatComposer(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey } = params;\n return insertToken({\n label,\n nodes,\n selection,\n tokenKey,\n tokenKind: 'file',\n });\n}\n\nexport function insertSkillTokenIntoChatComposer(params: {\n label: string;\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n tokenKey: string;\n}): ChatComposerEditorSnapshot {\n const { label, nodes, selection, tokenKey } = params;\n\n if (extractChatComposerTokenKeys(nodes, 'skill').includes(tokenKey)) {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection,\n };\n }\n\n return insertToken({\n label,\n nodes,\n selection,\n tokenKey,\n tokenKind: 'skill',\n trigger: resolveChatComposerSlashTrigger(nodes, selection),\n });\n}\n\nexport function syncSelectedSkillsIntoChatComposer(params: {\n nextKeys: string[];\n nodes: ChatComposerNode[];\n options: ChatSkillPickerOption[];\n selection: ChatComposerSelection | null;\n}): ChatComposerEditorSnapshot {\n const { nextKeys, nodes, options, selection } = params;\n const selectedSkillKeys = extractChatComposerTokenKeys(nodes, 'skill');\n const optionMap = new Map(options.map((option) => [option.key, option]));\n const addedKey = nextKeys.find((key) => !selectedSkillKeys.includes(key));\n\n if (addedKey) {\n const option = optionMap.get(addedKey);\n return insertSkillTokenIntoChatComposer({\n label: option?.label ?? addedKey,\n nodes,\n selection,\n tokenKey: addedKey,\n });\n }\n\n const removedKey = selectedSkillKeys.find((key) => !nextKeys.includes(key));\n if (!removedKey) {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection,\n };\n }\n\n return {\n nodes: removeChatComposerTokenNodes(\n nodes,\n (node) => node.tokenKind === 'skill' && node.tokenKey === removedKey,\n ),\n selection,\n };\n}\n\nexport function deleteChatComposerContent(params: {\n direction: 'backward' | 'forward';\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n}): ChatComposerEditorSnapshot {\n const { direction, nodes, selection: currentSelection } = params;\n const documentLength = getDocumentLength(nodes);\n const [selectionStart, selectionEnd] = currentSelection ? [Math.min(currentSelection.start, currentSelection.end), Math.max(currentSelection.start, currentSelection.end)] : [documentLength, documentLength];\n let rangeStart = selectionStart;\n let rangeEnd = selectionEnd;\n\n if (rangeStart === rangeEnd) {\n if (direction === 'backward' && rangeStart > 0) {\n rangeStart -= 1;\n } else if (direction === 'forward' && rangeEnd < documentLength) {\n rangeEnd += 1;\n } else {\n return {\n nodes: normalizeChatComposerNodes(nodes),\n selection: { start: rangeStart, end: rangeEnd },\n };\n }\n }\n\n return {\n nodes: replaceChatComposerRange(nodes, rangeStart, rangeEnd, []),\n selection: {\n start: rangeStart,\n end: rangeStart,\n },\n };\n}\n","import type { FormEvent } from 'react';\nimport type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatInputBarActionsProps,\n ChatSkillPickerOption,\n ChatSlashItem,\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { resolveChatComposerSlashTrigger } from '@agent-chat-ui/components/chat/ui/chat-input-bar/chat-composer.utils';\nimport {\n deleteChatComposerContent,\n insertFileTokenIntoChatComposer,\n insertSkillTokenIntoChatComposer,\n replaceChatComposerSelectionWithText,\n syncSelectedSkillsIntoChatComposer,\n type ChatComposerEditorSnapshot,\n} from './chat-composer-lexical-adapter';\nimport type { ChatInputBarTokenizedComposerHandle } from './chat-input-bar-tokenized-composer';\n\ntype ComposerActions = Pick<\n ChatInputBarActionsProps,\n 'onSend' | 'onStop' | 'isSending' | 'canStopGeneration'\n>;\n\ntype ChatComposerKeyboardAction =\n | { type: 'close-slash' }\n | { type: 'consume' }\n | { type: 'delete-content'; direction: 'backward' | 'forward' }\n | { type: 'insert-active-slash-item' }\n | { type: 'insert-line-break' }\n | { type: 'move-slash-index'; index: number }\n | { type: 'noop' }\n | { type: 'send-message' }\n | { type: 'stop-generation' };\n\nexport function resolveLexicalComposerKeyboardAction(params: {\n activeSlashIndex: number;\n canStopGeneration: boolean;\n isComposing: boolean;\n isSending: boolean;\n isSlashMenuOpen: boolean;\n key: string;\n shiftKey: boolean;\n slashItemCount: number;\n}): ChatComposerKeyboardAction {\n const {\n activeSlashIndex,\n canStopGeneration,\n isComposing,\n isSending,\n isSlashMenuOpen,\n key,\n shiftKey,\n slashItemCount,\n } = params;\n\n if (key === 'Enter' && !shiftKey && isSending) {\n return { type: 'consume' };\n }\n\n if (isSlashMenuOpen && slashItemCount > 0) {\n if (key === 'ArrowDown') {\n return {\n type: 'move-slash-index',\n index: (activeSlashIndex + 1) % slashItemCount,\n };\n }\n if (key === 'ArrowUp') {\n return {\n type: 'move-slash-index',\n index: (activeSlashIndex - 1 + slashItemCount) % slashItemCount,\n };\n }\n if ((key === 'Enter' && !shiftKey) || key === 'Tab') {\n return { type: 'insert-active-slash-item' };\n }\n }\n\n if (key === 'Escape') {\n if (isSlashMenuOpen) {\n return { type: 'close-slash' };\n }\n if (isSending && canStopGeneration) {\n return { type: 'stop-generation' };\n }\n return { type: 'noop' };\n }\n\n if (key === 'Enter' && shiftKey) {\n return { type: 'insert-line-break' };\n }\n\n if (key === 'Enter') {\n return { type: 'send-message' };\n }\n\n if (!isComposing && (key === 'Backspace' || key === 'Delete')) {\n return {\n type: 'delete-content',\n direction: key === 'Backspace' ? 'backward' : 'forward',\n };\n }\n\n return { type: 'noop' };\n}\n\ntype LexicalComposerHandleOwnerParams = {\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n optionsReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n};\n\nclass LexicalComposerHandleOwner implements ChatInputBarTokenizedComposerHandle {\n constructor(private readonly params: LexicalComposerHandleOwnerParams) {}\n\n insertSlashItem = (item: ChatSlashItem): void => {\n if (!item.value) {\n return;\n }\n\n this.params.onSlashItemSelect?.(item);\n this.params.publishSnapshot(\n insertSkillTokenIntoChatComposer({\n label: item.title,\n nodes: this.params.optionsReader().nodes,\n selection: this.params.optionsReader().selection,\n tokenKey: item.value,\n }),\n { focusAfterSync: true },\n );\n };\n\n insertFileToken = (tokenKey: string, label: string): void => {\n this.params.publishSnapshot(\n insertFileTokenIntoChatComposer({\n label,\n nodes: this.params.optionsReader().nodes,\n selection: this.params.optionsReader().selection,\n tokenKey,\n }),\n { focusAfterSync: true },\n );\n };\n\n insertFileTokens = (tokens: Array<{ tokenKey: string; label: string }>): void => {\n let nextNodes = this.params.optionsReader().nodes;\n let nextSelection = this.params.optionsReader().selection;\n\n for (const token of tokens) {\n const snapshot = insertFileTokenIntoChatComposer({\n label: token.label,\n nodes: nextNodes,\n selection: nextSelection,\n tokenKey: token.tokenKey,\n });\n nextNodes = snapshot.nodes;\n nextSelection = snapshot.selection;\n }\n\n this.params.publishSnapshot(\n {\n nodes: nextNodes,\n selection: nextSelection,\n },\n { focusAfterSync: true },\n );\n };\n\n focusComposer = (): void => {\n this.params.focusComposer();\n };\n\n focusComposerAtEnd = (): void => {\n this.params.focusComposerAtEnd();\n };\n\n syncSelectedSkills = (nextKeys: string[], options: ChatSkillPickerOption[]): void => {\n this.params.publishSnapshot(\n syncSelectedSkillsIntoChatComposer({\n nextKeys,\n nodes: this.params.optionsReader().nodes,\n options,\n selection: this.params.optionsReader().selection,\n }),\n { focusAfterSync: true },\n );\n };\n}\n\nexport function createLexicalComposerHandle(\n params: LexicalComposerHandleOwnerParams,\n): ChatInputBarTokenizedComposerHandle {\n return new LexicalComposerHandleOwner(params);\n}\n\nfunction getChatComposerContentSignature(nodes: ChatComposerNode[]): string {\n return JSON.stringify(\n nodes.map((node) =>\n node.type === 'text'\n ? { text: node.text, type: node.type }\n : {\n label: node.label,\n tokenKey: node.tokenKey,\n tokenKind: node.tokenKind,\n type: node.type,\n },\n ),\n );\n}\n\nexport function handleLexicalComposerBeforeInput(params: {\n disabled: boolean;\n event: FormEvent<HTMLDivElement>;\n isComposing: boolean;\n publishSnapshot: (snapshot: ChatComposerEditorSnapshot) => void;\n snapshotReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n}): void {\n const { disabled, event, isComposing, publishSnapshot, snapshotReader } = params;\n const nativeEvent = event.nativeEvent as InputEvent;\n const shouldInsertText =\n nativeEvent.inputType === 'insertText' ||\n nativeEvent.inputType === 'insertReplacementText';\n\n if (\n disabled ||\n isComposing ||\n nativeEvent.isComposing ||\n !shouldInsertText ||\n !nativeEvent.data\n ) {\n return;\n }\n\n event.preventDefault();\n publishSnapshot(\n replaceChatComposerSelectionWithText({\n nodes: snapshotReader().nodes,\n selection: snapshotReader().selection,\n text: nativeEvent.data,\n }),\n );\n}\n\nexport function handleLexicalComposerCompositionEnd(params: {\n data: string;\n fallbackSnapshot: () => ChatComposerEditorSnapshot;\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n snapshotReader: () => {\n nodes: ChatComposerNode[];\n selection: ChatComposerSelection | null;\n };\n}): void {\n const { data, fallbackSnapshot, publishSnapshot, snapshotReader } = params;\n const currentSnapshot = snapshotReader();\n const editorSnapshot = fallbackSnapshot();\n const shouldUseEditorSnapshot =\n getChatComposerContentSignature(editorSnapshot.nodes) !==\n getChatComposerContentSignature(currentSnapshot.nodes);\n const snapshot = shouldUseEditorSnapshot\n ? editorSnapshot\n : data.length > 0\n ? replaceChatComposerSelectionWithText({\n nodes: currentSnapshot.nodes,\n selection: currentSnapshot.selection,\n text: data,\n })\n : editorSnapshot;\n publishSnapshot(snapshot, { forcePublish: true });\n}\n\nexport function handleLexicalComposerKeyboardCommand(params: {\n actions: ComposerActions;\n activeSlashIndex: number;\n onSlashActiveIndexChange: (index: number) => void;\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n onSlashOpenChange: (open: boolean) => void;\n onSlashQueryChange?: (query: string | null) => void;\n publishSnapshot: (\n snapshot: ChatComposerEditorSnapshot,\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ) => void;\n slashItems: ChatSlashItem[];\n snapshot: ChatComposerEditorSnapshot;\n nativeEvent: KeyboardEvent;\n}): boolean {\n const {\n actions,\n activeSlashIndex,\n nativeEvent,\n onSlashActiveIndexChange,\n onSlashItemSelect,\n onSlashOpenChange,\n onSlashQueryChange,\n publishSnapshot,\n slashItems,\n snapshot,\n } = params;\n const action = resolveLexicalComposerKeyboardAction({\n activeSlashIndex,\n canStopGeneration: actions.canStopGeneration,\n isComposing: nativeEvent.isComposing,\n isSending: actions.isSending,\n isSlashMenuOpen: resolveChatComposerSlashTrigger(snapshot.nodes, snapshot.selection) !== null,\n key: nativeEvent.key,\n shiftKey: nativeEvent.shiftKey,\n slashItemCount: slashItems.length,\n });\n const activeSlashItem = slashItems[activeSlashIndex] ?? null;\n\n if (action.type !== 'noop') {\n nativeEvent.preventDefault();\n }\n\n switch (action.type) {\n case 'move-slash-index':\n onSlashActiveIndexChange(action.index);\n return true;\n case 'insert-active-slash-item':\n if (!activeSlashItem) {\n return true;\n }\n onSlashItemSelect?.(activeSlashItem);\n publishSnapshot(\n insertSkillTokenIntoChatComposer({\n label: activeSlashItem.title,\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n tokenKey: activeSlashItem.value ?? activeSlashItem.key,\n }),\n { focusAfterSync: true },\n );\n return true;\n case 'close-slash':\n onSlashQueryChange?.(null);\n onSlashOpenChange(false);\n return true;\n case 'consume':\n return true;\n case 'stop-generation':\n void actions.onStop();\n return true;\n case 'insert-line-break':\n publishSnapshot(\n replaceChatComposerSelectionWithText({\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n text: '\\n',\n }),\n );\n return true;\n case 'send-message':\n void actions.onSend();\n return true;\n case 'delete-content':\n publishSnapshot(\n deleteChatComposerContent({\n direction: action.direction,\n nodes: snapshot.nodes,\n selection: snapshot.selection,\n }),\n );\n return true;\n case 'noop':\n return false;\n }\n}\n","import { useEffect, useLayoutEffect, type MutableRefObject } from 'react';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n BLUR_COMMAND,\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_HIGH,\n KEY_DOWN_COMMAND,\n SELECTION_CHANGE_COMMAND,\n mergeRegister,\n type LexicalEditor,\n} from 'lexical';\nimport type { ChatComposerNode, ChatComposerSelection } from '../../../view-models/chat-ui.types';\nimport {\n getChatComposerNodesSignature,\n readChatComposerSnapshotFromEditorState,\n syncLexicalEditorFromChatComposerState,\n syncLexicalSelectionFromChatComposerSelection,\n} from './chat-composer-lexical-adapter';\n\ntype ChatComposerBindingsPluginProps = {\n disabled: boolean;\n editorRef: MutableRefObject<LexicalEditor | null>;\n editorSignatureRef: MutableRefObject<string>;\n isApplyingExternalUpdateRef: MutableRefObject<boolean>;\n isComposingRef: MutableRefObject<boolean>;\n lastPublishedSignatureRef: MutableRefObject<string>;\n nodes: ChatComposerNode[];\n onBlur: () => void;\n onKeyDown: (event: KeyboardEvent) => boolean;\n onNodesChange: (nodes: ChatComposerNode[]) => void;\n pendingSelectionRef: MutableRefObject<ChatComposerSelection | null>;\n selectionRef: MutableRefObject<ChatComposerSelection | null>;\n shouldFocusAfterSyncRef: MutableRefObject<boolean>;\n syncSlashState: (nodes: ChatComposerNode[], selection: ChatComposerSelection | null) => void;\n};\n\nexport function ChatComposerBindingsPlugin(\n {\n disabled,\n editorRef,\n editorSignatureRef,\n isApplyingExternalUpdateRef,\n isComposingRef,\n lastPublishedSignatureRef,\n nodes,\n onBlur,\n onKeyDown,\n onNodesChange,\n pendingSelectionRef,\n selectionRef,\n shouldFocusAfterSyncRef,\n syncSlashState,\n }: ChatComposerBindingsPluginProps,\n): null {\n const [editor] = useLexicalComposerContext();\n\n useLayoutEffect(() => {\n editorRef.current = editor;\n return () => {\n if (editorRef.current === editor) {\n editorRef.current = null;\n }\n };\n }, [editor, editorRef]);\n\n useLayoutEffect(() => {\n editor.setEditable(!disabled);\n }, [disabled, editor]);\n\n useLayoutEffect(() => {\n const nextSignature = getChatComposerNodesSignature(nodes);\n const pendingSelection = pendingSelectionRef.current;\n const shouldSyncDocument = nextSignature !== editorSignatureRef.current;\n\n if (!shouldSyncDocument && !pendingSelection) {\n return;\n }\n\n isApplyingExternalUpdateRef.current = true;\n\n if (shouldSyncDocument) {\n syncLexicalEditorFromChatComposerState(editor, nodes, pendingSelection);\n editorSignatureRef.current = nextSignature;\n lastPublishedSignatureRef.current = nextSignature;\n } else if (pendingSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, pendingSelection);\n }\n\n if (pendingSelection) {\n selectionRef.current = pendingSelection;\n pendingSelectionRef.current = null;\n }\n\n if (shouldFocusAfterSyncRef.current) {\n shouldFocusAfterSyncRef.current = false;\n const targetSelection = selectionRef.current;\n editor.focus(() => {\n if (targetSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n }\n });\n }\n\n requestAnimationFrame(() => {\n isApplyingExternalUpdateRef.current = false;\n });\n }, [\n editor,\n editorSignatureRef,\n isApplyingExternalUpdateRef,\n lastPublishedSignatureRef,\n nodes,\n pendingSelectionRef,\n selectionRef,\n shouldFocusAfterSyncRef,\n ]);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n const snapshot = readChatComposerSnapshotFromEditorState(editorState);\n const signature = getChatComposerNodesSignature(snapshot.nodes);\n\n selectionRef.current = snapshot.selection;\n editorSignatureRef.current = signature;\n syncSlashState(snapshot.nodes, snapshot.selection);\n\n if (isApplyingExternalUpdateRef.current || isComposingRef.current) {\n return;\n }\n\n if (signature === lastPublishedSignatureRef.current) {\n return;\n }\n\n lastPublishedSignatureRef.current = signature;\n onNodesChange(snapshot.nodes);\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n selectionRef.current = snapshot.selection;\n if (!isComposingRef.current) {\n syncSlashState(snapshot.nodes, snapshot.selection);\n }\n return false;\n },\n COMMAND_PRIORITY_EDITOR,\n ),\n editor.registerCommand(\n BLUR_COMMAND,\n () => {\n onBlur();\n return false;\n },\n COMMAND_PRIORITY_EDITOR,\n ),\n editor.registerCommand(\n KEY_DOWN_COMMAND,\n (event) => onKeyDown(event),\n COMMAND_PRIORITY_HIGH,\n ),\n );\n }, [\n editor,\n editorSignatureRef,\n isApplyingExternalUpdateRef,\n isComposingRef,\n lastPublishedSignatureRef,\n onBlur,\n onKeyDown,\n onNodesChange,\n selectionRef,\n syncSlashState,\n ]);\n\n return null;\n}\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type ClipboardEvent,\n type FormEvent,\n} from 'react';\nimport type { LexicalEditor } from 'lexical';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { LexicalComposer } from '@lexical/react/LexicalComposer';\nimport { EditorRefPlugin } from '@lexical/react/LexicalEditorRefPlugin';\nimport { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';\nimport { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';\nimport type {\n ChatComposerNode,\n ChatComposerSelection,\n ChatInputBarActionsProps,\n ChatSkillPickerOption,\n ChatSlashItem,\n} from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { resolveChatComposerSlashTrigger } from '@agent-chat-ui/components/chat/ui/chat-input-bar/chat-composer.utils';\nimport {\n getChatComposerNodesSignature,\n readChatComposerSnapshotFromEditorState,\n syncLexicalSelectionFromChatComposerSelection,\n writeChatComposerStateToLexicalRoot,\n} from './chat-composer-lexical-adapter';\nimport {\n createLexicalComposerHandle,\n handleLexicalComposerBeforeInput,\n handleLexicalComposerCompositionEnd,\n handleLexicalComposerKeyboardCommand,\n} from './chat-composer-lexical-controller';\nimport { ChatComposerBindingsPlugin } from './chat-composer-plugins';\nimport { ChatComposerTokenNode } from './chat-composer-token-node';\n\nexport type ChatInputBarTokenizedComposerHandle = {\n insertSlashItem: (item: ChatSlashItem) => void;\n insertFileToken: (tokenKey: string, label: string) => void;\n insertFileTokens: (tokens: Array<{ tokenKey: string; label: string }>) => void;\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n syncSelectedSkills: (nextKeys: string[], options: ChatSkillPickerOption[]) => void;\n};\n\ntype ChatInputBarTokenizedComposerProps = {\n nodes: ChatComposerNode[];\n placeholder: string;\n disabled: boolean;\n slashItems: ChatSlashItem[];\n onSlashItemSelect?: (item: ChatSlashItem) => void;\n actions: Pick<ChatInputBarActionsProps, 'onSend' | 'onStop' | 'isSending' | 'canStopGeneration'>;\n onNodesChange: (nodes: ChatComposerNode[]) => void;\n onFilesAdd?: (files: File[]) => Promise<void> | void;\n onSlashQueryChange?: (query: string | null) => void;\n onSlashTriggerChange?: (trigger: { query: string; start: number; end: number } | null) => void;\n onSlashOpenChange: (open: boolean) => void;\n onSlashActiveIndexChange: (index: number) => void;\n activeSlashIndex: number;\n};\n\nexport const ChatInputBarTokenizedComposer = forwardRef<\n ChatInputBarTokenizedComposerHandle,\n ChatInputBarTokenizedComposerProps\n>(function ChatInputBarTokenizedComposer(props, ref) {\n const editorRef = useRef<LexicalEditor | null>(null);\n const selectionRef = useRef<ChatComposerSelection | null>(null);\n const pendingSelectionRef = useRef<ChatComposerSelection | null>(null);\n const shouldFocusAfterSyncRef = useRef(false);\n const isComposingRef = useRef(false);\n const isApplyingExternalUpdateRef = useRef(false);\n const editorSignatureRef = useRef('');\n const lastPublishedSignatureRef = useRef('');\n\n const syncSlashState = (nodes: ChatComposerNode[], selection: ChatComposerSelection | null): void => {\n const trigger = resolveChatComposerSlashTrigger(nodes, selection);\n props.onSlashTriggerChange?.(trigger);\n props.onSlashQueryChange?.(trigger?.query ?? null);\n props.onSlashOpenChange(trigger !== null);\n };\n\n const readCurrentNodes = (): ChatComposerNode[] => {\n return props.nodes;\n };\n\n const readCurrentSelection = (): ChatComposerSelection | null => {\n if (selectionRef.current) {\n return selectionRef.current;\n }\n\n if (!editorRef.current) {\n return null;\n }\n\n const snapshot = readChatComposerSnapshotFromEditorState(editorRef.current.getEditorState());\n selectionRef.current = snapshot.selection;\n return snapshot.selection;\n };\n\n const publishSnapshot = (\n snapshot: { nodes: ChatComposerNode[]; selection: ChatComposerSelection | null },\n options?: { focusAfterSync?: boolean; forcePublish?: boolean },\n ): void => {\n selectionRef.current = snapshot.selection;\n pendingSelectionRef.current = snapshot.selection;\n\n if (options?.focusAfterSync) {\n shouldFocusAfterSyncRef.current = true;\n }\n\n const signature = getChatComposerNodesSignature(snapshot.nodes);\n syncSlashState(snapshot.nodes, snapshot.selection);\n\n if (options?.forcePublish || signature !== lastPublishedSignatureRef.current) {\n lastPublishedSignatureRef.current = signature;\n props.onNodesChange(snapshot.nodes);\n }\n };\n\n const focusComposer = (): void => {\n const editor = editorRef.current;\n if (!editor) {\n return;\n }\n\n editor.getRootElement()?.focus({ preventScroll: true });\n const targetSelection = selectionRef.current;\n if (targetSelection) {\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n }\n editor.focus();\n };\n\n const focusComposerAtEnd = (): void => {\n const editor = editorRef.current;\n if (!editor) {\n return;\n }\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n const end = snapshot.nodes.reduce((cursor, node) => cursor + (node.type === 'text' ? node.text.length : 1), 0);\n const targetSelection = { start: end, end };\n selectionRef.current = targetSelection;\n editor.getRootElement()?.focus({ preventScroll: true });\n syncLexicalSelectionFromChatComposerSelection(editor, targetSelection);\n editor.focus();\n };\n\n const readComposerSnapshot = (): { nodes: ChatComposerNode[]; selection: ChatComposerSelection | null } => ({\n nodes: readCurrentNodes(),\n selection: readCurrentSelection(),\n });\n\n useImperativeHandle(\n ref,\n () =>\n createLexicalComposerHandle({\n focusComposer,\n focusComposerAtEnd,\n onSlashItemSelect: props.onSlashItemSelect,\n optionsReader: readComposerSnapshot,\n publishSnapshot,\n }),\n [props.onSlashItemSelect],\n );\n\n const initialConfig = useMemo(\n () => ({\n editable: !props.disabled,\n editorState: () => {\n writeChatComposerStateToLexicalRoot(props.nodes, null);\n },\n namespace: 'NextClawChatComposerLexical',\n nodes: [ChatComposerTokenNode],\n onError: (error: Error) => {\n throw error;\n },\n theme: {},\n }),\n [props.disabled, props.nodes],\n );\n\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <div className=\"px-3 py-2 sm:px-4 sm:py-2.5\">\n <div className=\"min-h-11 sm:min-h-[60px]\">\n <PlainTextPlugin\n contentEditable={\n <ContentEditable\n className=\"min-h-7 max-h-[188px] w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent py-0.5 text-sm leading-6 text-gray-800 outline-none\"\n onBeforeInput={(event: FormEvent<HTMLDivElement>) => {\n handleLexicalComposerBeforeInput({\n disabled: props.disabled,\n event,\n isComposing: isComposingRef.current,\n publishSnapshot,\n snapshotReader: readComposerSnapshot,\n });\n }}\n onCompositionEnd={(event) => {\n isComposingRef.current = false;\n const nativeEvent = event.nativeEvent as CompositionEvent;\n handleLexicalComposerCompositionEnd({\n data: typeof nativeEvent.data === 'string' ? nativeEvent.data : '',\n fallbackSnapshot: () => {\n const editor = editorRef.current;\n return editor\n ? readChatComposerSnapshotFromEditorState(editor.getEditorState())\n : readComposerSnapshot();\n },\n publishSnapshot,\n snapshotReader: readComposerSnapshot,\n });\n }}\n onCompositionStart={() => {\n isComposingRef.current = true;\n }}\n onPaste={(event: ClipboardEvent<HTMLDivElement>) => {\n const files = Array.from(event.clipboardData.files ?? []);\n if (files.length > 0 && props.onFilesAdd) {\n event.preventDefault();\n void props.onFilesAdd(files);\n }\n }}\n />\n }\n placeholder={\n <div className=\"pointer-events-none absolute left-3 top-2 select-none text-sm leading-6 text-gray-400 sm:left-4 sm:top-2.5\">\n {props.placeholder}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n </div>\n </div>\n <EditorRefPlugin editorRef={editorRef} />\n <ChatComposerBindingsPlugin\n disabled={props.disabled}\n editorRef={editorRef}\n editorSignatureRef={editorSignatureRef}\n isApplyingExternalUpdateRef={isApplyingExternalUpdateRef}\n isComposingRef={isComposingRef}\n lastPublishedSignatureRef={lastPublishedSignatureRef}\n nodes={props.nodes}\n onBlur={() => {\n props.onSlashQueryChange?.(null);\n props.onSlashOpenChange(false);\n }}\n onKeyDown={(event) => {\n const editor = editorRef.current;\n if (!editor) {\n return false;\n }\n\n const snapshot = readChatComposerSnapshotFromEditorState(editor.getEditorState());\n selectionRef.current = snapshot.selection;\n return handleLexicalComposerKeyboardCommand({\n actions: props.actions,\n activeSlashIndex: props.activeSlashIndex,\n nativeEvent: event,\n onSlashActiveIndexChange: props.onSlashActiveIndexChange,\n onSlashItemSelect: props.onSlashItemSelect,\n onSlashOpenChange: props.onSlashOpenChange,\n onSlashQueryChange: props.onSlashQueryChange,\n publishSnapshot,\n slashItems: props.slashItems,\n snapshot,\n });\n }}\n onNodesChange={props.onNodesChange}\n pendingSelectionRef={pendingSelectionRef}\n selectionRef={selectionRef}\n shouldFocusAfterSyncRef={shouldFocusAfterSyncRef}\n syncSlashState={syncSlashState}\n />\n </LexicalComposer>\n );\n});\n\nChatInputBarTokenizedComposer.displayName = 'LexicalChatInputBarTokenizedComposer';\n","import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport type { ChatInputBarProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { ChatSlashMenu } from './chat-slash-menu';\nimport { ChatInputBarToolbar } from './chat-input-bar-toolbar';\nimport { ChatInputBarTokenizedComposer, type ChatInputBarTokenizedComposerHandle } from './chat-input-bar-tokenized-composer';\n\nfunction InputBarHint({ hint }: { hint: ChatInputBarProps['hint'] }) {\n if (!hint) {\n return null;\n }\n\n if (hint.loading) {\n return (\n <div className=\"px-4 pb-2\">\n <div className=\"inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2\">\n <span className=\"h-3 w-28 animate-pulse rounded bg-gray-200\" />\n <span className=\"h-3 w-16 animate-pulse rounded bg-gray-200\" />\n </div>\n </div>\n );\n }\n\n const toneClassName =\n hint.tone === 'warning'\n ? 'border-amber-200 bg-amber-50 text-amber-800'\n : 'border-gray-200 bg-gray-50 text-gray-700';\n\n return (\n <div className=\"px-4 pb-2\">\n <div className={`inline-flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs ${toneClassName}`}>\n {hint.text ? <span>{hint.text}</span> : null}\n {hint.actionLabel && hint.onAction ? (\n <button\n type=\"button\"\n onClick={hint.onAction}\n className=\"font-semibold underline-offset-2 hover:underline\"\n >\n {hint.actionLabel}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport type ChatInputBarHandle = {\n insertFileToken: (tokenKey: string, label: string) => void;\n insertFileTokens: (tokens: Array<{ tokenKey: string; label: string }>) => void;\n focusComposer: () => void;\n focusComposerAtEnd: () => void;\n};\n\nexport const ChatInputBar = forwardRef<ChatInputBarHandle, ChatInputBarProps>(function ChatInputBar(props, ref) {\n const composerRef = useRef<ChatInputBarTokenizedComposerHandle | null>(null);\n const isSlashMenuInteractionRef = useRef(false);\n const [activeSlashIndex, setActiveSlashIndex] = useState(0);\n const [activeSlashTriggerStart, setActiveSlashTriggerStart] = useState<number | null>(null);\n const [dismissedSlashTriggerStart, setDismissedSlashTriggerStart] = useState<number | null>(null);\n const isSlashPanelOpen = activeSlashTriggerStart !== null && dismissedSlashTriggerStart !== activeSlashTriggerStart;\n const activeSlashItem = props.slashMenu.items[activeSlashIndex] ?? null;\n const dismissSlashTrigger = () => activeSlashTriggerStart !== null && !isSlashMenuInteractionRef.current\n ? setDismissedSlashTriggerStart(activeSlashTriggerStart)\n : undefined;\n\n useEffect(() => {\n setActiveSlashIndex((current) => {\n if (props.slashMenu.items.length === 0) {\n return 0;\n }\n return Math.min(current, props.slashMenu.items.length - 1);\n });\n }, [props.slashMenu.items.length]);\n\n useEffect(() => {\n if (activeSlashTriggerStart === null && dismissedSlashTriggerStart !== null) {\n setDismissedSlashTriggerStart(null);\n }\n }, [activeSlashTriggerStart, dismissedSlashTriggerStart]);\n\n const toolbar = useMemo(() => {\n if (!props.toolbar.skillPicker) {\n return props.toolbar;\n }\n return {\n ...props.toolbar,\n skillPicker: {\n ...props.toolbar.skillPicker,\n onSelectedKeysChange: (nextKeys: string[]) => {\n composerRef.current?.syncSelectedSkills(nextKeys, props.toolbar.skillPicker?.options ?? []);\n props.toolbar.skillPicker?.onSelectedKeysChange(nextKeys);\n }\n }\n };\n }, [props.toolbar]);\n\n useImperativeHandle(ref, () => ({\n insertFileToken: (tokenKey, label) => composerRef.current?.insertFileToken(tokenKey, label),\n insertFileTokens: (tokens) => composerRef.current?.insertFileTokens(tokens),\n focusComposer: () => composerRef.current?.focusComposer(),\n focusComposerAtEnd: () => composerRef.current?.focusComposerAtEnd(),\n }), []);\n\n return (\n <div className=\"border-t border-gray-200/80 bg-white px-3 py-3 sm:px-4 sm:py-4\">\n <div className=\"nextclaw-chat-input-bar-shell mx-auto w-full max-w-[min(1120px,100%)] [container:nextclaw-chat-input-bar/inline-size]\">\n <div className=\"overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-card\">\n <div className=\"relative\">\n <ChatInputBarTokenizedComposer\n ref={composerRef}\n nodes={props.composer.nodes}\n placeholder={props.composer.placeholder}\n disabled={props.composer.disabled}\n slashItems={props.slashMenu.items}\n onSlashItemSelect={props.slashMenu.onSelectItem}\n actions={props.toolbar.actions}\n activeSlashIndex={activeSlashIndex}\n onNodesChange={props.composer.onNodesChange}\n onFilesAdd={props.composer.onFilesAdd}\n onSlashQueryChange={(query) => {\n if (query === null && isSlashMenuInteractionRef.current) return;\n if (query !== null) setActiveSlashIndex(0);\n props.composer.onSlashQueryChange?.(query);\n }}\n onSlashTriggerChange={(trigger) => {\n setActiveSlashTriggerStart(trigger?.start ?? null);\n }}\n onSlashOpenChange={(open) => {\n if (!open) dismissSlashTrigger();\n }}\n onSlashActiveIndexChange={setActiveSlashIndex}\n />\n <ChatSlashMenu\n isOpen={isSlashPanelOpen}\n isLoading={props.slashMenu.isLoading}\n items={props.slashMenu.items}\n activeIndex={activeSlashIndex}\n activeItem={activeSlashItem}\n texts={props.slashMenu.texts}\n onSelectItem={(item) => {\n setDismissedSlashTriggerStart(null);\n composerRef.current?.insertSlashItem(item);\n }}\n onOpenChange={(open) => {\n if (!open) dismissSlashTrigger();\n }}\n onDetailsPointerDown={() => {\n isSlashMenuInteractionRef.current = true;\n requestAnimationFrame(() => { isSlashMenuInteractionRef.current = false; });\n }}\n onSetActiveIndex={setActiveSlashIndex}\n />\n </div>\n\n <InputBarHint hint={props.hint} />\n <ChatInputBarToolbar {...toolbar} />\n </div>\n </div>\n </div>\n );\n});\n\nChatInputBar.displayName = 'ChatInputBar';\n","import type { ChatMessageRole } from '../../view-models/chat-ui.types';\nimport { Bot, User, Wrench } from 'lucide-react';\n\nexport function ChatMessageAvatar({ role }: { role: ChatMessageRole }) {\n if (role === 'user') {\n return (\n <div\n data-testid=\"chat-message-avatar-user\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-white shadow-sm\"\n >\n <User className=\"h-4 w-4\" />\n </div>\n );\n }\n if (role === 'tool') {\n return (\n <div\n data-testid=\"chat-message-avatar-tool\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-amber-100 text-amber-700 shadow-sm\"\n >\n <Wrench className=\"h-4 w-4\" />\n </div>\n );\n }\n return (\n <div\n data-testid=\"chat-message-avatar-assistant\"\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gradient-to-b from-gray-700 to-gray-950 text-white shadow-md ring-1 ring-inset ring-white/20\"\n >\n <Bot className=\"h-[18px] w-[18px] text-white/95\" strokeWidth={2.5} />\n </div>\n );\n}\n","function canUseClipboardApi(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n typeof navigator.clipboard?.writeText === 'function'\n );\n}\n\nfunction restoreSelection(ranges: Range[]) {\n if (typeof document === 'undefined') {\n return;\n }\n\n const selection = document.getSelection();\n if (!selection) {\n return;\n }\n\n selection.removeAllRanges();\n ranges.forEach((range) => selection.addRange(range));\n}\n\nfunction fallbackCopyText(text: string): boolean {\n if (typeof document === 'undefined' || !document.body) {\n return false;\n }\n\n const activeElement = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const activeInput = activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement\n ? activeElement\n : null;\n const activeSelection = activeInput\n ? {\n start: activeInput.selectionStart,\n end: activeInput.selectionEnd\n }\n : null;\n const selection = document.getSelection();\n const ranges = selection\n ? Array.from({ length: selection.rangeCount }, (_, index) => selection.getRangeAt(index).cloneRange())\n : [];\n\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.setAttribute('readonly', '');\n textarea.setAttribute('aria-hidden', 'true');\n textarea.style.position = 'fixed';\n textarea.style.top = '0';\n textarea.style.left = '-9999px';\n textarea.style.opacity = '0';\n textarea.style.pointerEvents = 'none';\n textarea.style.fontSize = '12pt';\n\n document.body.appendChild(textarea);\n\n try {\n textarea.focus({ preventScroll: true });\n } catch {\n textarea.focus();\n }\n\n textarea.select();\n textarea.setSelectionRange(0, textarea.value.length);\n\n let copied = false;\n try {\n copied = typeof document.execCommand === 'function' && document.execCommand('copy');\n } catch {\n copied = false;\n }\n\n textarea.remove();\n\n if (activeElement) {\n try {\n activeElement.focus({ preventScroll: true });\n } catch {\n activeElement.focus();\n }\n }\n\n if (activeInput && activeSelection) {\n activeInput.setSelectionRange(activeSelection.start, activeSelection.end);\n } else {\n restoreSelection(ranges);\n }\n\n return copied;\n}\n\nexport async function copyText(text: string): Promise<boolean> {\n if (!text) {\n return false;\n }\n\n if (canUseClipboardApi()) {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return fallbackCopyText(text);\n }\n }\n\n return fallbackCopyText(text);\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { copyText } from '../utils/copy-text';\n\ntype UseCopyFeedbackParams = {\n text: string;\n resetDelayMs?: number;\n};\n\ntype UseCopyFeedbackResult = {\n copied: boolean;\n copy: () => Promise<void>;\n};\n\nconst DEFAULT_RESET_DELAY_MS = 1300;\n\nexport function useCopyFeedback(params: UseCopyFeedbackParams): UseCopyFeedbackResult {\n const [copied, setCopied] = useState(false);\n\n const copy = useCallback(async () => {\n if (!params.text) {\n return;\n }\n\n const didCopy = await copyText(params.text);\n if (didCopy) {\n setCopied(true);\n } else {\n setCopied(false);\n }\n }, [params.text]);\n\n useEffect(() => {\n if (!copied || typeof window === 'undefined') {\n return;\n }\n\n const timer = window.setTimeout(() => setCopied(false), params.resetDelayMs ?? DEFAULT_RESET_DELAY_MS);\n return () => window.clearTimeout(timer);\n }, [copied, params.resetDelayMs]);\n\n return {\n copied,\n copy\n };\n}\n","import hljs from 'highlight.js/lib/core';\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport diff from 'highlight.js/lib/languages/diff';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport shell from 'highlight.js/lib/languages/shell';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport type { HLJSApi, LanguageFn } from 'highlight.js';\n\nconst PLAIN_TEXT_LANGUAGES = new Set([\n 'text',\n 'txt',\n 'plain',\n 'plaintext',\n 'none',\n 'output',\n]);\n\nconst AUTO_DETECT_LANGUAGES = [\n 'typescript',\n 'javascript',\n 'json',\n 'bash',\n 'shell',\n 'python',\n 'css',\n 'xml',\n 'markdown',\n 'yaml',\n 'sql',\n 'diff',\n];\n\nconst AUTO_DETECT_MIN_RELEVANCE = 4;\n\ntype RegisteredLanguage = {\n name: string;\n language: LanguageFn;\n aliases?: string[];\n};\n\nconst REGISTERED_LANGUAGES: RegisteredLanguage[] = [\n { name: 'typescript', language: typescript, aliases: ['ts', 'tsx'] },\n { name: 'javascript', language: javascript, aliases: ['js', 'jsx', 'mjs', 'cjs'] },\n { name: 'json', language: json, aliases: ['jsonc'] },\n { name: 'bash', language: bash, aliases: ['sh', 'zsh'] },\n { name: 'shell', language: shell, aliases: ['console', 'terminal'] },\n { name: 'python', language: python, aliases: ['py'] },\n { name: 'css', language: css },\n { name: 'xml', language: xml, aliases: ['html', 'svg'] },\n { name: 'markdown', language: markdown, aliases: ['md', 'mdx'] },\n { name: 'yaml', language: yaml, aliases: ['yml'] },\n { name: 'sql', language: sql },\n { name: 'diff', language: diff, aliases: ['patch'] },\n];\n\nexport type ChatCodeHighlightResult = {\n html: string;\n language: string;\n highlighted: boolean;\n};\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction normalizeLanguage(value: string): string {\n return value.trim().toLowerCase();\n}\n\nexport class ChatCodeSyntaxHighlighter {\n private readonly engine: HLJSApi;\n\n constructor() {\n this.engine = hljs.newInstance();\n REGISTERED_LANGUAGES.forEach((entry) => {\n this.engine.registerLanguage(entry.name, entry.language);\n if (entry.aliases) {\n this.engine.registerAliases(entry.aliases, { languageName: entry.name });\n }\n });\n }\n\n highlight = (code: string, language: string): ChatCodeHighlightResult => {\n const normalizedLanguage = normalizeLanguage(language);\n if (!code || PLAIN_TEXT_LANGUAGES.has(normalizedLanguage)) {\n return this.createPlainTextResult(code, normalizedLanguage || 'text');\n }\n\n if (this.engine.getLanguage(normalizedLanguage)) {\n const result = this.engine.highlight(code, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n });\n return {\n html: result.value,\n language: result.language ?? normalizedLanguage,\n highlighted: true,\n };\n }\n\n const autoDetected = this.engine.highlightAuto(code, AUTO_DETECT_LANGUAGES);\n if (autoDetected.language && autoDetected.relevance >= AUTO_DETECT_MIN_RELEVANCE) {\n return {\n html: autoDetected.value,\n language: autoDetected.language,\n highlighted: true,\n };\n }\n\n return this.createPlainTextResult(code, normalizedLanguage || 'text');\n };\n\n private createPlainTextResult = (code: string, language: string): ChatCodeHighlightResult => ({\n html: escapeHtml(code),\n language,\n highlighted: false,\n });\n}\n\nexport const chatCodeSyntaxHighlighter = new ChatCodeSyntaxHighlighter();\n","import { useMemo, type ReactNode } from 'react';\nimport { useCopyFeedback } from '../../hooks/use-copy-feedback';\nimport type { ChatMessageTexts } from '../../view-models/chat-ui.types';\nimport { Check, Copy } from 'lucide-react';\nimport { cn } from '../../internal/cn';\nimport { chatCodeSyntaxHighlighter } from './code-block/chat-code-syntax-highlighter';\n\nconst CODE_LANGUAGE_REGEX = /language-([a-z0-9-]+)/i;\n\nfunction flattenNodeText(value: ReactNode): string {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value);\n }\n if (Array.isArray(value)) {\n return value.map(flattenNodeText).join('');\n }\n return '';\n}\n\nfunction normalizeCodeText(value: ReactNode): string {\n const content = flattenNodeText(value);\n return content.endsWith('\\n') ? content.slice(0, -1) : content;\n}\n\nfunction resolveCodeLanguage(className?: string): string {\n const match = className ? CODE_LANGUAGE_REGEX.exec(className) : null;\n return match?.[1]?.toLowerCase() || 'text';\n}\n\ntype ChatCodeBlockProps = {\n className?: string;\n children: ReactNode;\n texts: Pick<ChatMessageTexts, 'copyCodeLabel' | 'copiedCodeLabel'>;\n};\n\nexport function ChatCodeBlock({ className, children, texts }: ChatCodeBlockProps) {\n const language = useMemo(() => resolveCodeLanguage(className), [className]);\n const codeText = useMemo(() => normalizeCodeText(children), [children]);\n const highlightedCode = useMemo(\n () => chatCodeSyntaxHighlighter.highlight(codeText, language),\n [codeText, language],\n );\n const codeClassName = useMemo(() => {\n const highlightedLanguageClass = `language-${highlightedCode.language}`;\n return cn(\n 'hljs',\n className,\n className?.includes('language-') ? undefined : highlightedLanguageClass,\n );\n }, [className, highlightedCode.language]);\n const { copied, copy } = useCopyFeedback({ text: codeText });\n\n return (\n <div className=\"chat-codeblock\">\n <div className=\"chat-codeblock-toolbar\">\n <span className=\"chat-codeblock-language\">{language}</span>\n <button\n type=\"button\"\n className=\"chat-codeblock-copy\"\n onClick={() => void copy()}\n aria-label={copied ? texts.copiedCodeLabel : texts.copyCodeLabel}\n >\n {copied ? <Check className=\"h-3.5 w-3.5\" /> : <Copy className=\"h-3.5 w-3.5\" />}\n <span>{copied ? texts.copiedCodeLabel : texts.copyCodeLabel}</span>\n </button>\n </div>\n <pre>\n <code\n className={codeClassName}\n data-highlighted={highlightedCode.highlighted ? 'true' : 'false'}\n dangerouslySetInnerHTML={{ __html: highlightedCode.html }}\n />\n </pre>\n </div>\n );\n}\n","import { useMemo, type MouseEvent, type ReactNode } from 'react';\nimport type { Components } from 'react-markdown';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { cn } from '../../internal/cn';\nimport { ChatCodeBlock } from './chat-code-block';\nimport type {\n ChatFileOpenActionViewModel,\n ChatMessageRole,\n ChatMessageTexts,\n} from '../../view-models/chat-ui.types';\n\nconst MARKDOWN_MAX_CHARS = 140_000;\nconst SAFE_LINK_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\nfunction trimMarkdown(value: string): string {\n if (value.length <= MARKDOWN_MAX_CHARS) {\n return value;\n }\n return `${value.slice(0, MARKDOWN_MAX_CHARS)}\\n\\n...`;\n}\n\nfunction resolveSafeHref(href?: string): string | null {\n if (!href) {\n return null;\n }\n if (href.startsWith('#') || href.startsWith('/') || href.startsWith('./') || href.startsWith('../')) {\n return href;\n }\n try {\n const url = new URL(href);\n return SAFE_LINK_PROTOCOLS.has(url.protocol) ? href : null;\n } catch {\n return null;\n }\n}\n\nfunction isExternalHref(href: string): boolean {\n return /^https?:\\/\\//i.test(href);\n}\n\nfunction looksLikeLocalFileHref(href: string): boolean {\n return (\n href.startsWith('./') ||\n href.startsWith('../') ||\n href.startsWith('/Users/') ||\n href.startsWith('/home/') ||\n href.startsWith('/tmp/') ||\n href.startsWith('/var/') ||\n /^\\/.+\\.[A-Za-z0-9_-]+(?::\\d+(?::\\d+)?)?$/.test(href)\n );\n}\n\nfunction parseLocalFileAction(href: string): ChatFileOpenActionViewModel | null {\n const normalizedHref = href.split('#')[0]?.split('?')[0] ?? href;\n const decodedHref = decodeURIComponent(normalizedHref);\n if (!looksLikeLocalFileHref(decodedHref)) {\n return null;\n }\n const lineMatch = /^(.*?)(?::(\\d+)(?::(\\d+))?)$/.exec(decodedHref);\n const rawPath = lineMatch?.[1] ?? decodedHref;\n const line = lineMatch?.[2] ? Number(lineMatch[2]) : undefined;\n const column = lineMatch?.[3] ? Number(lineMatch[3]) : undefined;\n return {\n path: rawPath,\n label: rawPath.split('/').filter(Boolean).pop() ?? rawPath,\n viewMode: 'preview',\n ...(typeof line === 'number' ? { line } : {}),\n ...(typeof column === 'number' ? { column } : {}),\n };\n}\n\ntype ChatMessageMarkdownProps = {\n text: string;\n role: ChatMessageRole;\n texts: Pick<ChatMessageTexts, 'copyCodeLabel' | 'copiedCodeLabel'>;\n inline?: boolean;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n};\n\nexport function ChatMessageMarkdown({\n text,\n role,\n texts,\n inline = false,\n onFileOpen,\n}: ChatMessageMarkdownProps) {\n const isUser = role === 'user';\n const markdownComponents = useMemo<Components>(() => ({\n p: ({ children }) => (inline ? <>{children}</> : <p>{children}</p>),\n a: ({ href, children, ...rest }) => {\n const safeHref = resolveSafeHref(href);\n if (!safeHref) {\n return <span className=\"chat-link-invalid\">{children}</span>;\n }\n const external = isExternalHref(safeHref);\n const localFileAction = external ? null : parseLocalFileAction(safeHref);\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n if (!onFileOpen || !localFileAction) {\n return;\n }\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) {\n return;\n }\n event.preventDefault();\n onFileOpen(localFileAction);\n };\n return (\n <a\n {...rest}\n href={safeHref}\n onClick={handleClick}\n target={external ? '_blank' : undefined}\n rel={external ? 'noreferrer noopener' : undefined}\n >\n {children}\n </a>\n );\n },\n table: ({ children, ...rest }) => (\n <div className=\"chat-table-wrap\">\n <table {...rest}>{children}</table>\n </div>\n ),\n input: ({ type, checked, ...rest }) => {\n if (type !== 'checkbox') {\n return <input {...rest} type={type} />;\n }\n return <input {...rest} type=\"checkbox\" checked={checked} readOnly disabled className=\"chat-task-checkbox\" />;\n },\n img: ({ src, alt, ...rest }) => {\n const safeSrc = resolveSafeHref(src);\n if (!safeSrc) {\n return null;\n }\n return <img {...rest} src={safeSrc} alt={alt || ''} loading=\"lazy\" decoding=\"async\" />;\n },\n code: ({ className, children, ...rest }) => {\n const plainText = String(children ?? '');\n const isInlineCode = !className && !plainText.includes('\\n');\n if (isInlineCode) {\n return (\n <code {...rest} className={cn('chat-inline-code', className)}>\n {children}\n </code>\n );\n }\n return (\n <ChatCodeBlock className={className} texts={texts}>\n {children as ReactNode}\n </ChatCodeBlock>\n );\n }\n }), [inline, onFileOpen, texts]);\n\n const WrapperTag = inline ? 'span' : 'div';\n\n return (\n <WrapperTag className={cn('chat-markdown', isUser ? 'chat-markdown-user' : 'chat-markdown-assistant')}>\n <ReactMarkdown skipHtml remarkPlugins={[remarkGfm]} components={markdownComponents}>\n {trimMarkdown(text)}\n </ReactMarkdown>\n </WrapperTag>\n );\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatInlineContentSegmentViewModel,\n ChatMessageRole,\n ChatMessageTexts,\n} from \"../../view-models/chat-ui.types\";\nimport { cn } from \"../../internal/cn\";\nimport { ChatMessageMarkdown } from \"./chat-message-markdown\";\n\ntype ChatMessageInlineContentProps = {\n segments: ChatInlineContentSegmentViewModel[];\n role: ChatMessageRole;\n texts: Pick<ChatMessageTexts, \"copyCodeLabel\" | \"copiedCodeLabel\">;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n};\n\nfunction hasVisibleInlineText(value: string): boolean {\n return value\n .split(\"\\u200B\")\n .join(\"\")\n .split(\"\\u200C\")\n .join(\"\")\n .split(\"\\u200D\")\n .join(\"\")\n .split(\"\\u2060\")\n .join(\"\")\n .split(\"\\uFEFF\")\n .join(\"\").length > 0;\n}\n\nfunction ChatInlineSkillIcon() {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n >\n <path d=\"M8.5 2.75 2.75 6l5.75 3.25L14.25 6 8.5 2.75Z\" />\n <path d=\"M2.75 10 8.5 13.25 14.25 10\" />\n <path d=\"M2.75 6v4l5.75 3.25V9.25L2.75 6Z\" />\n <path d=\"M14.25 6v4L8.5 13.25V9.25L14.25 6Z\" />\n </svg>\n );\n}\n\nfunction ChatInlineTokenBadge({\n kind,\n label,\n isUser,\n}: {\n kind: string;\n label: string;\n isUser: boolean;\n}) {\n const isSkill = kind === \"skill\";\n return (\n <span\n className={cn(\n \"mx-[2px] inline-flex h-7 max-w-full items-center gap-1.5 rounded-xl border px-2.5 align-baseline text-[11px] font-medium shadow-[0_0_0_1px_rgba(15,23,42,0.03)]\",\n isSkill\n ? isUser\n ? \"border-emerald-200/35 bg-emerald-400/18 text-emerald-50/95\"\n : \"border-emerald-200/70 bg-emerald-50 text-emerald-700\"\n : isUser\n ? \"border-white/30 bg-white/18 text-white\"\n : \"border-slate-200/80 bg-slate-100 text-slate-700\",\n )}\n title={label}\n >\n <span\n className={cn(\n \"inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center\",\n isSkill\n ? isUser\n ? \"text-emerald-100/90\"\n : \"text-emerald-600\"\n : isUser\n ? \"text-white/70\"\n : \"text-slate-500\",\n )}\n >\n <ChatInlineSkillIcon />\n </span>\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n\nexport function ChatMessageInlineContent({\n segments,\n role,\n texts,\n onFileOpen,\n}: ChatMessageInlineContentProps) {\n const isUser = role === \"user\";\n\n return (\n <div className=\"whitespace-pre-wrap break-words leading-6\">\n {segments.map((segment, index) => {\n if (segment.type === \"token\") {\n return (\n <ChatInlineTokenBadge\n key={`token-${index}-${segment.token.kind}-${segment.token.key}`}\n kind={segment.token.kind}\n label={segment.token.label}\n isUser={isUser}\n />\n );\n }\n if (!hasVisibleInlineText(segment.text)) {\n return (\n <span key={`space-${index}`} className=\"whitespace-pre-wrap\">\n {segment.text}\n </span>\n );\n }\n return (\n <ChatMessageMarkdown\n key={`markdown-${index}`}\n text={segment.text}\n role={role}\n texts={texts}\n inline\n onFileOpen={onFileOpen}\n />\n );\n })}\n </div>\n );\n}\n","import type {\n ChatAttachmentCategory,\n ChatMessagePartViewModel,\n} from \"../../../view-models/chat-ui.types\";\n\nexport type ChatMessageFileView = Extract<\n ChatMessagePartViewModel,\n { type: \"file\" }\n>[\"file\"];\n\nexport type FileCategory = ChatAttachmentCategory;\n\nexport const FILE_CATEGORY_TILE_CLASSES: Record<FileCategory, string> = {\n archive: \"border-amber-200/80 bg-amber-50 text-amber-700\",\n audio: \"border-fuchsia-200/80 bg-fuchsia-50 text-fuchsia-700\",\n code: \"border-cyan-200/80 bg-cyan-50 text-cyan-700\",\n data: \"border-slate-200/80 bg-slate-50 text-slate-700\",\n document: \"border-blue-200/80 bg-blue-50 text-blue-700\",\n generic: \"border-slate-200/80 bg-slate-50 text-slate-700\",\n image: \"border-emerald-200/80 bg-emerald-50 text-emerald-700\",\n pdf: \"border-rose-200/80 bg-rose-50 text-rose-700\",\n sheet: \"border-lime-200/80 bg-lime-50 text-lime-700\",\n video: \"border-violet-200/80 bg-violet-50 text-violet-700\",\n};\n\nconst CODE_EXTENSIONS = new Set([\n \"c\",\n \"cpp\",\n \"css\",\n \"go\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"md\",\n \"php\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"svg\",\n \"ts\",\n \"tsx\",\n]);\n\nconst DATA_EXTENSIONS = new Set([\n \"graphql\",\n \"json\",\n \"toml\",\n \"xml\",\n \"yaml\",\n \"yml\",\n]);\nconst IMAGE_EXTENSIONS = new Set([\n \"avif\",\n \"bmp\",\n \"gif\",\n \"heic\",\n \"heif\",\n \"ico\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"tif\",\n \"tiff\",\n \"webp\",\n]);\nconst AUDIO_EXTENSIONS = new Set([\n \"aac\",\n \"flac\",\n \"m4a\",\n \"mp3\",\n \"ogg\",\n \"opus\",\n \"wav\",\n \"weba\",\n]);\nconst VIDEO_EXTENSIONS = new Set([\n \"avi\",\n \"m4v\",\n \"mov\",\n \"mp4\",\n \"mkv\",\n \"webm\",\n \"wmv\",\n]);\nconst DOCUMENT_EXTENSIONS = new Set([\n \"doc\",\n \"docx\",\n \"odt\",\n \"pages\",\n \"rtf\",\n \"txt\",\n]);\nconst SHEET_EXTENSIONS = new Set([\n \"csv\",\n \"numbers\",\n \"ods\",\n \"tsv\",\n \"xls\",\n \"xlsx\",\n]);\nconst ARCHIVE_EXTENSIONS = new Set([\n \"7z\",\n \"bz2\",\n \"gz\",\n \"rar\",\n \"tar\",\n \"tgz\",\n \"zip\",\n]);\n\nfunction formatFileSize(sizeBytes?: number): string | null {\n if (!Number.isFinite(sizeBytes) || sizeBytes == null || sizeBytes < 0) {\n return null;\n }\n if (sizeBytes === 0) {\n return \"0 B\";\n }\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let value = sizeBytes;\n let unitIndex = 0;\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n const digits = value >= 10 || unitIndex === 0 ? 0 : 1;\n return `${value.toFixed(digits).replace(/\\.0$/, \"\")} ${units[unitIndex]}`;\n}\n\nfunction getFileExtension(label: string, mimeType: string): string {\n const extension = readFileExtension(label);\n if (extension) {\n return extension.toUpperCase();\n }\n const subtype = mimeType.split(\"/\")[1] ?? \"\";\n const cleaned = subtype.split(/[+.;-]/)[0]?.trim();\n if (!cleaned) {\n return \"FILE\";\n }\n return cleaned.slice(0, 6).toUpperCase();\n}\n\nfunction readFileExtension(label: string): string {\n return /\\.([a-z0-9]{1,12})$/i.exec(label.trim())?.[1]?.toLowerCase() ?? \"\";\n}\n\nfunction truncateDisplayCode(value: string): string {\n return value.trim().slice(0, 4).toUpperCase();\n}\n\nfunction isImageDataUrl(dataUrl?: string): boolean {\n return typeof dataUrl === \"string\" && /^data:image\\//i.test(dataUrl.trim());\n}\n\nfunction inferMimeTypeFromExtension(extension: string): string | null {\n if (IMAGE_EXTENSIONS.has(extension)) {\n if (extension === \"jpg\" || extension === \"jpeg\") {\n return \"image/jpeg\";\n }\n if (extension === \"svg\") {\n return \"image/svg+xml\";\n }\n return `image/${extension}`;\n }\n if (AUDIO_EXTENSIONS.has(extension)) {\n if (extension === \"mp3\") {\n return \"audio/mpeg\";\n }\n if (extension === \"m4a\") {\n return \"audio/mp4\";\n }\n if (extension === \"weba\") {\n return \"audio/webm\";\n }\n return `audio/${extension}`;\n }\n if (VIDEO_EXTENSIONS.has(extension)) {\n if (extension === \"mov\") {\n return \"video/quicktime\";\n }\n if (extension === \"m4v\") {\n return \"video/mp4\";\n }\n return `video/${extension}`;\n }\n if (extension === \"pdf\") {\n return \"application/pdf\";\n }\n return null;\n}\n\nexport function inferMimeTypeFromFileName(fileName: string): string | null {\n const extension = readFileExtension(fileName);\n if (!extension) {\n return null;\n }\n return inferMimeTypeFromExtension(extension);\n}\n\nexport function resolveRenderableMimeType(file: ChatMessageFileView): string | null {\n const normalizedMimeType = file.mimeType.trim().toLowerCase();\n if (\n normalizedMimeType.length > 0 &&\n normalizedMimeType !== \"application/octet-stream\"\n ) {\n return normalizedMimeType;\n }\n return inferMimeTypeFromFileName(file.label);\n}\n\nexport function isImageFileLike(file: ChatMessageFileView): boolean {\n const normalizedMimeType = file.mimeType.trim().toLowerCase();\n const extension = readFileExtension(file.label);\n return (\n file.isImage ||\n normalizedMimeType.startsWith(\"image/\") ||\n IMAGE_EXTENSIONS.has(extension) ||\n isImageDataUrl(file.dataUrl)\n );\n}\n\nfunction resolveFileCategory(label: string, mimeType: string): FileCategory {\n const extension = readFileExtension(label);\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedMimeType.startsWith(\"image/\") || IMAGE_EXTENSIONS.has(extension)) {\n return \"image\";\n }\n if (normalizedMimeType.startsWith(\"audio/\") || AUDIO_EXTENSIONS.has(extension)) {\n return \"audio\";\n }\n if (normalizedMimeType.startsWith(\"video/\") || VIDEO_EXTENSIONS.has(extension)) {\n return \"video\";\n }\n if (normalizedMimeType.includes(\"pdf\") || extension === \"pdf\") {\n return \"pdf\";\n }\n if (\n ARCHIVE_EXTENSIONS.has(extension) ||\n /(zip|tar|gzip|rar|compressed|archive)/.test(normalizedMimeType)\n ) {\n return \"archive\";\n }\n if (\n SHEET_EXTENSIONS.has(extension) ||\n /(spreadsheet|sheet|excel|csv)/.test(normalizedMimeType)\n ) {\n return \"sheet\";\n }\n if (\n DATA_EXTENSIONS.has(extension) ||\n /(json|xml|yaml|toml)/.test(normalizedMimeType)\n ) {\n return \"data\";\n }\n if (\n CODE_EXTENSIONS.has(extension) ||\n /(javascript|typescript|jsx|tsx|css|html)/.test(normalizedMimeType)\n ) {\n return \"code\";\n }\n if (\n DOCUMENT_EXTENSIONS.has(extension) ||\n /(msword|document|opendocument|rtf|text\\/)/.test(normalizedMimeType)\n ) {\n return \"document\";\n }\n return \"generic\";\n}\n\nexport function buildChatMessageFileMeta(file: ChatMessageFileView): {\n category: FileCategory;\n extension: string;\n sizeLabel: string | null;\n} {\n const category = resolveFileCategory(file.label, file.mimeType);\n const sizeLabel = formatFileSize(file.sizeBytes);\n return {\n category,\n extension: getFileExtension(file.label, file.mimeType),\n sizeLabel,\n };\n}\n\nexport function getFileCategoryDisplayCode(\n category: FileCategory,\n extension: string,\n): string {\n if (category === \"image\") {\n return \"IMG\";\n }\n if (category === \"video\") {\n return \"VID\";\n }\n if (category === \"audio\") {\n return \"AUD\";\n }\n if (category === \"generic\") {\n return truncateDisplayCode(extension || \"FILE\");\n }\n return truncateDisplayCode(extension);\n}\n","import { cn } from \"../../../internal/cn\";\nimport {\n File,\n FileArchive,\n FileAudio2,\n FileCode2,\n FileImage,\n FileJson2,\n FileSpreadsheet,\n FileText,\n FileVideo2,\n} from \"lucide-react\";\nimport {\n buildChatMessageFileMeta,\n FILE_CATEGORY_TILE_CLASSES,\n isImageFileLike,\n resolveRenderableMimeType,\n type FileCategory,\n type ChatMessageFileView,\n} from \"./meta\";\nimport type { ChatMessageTexts } from \"../../../view-models/chat-ui.types\";\n\ntype ChatMessageFileProps = {\n file: ChatMessageFileView;\n isUser?: boolean;\n texts?: Pick<\n ChatMessageTexts,\n \"attachmentOpenLabel\" | \"attachmentAttachedLabel\" | \"attachmentCategoryLabels\"\n >;\n};\n\nconst DEFAULT_FILE_CATEGORY_LABELS: Record<FileCategory, string> = {\n archive: \"Archive\",\n audio: \"Audio\",\n code: \"Code file\",\n data: \"Data file\",\n document: \"Document\",\n generic: \"File\",\n image: \"Image\",\n pdf: \"PDF document\",\n sheet: \"Spreadsheet\",\n video: \"Video\",\n};\n\nconst FILE_CATEGORY_ICONS: Record<FileCategory, typeof File> = {\n archive: FileArchive,\n audio: FileAudio2,\n code: FileCode2,\n data: FileJson2,\n document: FileText,\n generic: File,\n image: FileImage,\n pdf: FileText,\n sheet: FileSpreadsheet,\n video: FileVideo2,\n};\n\nfunction readFileCategoryLabel(\n category: FileCategory,\n texts?: ChatMessageFileProps[\"texts\"],\n): string {\n return (\n texts?.attachmentCategoryLabels?.[category] ??\n DEFAULT_FILE_CATEGORY_LABELS[category]\n );\n}\n\nfunction renderMetaLine(\n categoryLabel: string,\n sizeLabel: string | null,\n isUser: boolean,\n) {\n return (\n <div\n className={cn(\n \"mt-1 text-xs leading-5\",\n isUser ? \"text-white/70\" : \"text-slate-500\",\n )}\n >\n {sizeLabel ? `${categoryLabel} · ${sizeLabel}` : categoryLabel}\n </div>\n );\n}\n\nfunction renderActionPill(\n label: string,\n isUser: boolean,\n isInteractive: boolean,\n) {\n return (\n <span\n className={cn(\n \"inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium\",\n isInteractive\n ? isUser\n ? \"border-white/14 bg-white/12 text-white\"\n : \"border-slate-200/80 bg-white text-slate-700\"\n : isUser\n ? \"border-white/10 bg-white/6 text-white/62\"\n : \"border-slate-200/70 bg-slate-100/80 text-slate-500\",\n )}\n >\n {label}\n </span>\n );\n}\n\nfunction renderActionLink(\n label: string,\n href: string,\n isUser: boolean,\n) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n \"inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium transition duration-200\",\n isUser\n ? \"border-white/14 bg-white/12 text-white hover:border-white/20 hover:bg-white/16\"\n : \"border-slate-200/80 bg-white text-slate-700 hover:border-slate-300 hover:bg-slate-50\",\n )}\n >\n {label}\n </a>\n );\n}\n\nfunction FileCategoryGlyph({\n category,\n isUser,\n}: {\n category: FileCategory;\n isUser: boolean;\n}) {\n const Icon = FILE_CATEGORY_ICONS[category];\n\n return (\n <div\n className={cn(\n \"flex h-14 w-14 shrink-0 items-center justify-center rounded-[1rem] border\",\n isUser\n ? \"border-white/12 bg-white/10 text-white\"\n : FILE_CATEGORY_TILE_CLASSES[category],\n )}\n >\n <Icon\n className={cn(\n \"h-7 w-7\",\n isUser ? \"text-white/92\" : \"text-current\",\n )}\n strokeWidth={2.2}\n />\n </div>\n );\n}\n\nfunction renderImagePreview(params: {\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n}) {\n const { file, categoryLabel, sizeLabel, isUser } = params;\n if (!file.dataUrl) {\n return null;\n }\n return (\n <a\n href={file.dataUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"group block\"\n >\n <div\n className={cn(\n \"relative overflow-hidden rounded-[1rem]\",\n isUser\n ? \"ring-1 ring-white/10\"\n : \"bg-slate-100/80 ring-1 ring-slate-200/80\",\n )}\n >\n <img\n src={file.dataUrl}\n alt={file.label}\n className=\"block h-auto max-h-[26rem] w-full rounded-[1rem] bg-transparent object-contain transition duration-300 group-hover:scale-[1.01]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-3 flex items-center gap-2\">\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-1 text-[10px] font-semibold tracking-[0.18em] text-white backdrop-blur-sm\",\n isUser ? \"bg-slate-950/36\" : \"bg-slate-950/58\",\n )}\n >\n {categoryLabel}\n </span>\n {sizeLabel ? (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-1 text-[10px] font-medium text-white/92 backdrop-blur-sm\",\n isUser ? \"bg-slate-950/28\" : \"bg-slate-950/46\",\n )}\n >\n {sizeLabel}\n </span>\n ) : null}\n </div>\n </div>\n </a>\n );\n}\n\nfunction renderFileCardHeader(params: {\n category: FileCategory;\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n action: React.ReactNode;\n}) {\n const { category, file, categoryLabel, sizeLabel, isUser, action } = params;\n return (\n <div className=\"flex items-center gap-3 p-3.5\">\n <FileCategoryGlyph\n category={category}\n isUser={isUser}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[15px] font-semibold leading-5\">\n {file.label}\n </div>\n {renderMetaLine(categoryLabel, sizeLabel, isUser)}\n </div>\n {action}\n </div>\n </div>\n </div>\n );\n}\n\nfunction renderInlineMediaCard(params: {\n category: FileCategory;\n file: ChatMessageFileView;\n categoryLabel: string;\n sizeLabel: string | null;\n isUser: boolean;\n shellClasses: string;\n actionLabel: string;\n}) {\n const { category, file, categoryLabel, sizeLabel, isUser, shellClasses, actionLabel } = params;\n if (!file.dataUrl || (category !== \"audio\" && category !== \"video\")) {\n return null;\n }\n const mediaMimeType = resolveRenderableMimeType(file);\n return (\n <div className={shellClasses}>\n {renderFileCardHeader({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n action: renderActionLink(actionLabel, file.dataUrl, isUser),\n })}\n <div className=\"px-3.5 pb-3.5\">\n {category === \"audio\" ? (\n <audio\n controls\n preload=\"metadata\"\n aria-label={file.label}\n className=\"block w-full\"\n >\n <source\n src={file.dataUrl}\n {...(mediaMimeType ? { type: mediaMimeType } : {})}\n />\n </audio>\n ) : (\n <div\n className={cn(\n \"overflow-hidden rounded-[1rem] border\",\n isUser\n ? \"border-white/10 bg-slate-950/26\"\n : \"border-slate-200/80 bg-slate-100/80\",\n )}\n >\n <video\n controls\n preload=\"metadata\"\n playsInline\n aria-label={file.label}\n className=\"block max-h-[28rem] w-full bg-black\"\n >\n <source\n src={file.dataUrl}\n {...(mediaMimeType ? { type: mediaMimeType } : {})}\n />\n </video>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport function ChatMessageFile({\n file,\n isUser = false,\n texts,\n}: ChatMessageFileProps) {\n const { category, sizeLabel } = buildChatMessageFileMeta(file);\n const renderAsImage = isImageFileLike(file) && Boolean(file.dataUrl);\n const renderAsAudio = category === \"audio\" && Boolean(file.dataUrl);\n const renderAsVideo = category === \"video\" && Boolean(file.dataUrl);\n const isInteractive = Boolean(file.dataUrl);\n const actionLabel = isInteractive\n ? texts?.attachmentOpenLabel ?? \"Open\"\n : texts?.attachmentAttachedLabel ?? \"Attached\";\n const categoryLabel = readFileCategoryLabel(category, texts);\n const shellClasses = cn(\n \"block overflow-hidden rounded-[1.25rem] border transition duration-200\",\n isUser\n ? \"border-white/12 bg-white/10 text-white\"\n : \"border-slate-200/80 bg-white/95 text-slate-900\",\n isInteractive &&\n (isUser\n ? \"hover:border-white/18 hover:bg-white/13\"\n : \"hover:border-slate-300 hover:bg-white\"),\n );\n\n if (renderAsImage) {\n return renderImagePreview({ file, categoryLabel, sizeLabel, isUser });\n }\n\n if (renderAsAudio || renderAsVideo) {\n return renderInlineMediaCard({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n shellClasses,\n actionLabel,\n });\n }\n\n const content = renderFileCardHeader({\n category,\n file,\n categoryLabel,\n sizeLabel,\n isUser,\n action: renderActionPill(actionLabel, isUser, isInteractive),\n });\n\n if (!isInteractive || !file.dataUrl) {\n return <div className={shellClasses}>{content}</div>;\n }\n\n return (\n <a\n href={file.dataUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(shellClasses, \"group\")}\n >\n {content}\n </a>\n );\n}\n","import { useEffect, useRef, useState, type MouseEvent } from \"react\";\n\ntype UseReasoningBlockOpenStateParams = {\n isInProgress: boolean;\n};\n\ntype UseReasoningBlockOpenStateResult = {\n isOpen: boolean;\n onSummaryClick: (event: MouseEvent<HTMLElement>) => void;\n};\n\nexport function useReasoningBlockOpenState(\n params: UseReasoningBlockOpenStateParams,\n): UseReasoningBlockOpenStateResult {\n const { isInProgress } = params;\n const [isOpen, setIsOpen] = useState(isInProgress);\n const [keepOpenAfterCompletion, setKeepOpenAfterCompletion] = useState(false);\n const previousInProgressRef = useRef(isInProgress);\n\n useEffect(() => {\n const wasInProgress = previousInProgressRef.current;\n if (!wasInProgress && isInProgress) {\n setIsOpen(true);\n setKeepOpenAfterCompletion(false);\n } else if (wasInProgress && !isInProgress && !keepOpenAfterCompletion) {\n setIsOpen(false);\n }\n previousInProgressRef.current = isInProgress;\n }, [isInProgress, keepOpenAfterCompletion]);\n\n function onSummaryClick(event: MouseEvent<HTMLElement>) {\n event.preventDefault();\n const nextOpen = !isOpen;\n setIsOpen(nextOpen);\n\n if (!nextOpen) {\n setKeepOpenAfterCompletion(false);\n return;\n }\n\n if (isInProgress) {\n setKeepOpenAfterCompletion(true);\n }\n }\n\n return {\n isOpen,\n onSummaryClick,\n };\n}\n","import { useEffect, useLayoutEffect, useRef, type RefObject } from \"react\";\n\ntype UseStickyBottomScrollParams = {\n scrollRef: RefObject<HTMLElement>;\n resetKey: string | null;\n isLoading: boolean;\n hasContent: boolean;\n contentVersion: unknown;\n stickyThresholdPx?: number;\n};\n\ntype UseStickyBottomScrollResult = {\n onScroll: () => void;\n};\n\nconst DEFAULT_STICKY_THRESHOLD_PX = 10;\n\nfunction scrollElementToBottom(element: HTMLElement) {\n element.scrollTop = element.scrollHeight;\n}\n\nfunction queueScrollToBottom(params: {\n scrollRef: RefObject<HTMLElement>;\n scheduledScrollFrameRef: { current: number | null };\n isProgrammaticScrollRef: { current: boolean };\n}) {\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n if (params.scheduledScrollFrameRef.current !== null) {\n cancelAnimationFrame(params.scheduledScrollFrameRef.current);\n }\n\n params.scheduledScrollFrameRef.current = requestAnimationFrame(() => {\n params.scheduledScrollFrameRef.current = null;\n const currentElement = params.scrollRef.current;\n if (!currentElement) {\n return;\n }\n\n params.isProgrammaticScrollRef.current = true;\n scrollElementToBottom(currentElement);\n });\n}\n\nexport function useStickyBottomScroll(\n params: UseStickyBottomScrollParams,\n): UseStickyBottomScrollResult {\n const isStickyRef = useRef(true);\n const isProgrammaticScrollRef = useRef(false);\n const previousResetKeyRef = useRef<string | null>(null);\n const pendingInitialScrollRef = useRef(false);\n const scheduledScrollFrameRef = useRef<number | null>(null);\n\n const onScroll = () => {\n if (isProgrammaticScrollRef.current) {\n isProgrammaticScrollRef.current = false;\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n const distanceFromBottom =\n element.scrollHeight - element.scrollTop - element.clientHeight;\n isStickyRef.current =\n distanceFromBottom <=\n (params.stickyThresholdPx ?? DEFAULT_STICKY_THRESHOLD_PX);\n };\n\n useEffect(() => {\n if (previousResetKeyRef.current === params.resetKey) {\n return;\n }\n\n previousResetKeyRef.current = params.resetKey;\n isStickyRef.current = true;\n pendingInitialScrollRef.current = true;\n }, [params.resetKey]);\n\n useEffect(() => {\n const scheduledScrollFrame = scheduledScrollFrameRef.current;\n return () => {\n if (scheduledScrollFrame !== null) {\n cancelAnimationFrame(scheduledScrollFrame);\n }\n };\n }, []);\n\n useLayoutEffect(() => {\n if (\n !pendingInitialScrollRef.current ||\n params.isLoading ||\n !params.hasContent\n ) {\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n pendingInitialScrollRef.current = false;\n queueScrollToBottom({\n scrollRef: params.scrollRef,\n scheduledScrollFrameRef,\n isProgrammaticScrollRef,\n });\n }, [params.hasContent, params.isLoading, params.scrollRef]);\n\n useLayoutEffect(() => {\n if (!isStickyRef.current || !params.hasContent) {\n return;\n }\n\n const element = params.scrollRef.current;\n if (!element) {\n return;\n }\n\n queueScrollToBottom({\n scrollRef: params.scrollRef,\n scheduledScrollFrameRef,\n isProgrammaticScrollRef,\n });\n }, [params.contentVersion, params.hasContent, params.scrollRef]);\n\n return { onScroll };\n}\n","import { useRef } from \"react\";\nimport { useReasoningBlockOpenState } from \"../../hooks/use-reasoning-block-open-state\";\nimport { useStickyBottomScroll } from \"../../hooks/use-sticky-bottom-scroll\";\nimport { cn } from \"../../internal/cn\";\n\ntype ChatReasoningBlockProps = {\n label: string;\n text: string;\n isUser: boolean;\n isInProgress: boolean;\n};\n\nfunction normalizeReasoningLabel(label: string): string {\n const normalizedLabel = label.trim().toLowerCase();\n if (\n normalizedLabel === \"reasoning\" ||\n normalizedLabel === \"thinking\" ||\n normalizedLabel === \"推理\" ||\n normalizedLabel === \"推理过程\" ||\n normalizedLabel === \"思考过程\" ||\n normalizedLabel === \"思考\"\n ) {\n return \"思考\";\n }\n return label;\n}\n\nexport function ChatReasoningBlock({ label, text, isUser, isInProgress }: ChatReasoningBlockProps) {\n const { isOpen, onSummaryClick } = useReasoningBlockOpenState({\n isInProgress,\n });\n const scrollRef = useRef<HTMLDivElement>(null);\n const displayLabel = normalizeReasoningLabel(label);\n const { onScroll } = useStickyBottomScroll({\n scrollRef,\n resetKey: `${displayLabel}:${isInProgress ? \"streaming\" : \"idle\"}`,\n isLoading: false,\n hasContent: text.length > 0,\n contentVersion: text,\n stickyThresholdPx: 20,\n });\n\n return (\n <details className=\"mt-2\" open={isOpen}>\n <summary\n className={cn(\"cursor-pointer text-xs\", isUser ? \"text-primary-100\" : \"text-gray-500\")}\n onClick={onSummaryClick}\n >\n {displayLabel}\n </summary>\n <div\n ref={scrollRef}\n onScroll={onScroll}\n data-reasoning-scroll=\"true\"\n className={cn(\n \"mt-2 w-fit max-w-[500px] max-h-56 overflow-y-auto rounded-lg custom-scrollbar-amber\",\n isUser ? \"bg-primary-700/60\" : \"bg-gray-100\",\n )}\n >\n <pre className=\"min-w-0 whitespace-pre-wrap break-all p-2 text-[11px]\">{text}</pre>\n </div>\n </details>\n );\n}\n","import { cn } from '../../../internal/cn';\nimport type { ReactNode } from 'react';\n\nexport function ToolCardRoot({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <div \n className={cn(\n \"my-2 rounded-lg border border-amber-200/50 bg-amber-100/30 shadow-sm overflow-hidden text-[12px]\",\n \"w-[280px] sm:w-[360px] md:w-[480px] min-w-full max-w-full transition-all flex flex-col\",\n className\n )}\n >\n {children}\n </div>\n );\n}\n\nexport function ToolCardContent({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <div className={cn(\"border-t border-amber-200/15 bg-amber-50/50 px-3 pt-1 pb-2 w-full overflow-hidden\", className)}>\n {children}\n </div>\n );\n}\n","import { Check, Loader2, AlertTriangle, Minus } from 'lucide-react';\nimport { cn } from '../../../internal/cn';\nimport type { ChatToolPartViewModel } from '../../../view-models/chat-ui.types';\n\nexport const STATUS_STYLES = {\n running: { text: 'text-amber-500/80', icon: Loader2, spin: true },\n success: { text: 'text-amber-500/80', icon: Check, spin: false },\n error: { text: 'text-amber-500/80', icon: AlertTriangle, spin: false },\n cancelled: { text: 'text-amber-500/80', icon: Minus, spin: false }\n} as const;\n\nexport function ToolStatusLabel({ card }: { card: ChatToolPartViewModel }) {\n const style = STATUS_STYLES[card.statusTone] || STATUS_STYLES.cancelled;\n const Icon = style.icon;\n\n return (\n <span className={cn('inline-flex items-center gap-1.5 text-[11px] font-medium leading-none shrink-0', style.text)}>\n <Icon className={cn(\"h-3.5 w-3.5\", style.spin && \"animate-spin\")} strokeWidth={3} />\n {card.statusTone === 'running' ? card.statusLabel : null}\n </span>\n );\n}\n","import { ArrowUpRight, ChevronDown, ChevronRight, type LucideIcon } from 'lucide-react';\nimport type { MouseEvent, ReactNode } from 'react';\nimport { cn } from '../../../internal/cn';\nimport { ToolStatusLabel } from './tool-card-status';\nimport type {\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../../view-models/chat-ui.types';\n\nfunction ToolCardSessionActionButton({\n action,\n onAction,\n}: {\n action: ChatToolActionViewModel;\n onAction: (action: ChatToolActionViewModel) => void;\n}) {\n const isChildSession = action.sessionKind === 'child';\n const label = isChildSession ? 'Open child session' : 'Open session';\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onAction(action);\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.08em] transition-colors',\n 'border-amber-200/80 bg-white/80 text-amber-800 hover:bg-amber-50',\n )}\n aria-label={label}\n title={label}\n >\n <ArrowUpRight className=\"h-3 w-3\" strokeWidth={2.5} />\n </button>\n );\n}\n\nexport function ToolCardHeader({ \n card, \n icon: Icon, \n expanded, \n canExpand,\n hideSummary = false,\n actionSlot,\n onToggle \n}: { \n card: ChatToolPartViewModel; \n icon: LucideIcon; \n expanded: boolean; \n canExpand: boolean;\n hideSummary?: boolean;\n actionSlot?: ReactNode;\n onToggle: () => void; \n}) {\n const summaryPart = hideSummary\n ? ''\n : card.summary?.replace(/^(command|path|args|query|input):\\s*/i, '') ?? '';\n\n return (\n <div \n className={cn(\n \"flex items-center gap-3 px-3 py-2.5 transition-colors bg-transparent\", \n canExpand ? \"cursor-pointer hover:bg-amber-100/30\" : \"\"\n )}\n onClick={onToggle}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-2 overflow-hidden font-mono text-amber-950/80\">\n <Icon className=\"h-4 w-4 text-amber-600/80 shrink-0\" strokeWidth={3} />\n <div className=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden\">\n <span className=\"font-bold shrink-0 tracking-tight\">{card.toolName}</span>\n {summaryPart && (\n <>\n <span className=\"text-amber-300 font-bold select-none shrink-0\">›</span>\n <span className=\"block min-w-0 flex-1 truncate font-normal\" title={summaryPart}>\n {summaryPart}\n </span>\n </>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 shrink-0\">\n {actionSlot}\n <ToolStatusLabel card={card} />\n {canExpand && (\n expanded ? (\n <ChevronDown className=\"h-4 w-4 text-amber-400/80\" strokeWidth={3} />\n ) : (\n <ChevronRight className=\"h-4 w-4 text-amber-400/80\" strokeWidth={3} />\n )\n )}\n </div>\n </div>\n );\n}\n\nexport function ToolCardHeaderSessionAction({\n action,\n onAction,\n}: {\n action: ChatToolActionViewModel;\n onAction: (action: ChatToolActionViewModel) => void;\n}) {\n return <ToolCardSessionActionButton action={action} onAction={onAction} />;\n}\n","import type {\n ChatFileOperationBlockViewModel,\n ChatFileOperationLineViewModel,\n} from \"../../../view-models/chat-ui.types\";\nimport { cn } from \"../../../internal/cn\";\n\nconst FILE_TEXT_CLASS_NAME = \"font-mono text-[11px] leading-5\";\nconst FILE_ROW_CLASS_NAME = `flex h-5 w-full ${FILE_TEXT_CLASS_NAME}`;\nconst FILE_LINE_NUMBER_CELL_CLASS_NAME =\n \"flex h-5 items-center justify-center px-2.5 tabular-nums select-none\";\n\nfunction readVisibleLineNumber(line: ChatFileOperationLineViewModel): string {\n const value = line.newLineNumber ?? line.oldLineNumber;\n return typeof value === \"number\" ? String(value) : \"\";\n}\n\nfunction readLineKey(\n prefix: string,\n line: ChatFileOperationLineViewModel,\n index: number,\n): string {\n return `${prefix}-${index}-${line.oldLineNumber ?? \"x\"}-${line.newLineNumber ?? \"x\"}`;\n}\n\nfunction hasVisibleLineNumber(line: ChatFileOperationLineViewModel): boolean {\n return (\n typeof line.newLineNumber === \"number\" ||\n typeof line.oldLineNumber === \"number\"\n );\n}\n\nfunction readHasBlockLineNumbers(block: ChatFileOperationBlockViewModel): boolean {\n return block.lines.some(hasVisibleLineNumber);\n}\n\nfunction readLineNumberColumnWidth(\n block: ChatFileOperationBlockViewModel,\n): string {\n const maxDigits = block.lines.reduce((currentMax, line) => {\n if (!hasVisibleLineNumber(line)) {\n return currentMax;\n }\n return Math.max(currentMax, readVisibleLineNumber(line).length);\n }, 0);\n const width = Math.max(6.5, Math.min(8, maxDigits + 3.5));\n return `${width}ch`;\n}\n\nfunction readCodeColumnWidth(block: ChatFileOperationBlockViewModel): string {\n const maxColumns = block.lines.reduce(\n (currentMax, line) => Math.max(currentMax, Math.max(1, line.text.length)),\n 1,\n );\n return `calc(${maxColumns}ch + 1.25rem)`;\n}\n\nfunction getLineNumberTone(line: ChatFileOperationLineViewModel): string {\n if (line.kind === \"remove\") {\n return \"border-r border-rose-200 bg-rose-50 text-rose-700\";\n }\n if (line.kind === \"add\") {\n return \"border-r border-emerald-200 bg-emerald-50 text-emerald-700\";\n }\n return \"border-r border-stone-200 bg-stone-100 text-stone-500\";\n}\n\nfunction getCodeRowTone(line: ChatFileOperationLineViewModel): string {\n if (line.kind === \"remove\") {\n return \"bg-rose-50 text-rose-950\";\n }\n if (line.kind === \"add\") {\n return \"bg-emerald-50 text-emerald-950\";\n }\n return \"bg-white text-amber-950/80\";\n}\n\nfunction FileOperationLineNumberCell({\n layout,\n line,\n lineNumberColumnWidth,\n}: {\n layout: \"compact\" | \"workspace\";\n line: ChatFileOperationLineViewModel;\n lineNumberColumnWidth: string;\n}) {\n return (\n <span\n data-file-line-number-cell=\"true\"\n style={layout === \"compact\" ? { width: lineNumberColumnWidth, minWidth: lineNumberColumnWidth } : undefined}\n className={cn(\n FILE_LINE_NUMBER_CELL_CLASS_NAME,\n layout === \"compact\" ? \"sticky left-0 z-[1]\" : \"w-full shrink-0\",\n getLineNumberTone(line),\n )}\n >\n {readVisibleLineNumber(line)}\n </span>\n );\n}\n\nfunction FileOperationCodeCell({\n line,\n}: {\n line: ChatFileOperationLineViewModel;\n}) {\n return (\n <span\n data-file-code-row=\"true\"\n className={cn(\n \"block min-w-0 flex-1 whitespace-pre px-2.5\",\n getCodeRowTone(line),\n )}\n >\n {line.text || \" \"}\n </span>\n );\n}\n\nfunction FileOperationLineRow({\n line,\n showLineNumbers,\n lineNumberColumnWidth,\n}: {\n line: ChatFileOperationLineViewModel;\n showLineNumbers: boolean;\n lineNumberColumnWidth: string;\n}) {\n return (\n <div data-file-line-row=\"true\" className={FILE_ROW_CLASS_NAME}>\n {showLineNumbers ? (\n <FileOperationLineNumberCell\n layout=\"compact\"\n line={line}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ) : null}\n <FileOperationCodeCell line={line} />\n </div>\n );\n}\n\nfunction FileOperationWorkspaceSurface({\n block,\n}: {\n block: ChatFileOperationBlockViewModel;\n}) {\n const showLineNumbers = readHasBlockLineNumbers(block);\n const lineNumberColumnWidth = readLineNumberColumnWidth(block);\n const codeColumnWidth = readCodeColumnWidth(block);\n\n return (\n <div\n data-file-code-surface=\"true\"\n data-file-code-surface-layout=\"workspace\"\n className=\"flex h-full min-h-full min-w-full bg-white\"\n >\n {showLineNumbers ? (\n <div\n data-file-code-gutter=\"true\"\n style={{\n width: lineNumberColumnWidth,\n minWidth: lineNumberColumnWidth,\n }}\n className={cn(\n \"flex h-full min-h-full shrink-0 flex-col\",\n FILE_TEXT_CLASS_NAME,\n )}\n >\n {block.lines.map((line, index) => (\n <FileOperationLineNumberCell\n key={readLineKey(\"gutter\", line, index)}\n layout=\"workspace\"\n line={line}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ))}\n <div className=\"min-h-0 flex-1 border-r border-stone-200 bg-stone-100\" />\n </div>\n ) : null}\n\n <div\n data-file-code-canvas=\"true\"\n className=\"flex h-full min-h-full min-w-0 flex-1 flex-col bg-white\"\n >\n <div\n data-file-code-stack=\"true\"\n className=\"min-w-full\"\n style={{ minWidth: codeColumnWidth }}\n >\n {block.lines.map((line, index) => (\n <div\n key={readLineKey(\"code\", line, index)}\n data-file-code-canvas-row=\"true\"\n className={FILE_ROW_CLASS_NAME}\n >\n <FileOperationCodeCell line={line} />\n </div>\n ))}\n </div>\n <div className=\"min-h-0 flex-1 bg-white\" />\n </div>\n </div>\n );\n}\n\nexport function FileOperationCodeSurface({\n block,\n layout = \"compact\",\n}: {\n block: ChatFileOperationBlockViewModel;\n layout?: \"compact\" | \"workspace\";\n}) {\n if (layout === \"workspace\") {\n return <FileOperationWorkspaceSurface block={block} />;\n }\n\n const showLineNumbers = readHasBlockLineNumbers(block);\n const lineNumberColumnWidth = readLineNumberColumnWidth(block);\n const codeColumnWidth = readCodeColumnWidth(block);\n const surfaceMinWidth = showLineNumbers\n ? `calc(${lineNumberColumnWidth} + ${codeColumnWidth})`\n : codeColumnWidth;\n\n return (\n <div\n data-file-code-surface=\"true\"\n data-file-code-surface-layout=\"compact\"\n className=\"overflow-x-auto custom-scrollbar-amber bg-white\"\n >\n <div\n data-file-code-stack=\"true\"\n className=\"min-w-full\"\n style={{ minWidth: surfaceMinWidth }}\n >\n {block.lines.map((line, index) => (\n <FileOperationLineRow\n key={readLineKey(\"row\", line, index)}\n line={line}\n showLineNumbers={showLineNumbers}\n lineNumberColumnWidth={lineNumberColumnWidth}\n />\n ))}\n </div>\n </div>\n );\n}\n\nexport function FileOperationLinesGrid({\n block,\n}: {\n block: ChatFileOperationBlockViewModel;\n}) {\n return <FileOperationCodeSurface block={block} layout=\"compact\" />;\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatFileOperationBlockViewModel,\n ChatToolPartViewModel,\n} from \"../../../view-models/chat-ui.types\";\nimport { cn } from \"../../../internal/cn\";\nimport { useStickyBottomScroll } from \"../../../hooks/use-sticky-bottom-scroll\";\nimport { Fragment, type ReactNode, useRef } from \"react\";\nimport { ChatUiPrimitives } from \"../../primitives/chat-ui-primitives\";\nimport { FileOperationLinesGrid } from \"./tool-card-file-operation-lines\";\n\nfunction isPreviewBlock(block: ChatFileOperationBlockViewModel): boolean {\n return block.display === \"preview\";\n}\n\nfunction readFileOperationContentVersion(\n block: Pick<ChatFileOperationBlockViewModel, \"lines\" | \"rawText\">,\n): string {\n if (block.rawText) {\n return block.rawText;\n }\n return block.lines\n .map((line) =>\n [\n line.kind,\n line.oldLineNumber ?? \"\",\n line.newLineNumber ?? \"\",\n line.text,\n ].join(\":\"),\n )\n .join(\"\\n\");\n}\n\nfunction getCaptionTone(part: string): string {\n if (/^\\+\\d+$/.test(part)) {\n return \"text-emerald-700\";\n }\n if (/^-\\d+$/.test(part)) {\n return \"text-rose-700\";\n }\n return \"text-stone-500\";\n}\n\nfunction renderCaption(caption: string) {\n const parts = caption\n .split(\"·\")\n .map((part) => part.trim())\n .filter((part) => /^\\+\\d+$/.test(part) || /^-\\d+$/.test(part));\n if (parts.length === 0) {\n return null;\n }\n return (\n <div className=\"flex shrink-0 items-center gap-x-1 whitespace-nowrap text-[10px] font-medium uppercase tracking-[0.08em]\">\n {parts.map((part, index) => (\n <Fragment key={`${part}-${index}`}>\n {index > 0 ? <span className=\"text-stone-300\">·</span> : null}\n <span className={cn(getCaptionTone(part))}>{part}</span>\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction buildFileOpenAction(\n block: ChatFileOperationBlockViewModel,\n): ChatFileOpenActionViewModel {\n return {\n path: block.path,\n label: block.path.split(\"/\").filter(Boolean).pop() ?? block.path,\n viewMode: block.display === \"diff\" ? \"diff\" : \"preview\",\n ...(block.rawText ? { rawText: block.rawText } : {}),\n ...(block.beforeText ? { beforeText: block.beforeText } : {}),\n ...(block.afterText ? { afterText: block.afterText } : {}),\n ...(block.patchText ? { patchText: block.patchText } : {}),\n ...(typeof block.oldStartLine === \"number\"\n ? { oldStartLine: block.oldStartLine }\n : {}),\n ...(typeof block.newStartLine === \"number\"\n ? { newStartLine: block.newStartLine }\n : {}),\n fullLines: block.fullLines ?? block.lines,\n };\n}\n\nfunction StickyFileOperationScrollArea({\n children,\n contentVersion,\n resetKey,\n className,\n scrollKind,\n}: {\n children: ReactNode;\n contentVersion: unknown;\n resetKey: string;\n className?: string;\n scrollKind: \"block\" | \"raw\" | \"output\";\n}) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const { onScroll } = useStickyBottomScroll({\n scrollRef,\n resetKey,\n isLoading: false,\n hasContent: true,\n contentVersion,\n stickyThresholdPx: 20,\n });\n\n return (\n <div\n ref={scrollRef}\n onScroll={onScroll}\n data-file-scroll-kind={scrollKind}\n className={cn(\n \"overflow-y-auto bg-white custom-scrollbar-amber\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nfunction FileOperationBlock({\n block,\n showPathRow,\n isFirst,\n onFileOpen,\n}: {\n block: ChatFileOperationBlockViewModel;\n showPathRow: boolean;\n isFirst: boolean;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } =\n ChatUiPrimitives;\n const previewBlock = isPreviewBlock(block);\n const showMetaRow = showPathRow || Boolean(block.caption);\n\n const handlePathClick = () => {\n if (!onFileOpen) {\n return;\n }\n onFileOpen(buildFileOpenAction(block));\n };\n\n return (\n <section\n className={cn(\n \"overflow-hidden bg-white\",\n !isFirst && \"border-t border-stone-200/80\",\n )}\n >\n {showMetaRow ? (\n <div\n className={cn(\n \"flex items-center justify-between gap-4 border-b border-stone-200/80 px-4 text-stone-700\",\n showPathRow ? \"py-2\" : \"py-1.5\",\n )}\n >\n <div className=\"min-w-0 flex-1\">\n {showPathRow ? (\n <TooltipProvider delayDuration={250}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={handlePathClick}\n className={cn(\n \"w-full truncate whitespace-nowrap text-left font-mono text-[12px] font-medium text-stone-700\",\n onFileOpen &&\n \"transition-colors hover:text-amber-900 hover:underline\",\n )}\n title={block.path}\n >\n {block.path}\n </button>\n </TooltipTrigger>\n <TooltipContent\n side=\"top\"\n className=\"max-w-[420px] text-xs font-mono break-all\"\n >\n {block.path}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n ) : null}\n </div>\n {block.caption ? renderCaption(block.caption) : null}\n </div>\n ) : null}\n\n {block.lines.length > 0 ? (\n <StickyFileOperationScrollArea\n resetKey={`block:${block.key}`}\n contentVersion={readFileOperationContentVersion(block)}\n className=\"max-h-72\"\n scrollKind=\"block\"\n >\n <FileOperationLinesGrid block={block} />\n </StickyFileOperationScrollArea>\n ) : block.rawText ? (\n <StickyFileOperationScrollArea\n resetKey={`raw:${block.key}`}\n contentVersion={block.rawText}\n className=\"max-h-72\"\n scrollKind=\"raw\"\n >\n <div className=\"overflow-x-auto custom-scrollbar-amber\">\n <pre className=\"min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80\">\n {block.rawText}\n </pre>\n </div>\n </StickyFileOperationScrollArea>\n ) : null}\n\n {block.truncated && !previewBlock ? (\n <div className=\"border-t border-stone-200/85 bg-stone-50 px-4 py-2 text-[10px] text-stone-500\">\n Showing a shortened diff preview.\n </div>\n ) : null}\n </section>\n );\n}\n\nexport function ToolCardFileOperationContent({\n card,\n className,\n onFileOpen,\n}: {\n card: ChatToolPartViewModel;\n className?: string;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const blocks = card.fileOperation?.blocks ?? [];\n const output = card.output?.trim() ?? \"\";\n if (blocks.length === 0 && !output) {\n return null;\n }\n\n return (\n <div className={cn(\"overflow-hidden bg-white\", className)}>\n {blocks.map((block, index) => {\n return (\n <FileOperationBlock\n key={block.key}\n block={block}\n showPathRow={true}\n isFirst={index === 0}\n onFileOpen={onFileOpen}\n />\n );\n })}\n\n {output ? (\n <StickyFileOperationScrollArea\n resetKey={`output:${card.toolName}:${card.summary ?? \"none\"}`}\n contentVersion={output}\n className={cn(\n \"max-h-56\",\n blocks.length > 0 && \"border-t border-stone-200/80\",\n )}\n scrollKind=\"output\"\n >\n <div className=\"overflow-x-auto custom-scrollbar-amber\">\n <pre className=\"min-w-max whitespace-pre bg-white px-4 py-2 font-mono text-[11px] leading-5 text-amber-950/80\">\n {output}\n </pre>\n </div>\n </StickyFileOperationScrollArea>\n ) : null}\n </div>\n );\n}\n","import { Terminal, FileText, Code2, Search, Globe } from 'lucide-react';\nimport { useState, useEffect, useRef, type ReactNode } from 'react';\nimport type {\n ChatFileOpenActionViewModel,\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../../view-models/chat-ui.types';\nimport { ToolCardRoot, ToolCardContent } from './tool-card-root';\nimport { ToolCardHeader, ToolCardHeaderSessionAction } from './tool-card-header';\nimport { ToolCardFileOperationContent } from './tool-card-file-operation';\nimport { cn } from '../../../internal/cn';\n\nconst TOOL_CARD_AUTO_EXPAND_DELAY_MS = 200;\nconst ANSI_ESCAPE_PREFIX = String.fromCharCode(27);\nconst ANSI_ESCAPE_PATTERN = new RegExp(`${ANSI_ESCAPE_PREFIX}\\\\[[0-?]*[ -/]*[@-~]`, 'g');\n\nfunction readNonEmptyString(value: unknown): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n return value.length > 0 ? value : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction stripAnsi(value: string): string {\n return value.replace(ANSI_ESCAPE_PATTERN, '');\n}\n\nfunction isStructuredTerminalRecord(record: Record<string, unknown>): boolean {\n return (\n 'command' in record ||\n 'workingDir' in record ||\n 'exitCode' in record ||\n 'durationMs' in record ||\n 'stdout' in record ||\n 'stderr' in record ||\n 'aggregated_output' in record ||\n 'combinedOutput' in record\n );\n}\n\nfunction extractTerminalOutputFromRecord(record: Record<string, unknown>): string | null {\n const aggregatedOutput =\n readNonEmptyString(record.aggregated_output) ??\n readNonEmptyString(record.combinedOutput) ??\n readNonEmptyString(record.output);\n if (aggregatedOutput) {\n return aggregatedOutput;\n }\n\n const stdout = readNonEmptyString(record.stdout);\n const stderr = readNonEmptyString(record.stderr);\n if (!stdout && !stderr) {\n return null;\n }\n return [stdout, stderr].filter((value): value is string => Boolean(value)).join('\\n');\n}\n\nfunction normalizeTerminalOutput(rawOutput?: string, structuredOutput?: unknown): string {\n if (isRecord(structuredOutput)) {\n const terminalOutput = extractTerminalOutputFromRecord(structuredOutput);\n if (terminalOutput) {\n return stripAnsi(terminalOutput);\n }\n if (isStructuredTerminalRecord(structuredOutput)) {\n return '';\n }\n }\n if (!rawOutput) {\n return '';\n }\n const trimmed = rawOutput.trim();\n if (!trimmed.startsWith('{')) {\n return stripAnsi(rawOutput);\n }\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!isRecord(parsed)) {\n return stripAnsi(rawOutput);\n }\n const terminalOutput = extractTerminalOutputFromRecord(parsed);\n if (terminalOutput) {\n return stripAnsi(terminalOutput);\n }\n if (isStructuredTerminalRecord(parsed)) {\n return '';\n }\n return stripAnsi(rawOutput);\n } catch {\n return stripAnsi(rawOutput);\n }\n}\n\nfunction shouldAutoExpandRunningFileOperation(toolName: string): boolean {\n return toolName === 'write_file' || toolName === 'edit_file';\n}\n\nfunction useToolCardExpandedState({\n canExpand,\n isRunning,\n autoExpandWhileRunning = true,\n expandOnError = false,\n statusTone,\n}: {\n canExpand: boolean;\n isRunning: boolean;\n autoExpandWhileRunning?: boolean;\n expandOnError?: boolean;\n statusTone: ChatToolPartViewModel['statusTone'];\n}) {\n const [expanded, setExpanded] = useState(false);\n const [hasUserToggled, setHasUserToggled] = useState(false);\n const expandTimerRef = useRef<number | null>(null);\n const prevRunningRef = useRef(isRunning);\n const isFirstRenderRef = useRef(true);\n\n useEffect(() => {\n return () => {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n }\n };\n }, []);\n\n useEffect(() => {\n if (expandOnError && statusTone === 'error' && canExpand && !hasUserToggled) {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n setExpanded(true);\n prevRunningRef.current = isRunning;\n isFirstRenderRef.current = false;\n return;\n }\n\n if (\n autoExpandWhileRunning &&\n isRunning &&\n canExpand &&\n !hasUserToggled &&\n !expanded &&\n (isFirstRenderRef.current || !prevRunningRef.current)\n ) {\n expandTimerRef.current = window.setTimeout(() => {\n setExpanded(true);\n expandTimerRef.current = null;\n }, TOOL_CARD_AUTO_EXPAND_DELAY_MS);\n }\n\n if (!isRunning) {\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n if (prevRunningRef.current && !hasUserToggled) {\n setExpanded(false);\n }\n }\n\n prevRunningRef.current = isRunning;\n isFirstRenderRef.current = false;\n }, [autoExpandWhileRunning, canExpand, expandOnError, expanded, hasUserToggled, isRunning, statusTone]);\n\n const onToggle = () => {\n if (!canExpand) {\n return;\n }\n if (expandTimerRef.current !== null) {\n window.clearTimeout(expandTimerRef.current);\n expandTimerRef.current = null;\n }\n setExpanded((current) => !current);\n setHasUserToggled(true);\n };\n\n return { expanded, onToggle };\n}\n\nfunction GenericToolSection({\n label,\n tone,\n children,\n}: {\n label: string;\n tone: 'input' | 'output' | 'error';\n children: ReactNode;\n}) {\n const tones = {\n input: {\n shell: 'border-stone-200/80 bg-stone-50/90',\n header: 'border-stone-200/80 bg-stone-100/85 text-stone-500',\n dot: 'bg-stone-400/80',\n body: 'text-stone-700',\n },\n output: {\n shell: 'border-amber-200/70 bg-white/90',\n header: 'border-amber-200/70 bg-amber-50/90 text-amber-700',\n dot: 'bg-amber-500/80',\n body: 'text-amber-950/80',\n },\n error: {\n shell: 'border-rose-200/80 bg-rose-50/85',\n header: 'border-rose-200/80 bg-rose-100/80 text-rose-700',\n dot: 'bg-rose-500/80',\n body: 'text-rose-950/85',\n },\n } as const;\n const style = tones[tone];\n\n return (\n <section\n className={cn(\n 'overflow-hidden rounded-md border shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]',\n style.shell,\n )}\n >\n <div\n className={cn(\n 'flex items-center gap-2 border-b px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.16em]',\n style.header,\n )}\n >\n <span className={cn('h-1.5 w-1.5 rounded-full', style.dot)} />\n <span>{label}</span>\n </div>\n <div className=\"w-full overflow-hidden\">\n <pre\n className={cn(\n 'w-full max-w-full min-w-0 max-h-64 overflow-x-auto overflow-y-auto px-3 py-2.5 font-mono text-[12px] leading-relaxed whitespace-pre custom-scrollbar-amber',\n style.body,\n )}\n >\n {children}\n </pre>\n </div>\n </section>\n );\n}\n\n// -------------------------------------------------------------\n// 1. Terminal View\n// -------------------------------------------------------------\nexport function TerminalExecutionView({ card }: { card: ChatToolPartViewModel }) {\n const output = normalizeTerminalOutput(card.output, card.outputData);\n const isRunning = card.statusTone === 'running';\n const hasContent = !!(card.summary?.trim() || output.trim().length > 0);\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: output.trim().length > 0 || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n expandOnError: hasContent,\n statusTone: card.statusTone,\n });\n\n const commandPart = card.summary?.replace(/^(command|path|args|query|input):\\s*/i, '');\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Terminal} \n expanded={expanded} \n canExpand={output.trim().length > 0 || isRunning} \n onToggle={onToggle} \n />\n {expanded && (\n <>\n <div className=\"px-3 pb-2 font-mono w-full max-h-48 overflow-y-auto custom-scrollbar-amber min-h-0 text-[12px]\">\n <div className=\"flex items-start gap-2 leading-relaxed\">\n <span className=\"text-amber-500/50 font-medium shrink-0 select-none mt-[1px]\">$</span>\n <div className=\"flex-1 min-w-0\">\n {commandPart ? (\n <div className=\"text-amber-950/80 break-words whitespace-pre-wrap tracking-tight font-medium inline-block\">\n {commandPart}\n {isRunning && !output && (\n <span className=\"inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle\" />\n )}\n </div>\n ) : (\n <div className=\"h-3 w-32 bg-amber-200/30 rounded animate-pulse mt-2\" />\n )}\n </div>\n </div>\n </div>\n {output && (\n <ToolCardContent>\n <pre className=\"font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber leading-relaxed px-0\">\n {output}\n {isRunning && <span className=\"inline-block w-1.5 h-3 ml-1 bg-amber-500/60 animate-pulse align-middle\" />}\n </pre>\n </ToolCardContent>\n )}\n </>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 2. File Operation View\n// -------------------------------------------------------------\nexport function FileOperationView({\n card,\n onFileOpen,\n}: {\n card: ChatToolPartViewModel;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n}) {\n const output = card.output?.trim() ?? '';\n const isRunning = card.statusTone === 'running';\n const hasStructuredPreview = Boolean(card.fileOperation?.blocks.length);\n const hasContent = hasStructuredPreview || Boolean(output);\n const previewBlocks = card.fileOperation?.blocks ?? [];\n const previewLineCount = previewBlocks.reduce((count, block) => count + block.lines.length, 0);\n const previewCharCount = previewBlocks.reduce((count, block) => {\n if (block.rawText) {\n return count + block.rawText.length;\n }\n return count + block.lines.reduce((lineCount, line) => lineCount + line.text.length + 1, 0);\n }, 0);\n const shouldAutoExpandWhileRunning =\n shouldAutoExpandRunningFileOperation(card.toolName) &&\n !(\n isRunning &&\n card.toolName === 'write_file' &&\n (previewLineCount > 24 || previewCharCount > 1_200)\n );\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: hasContent || isRunning,\n isRunning,\n autoExpandWhileRunning: shouldAutoExpandWhileRunning,\n expandOnError: hasContent,\n statusTone: card.statusTone,\n });\n\n const isEdit = card.toolName === 'edit_file' || card.toolName === 'write_file' || card.toolName === 'apply_patch' || card.toolName === 'file_change';\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={isEdit ? Code2 : FileText} \n expanded={expanded} \n canExpand={hasContent || isRunning} \n hideSummary={expanded && hasStructuredPreview}\n onToggle={onToggle} \n />\n {expanded && hasContent && (\n <ToolCardContent className=\"border-t border-amber-200/20 bg-transparent px-0 pt-0 pb-0\">\n <ToolCardFileOperationContent card={card} onFileOpen={onFileOpen} />\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 3. Search View\n// -------------------------------------------------------------\nexport function SearchSnippetView({ card }: { card: ChatToolPartViewModel }) {\n const isRunning = card.statusTone === 'running';\n const output = card.output?.trim() ?? '';\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: !!output || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n statusTone: card.statusTone,\n });\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Search} \n expanded={expanded} \n canExpand={!!output || isRunning} \n onToggle={onToggle} \n />\n {expanded && output && (\n <ToolCardContent>\n <pre className=\"font-mono text-[12px] text-amber-950/70 whitespace-pre-wrap break-all w-full max-w-full max-h-64 overflow-y-auto overflow-x-hidden min-w-0 custom-scrollbar-amber leading-relaxed\">\n {output}\n </pre>\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n\n// -------------------------------------------------------------\n// 4. Generic View\n// -------------------------------------------------------------\nexport function GenericToolCard({\n card,\n onToolAction,\n renderToolAgent,\n}: {\n card: ChatToolPartViewModel;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n}) {\n const input = card.input?.trim() ?? '';\n const output = card.output?.trim() ?? '';\n const isRunning = card.statusTone === 'running';\n const hasInputSection = input.length > 0;\n const hasOutputSection = output.length > 0;\n const hasContent = hasInputSection || hasOutputSection;\n const inputLabel = card.inputLabel?.trim() || 'Input';\n const outputLabel = card.outputLabel?.trim() || 'Output';\n const { expanded, onToggle } = useToolCardExpandedState({\n canExpand: hasContent || isRunning,\n isRunning,\n autoExpandWhileRunning: false,\n statusTone: card.statusTone,\n });\n\n return (\n <ToolCardRoot>\n <ToolCardHeader \n card={card} \n icon={Globe} \n expanded={expanded} \n canExpand={hasContent || isRunning} \n actionSlot={\n card.agentId || (card.action && onToolAction) ? (\n <>\n {card.agentId && renderToolAgent ? renderToolAgent(card.agentId) : null}\n {card.action && onToolAction ? (\n <ToolCardHeaderSessionAction\n action={card.action}\n onAction={onToolAction}\n />\n ) : null}\n </>\n ) : undefined\n }\n onToggle={onToggle} \n />\n {expanded && hasContent && (\n <ToolCardContent className=\"bg-transparent px-2.5 py-2.5\">\n {hasInputSection && (\n <GenericToolSection label={inputLabel} tone=\"input\">\n {input}\n </GenericToolSection>\n )}\n {hasInputSection && hasOutputSection && (\n <div className=\"h-2\" />\n )}\n {hasOutputSection && (\n <GenericToolSection\n label={outputLabel}\n tone={card.statusTone === 'error' ? 'error' : 'output'}\n >\n {output}\n </GenericToolSection>\n )}\n </ToolCardContent>\n )}\n </ToolCardRoot>\n );\n}\n","import type {\n ChatFileOpenActionViewModel,\n ChatToolActionViewModel,\n ChatToolPartViewModel,\n} from '../../view-models/chat-ui.types';\nimport type { ReactNode } from 'react';\nimport { TerminalExecutionView, FileOperationView, SearchSnippetView, GenericToolCard } from './chat-tool-specialized';\n\nfunction isTerminalTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'exec' || lowered === 'exec_command' || lowered === 'execute_command' || lowered === 'command_execution' || lowered === 'bash' || lowered === 'shell' || lowered.includes('run_');\n}\n\nfunction isFileEditTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'read_file' || lowered === 'write_file' || lowered === 'edit_file' || lowered === 'apply_patch' || lowered === 'file_change';\n}\n\nfunction isSearchTool(name: string) {\n const lowered = name.toLowerCase();\n return lowered === 'grep_search' || lowered === 'find_files' || lowered.includes('search');\n}\n\nexport function ChatToolCard({\n card,\n onToolAction,\n onFileOpen,\n renderToolAgent,\n}: {\n card: ChatToolPartViewModel;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n}) {\n if (isTerminalTool(card.toolName)) {\n return <TerminalExecutionView card={card} />;\n }\n if (isFileEditTool(card.toolName)) {\n return <FileOperationView card={card} onFileOpen={onFileOpen} />;\n }\n if (isSearchTool(card.toolName)) {\n return <SearchSnippetView card={card} />;\n }\n\n // Fallback minimalist card for read_url_content, multi_replace, etc.\n return (\n <GenericToolCard\n card={card}\n onToolAction={onToolAction}\n renderToolAgent={renderToolAgent}\n />\n );\n}\n","type ChatUnknownPartProps = {\n label: string;\n rawType: string;\n text?: string;\n};\n\nexport function ChatUnknownPart(props: ChatUnknownPartProps) {\n return (\n <div className=\"rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-2 text-xs text-gray-600\">\n <div className=\"font-semibold text-gray-700\">\n {props.label}: {props.rawType}\n </div>\n {props.text ? <pre className=\"mt-1 whitespace-pre-wrap break-words text-[11px] text-gray-500\">{props.text}</pre> : null}\n </div>\n );\n}\n","import { memo, type ReactNode } from \"react\";\nimport type {\n ChatFileOpenActionViewModel,\n ChatMessageTexts,\n ChatToolActionViewModel,\n ChatMessageViewModel,\n} from \"../../view-models/chat-ui.types\";\nimport { cn } from \"../../internal/cn\";\nimport { ChatMessageMarkdown } from \"./chat-message-markdown\";\nimport { ChatMessageInlineContent } from \"./chat-message-inline-content\";\nimport { ChatMessageFile } from \"./chat-message-file\";\nimport { ChatReasoningBlock } from \"./chat-reasoning-block\";\nimport { ChatToolCard } from \"./chat-tool-card\";\nimport { ChatUnknownPart } from \"./chat-unknown-part\";\n\ntype ChatMessageProps = {\n message: ChatMessageViewModel;\n texts: Pick<\n ChatMessageTexts,\n | \"copyCodeLabel\"\n | \"copiedCodeLabel\"\n | \"attachmentOpenLabel\"\n | \"attachmentAttachedLabel\"\n | \"attachmentCategoryLabels\"\n >;\n onToolAction?: (action: ChatToolActionViewModel) => void;\n onFileOpen?: (action: ChatFileOpenActionViewModel) => void;\n renderToolAgent?: (agentId: string) => ReactNode;\n};\n\nexport const ChatMessage = memo(function ChatMessage(props: ChatMessageProps) {\n const { message, texts, onToolAction, onFileOpen, renderToolAgent } = props;\n const { role } = message;\n const isUser = role === \"user\";\n const isMessageInProgress =\n message.status === \"pending\" || message.status === \"streaming\";\n\n return (\n <div\n className={cn(\n \"inline-block w-fit max-w-full rounded-2xl border px-4 shadow-sm\",\n isUser\n ? \"border-primary bg-primary py-3 text-white\"\n : role === \"assistant\"\n ? \"border-gray-200 bg-white pb-3 pt-4 text-gray-900\"\n : \"border-orange-200/80 bg-orange-50/70 py-3 text-gray-900\",\n )}\n >\n <div className=\"space-y-2\">\n {message.parts.map((part, index) => {\n const { type } = part;\n\n if (type === \"markdown\") {\n return (\n <ChatMessageMarkdown\n key={`markdown-${index}`}\n text={part.text}\n role={role}\n texts={texts}\n onFileOpen={onFileOpen}\n />\n );\n }\n if (type === \"inline-content\") {\n return (\n <ChatMessageInlineContent\n key={`inline-content-${index}`}\n segments={part.segments}\n role={role}\n texts={texts}\n onFileOpen={onFileOpen}\n />\n );\n }\n if (type === \"reasoning\") {\n return (\n <ChatReasoningBlock\n key={`reasoning-${index}`}\n label={part.label}\n text={part.text}\n isUser={isUser}\n isInProgress={\n isMessageInProgress && index === message.parts.length - 1\n }\n />\n );\n }\n if (type === \"tool-card\") {\n return (\n <div key={`tool-${index}`} className=\"mt-0.5\">\n <ChatToolCard\n card={part.card}\n onToolAction={onToolAction}\n onFileOpen={onFileOpen}\n renderToolAgent={renderToolAgent}\n />\n </div>\n );\n }\n if (type === \"file\") {\n return (\n <ChatMessageFile\n key={`file-${index}`}\n file={part.file}\n isUser={isUser}\n texts={texts}\n />\n );\n }\n if (type === \"unknown\") {\n return (\n <ChatUnknownPart\n key={`unknown-${index}`}\n label={part.label}\n rawType={part.rawType}\n text={part.text}\n />\n );\n }\n return null;\n })}\n </div>\n </div>\n );\n});\n","import { cn } from '../../internal/cn';\n\ntype ChatMessageMetaProps = {\n roleLabel: string;\n timestampLabel: string;\n isUser: boolean;\n};\n\nexport function ChatMessageMeta(props: ChatMessageMetaProps) {\n return (\n <div\n className={cn(\n 'px-1 text-[11px] leading-4 text-gray-400',\n props.isUser ? 'text-right' : 'text-left'\n )}\n >\n {props.roleLabel} · {props.timestampLabel}\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport { useCopyFeedback } from '../../hooks/use-copy-feedback';\nimport { Check, Copy } from 'lucide-react';\nimport type { ChatMessageViewModel, ChatMessageTexts } from '../../view-models/chat-ui.types';\n\nexport function ChatMessageActionCopy({\n message,\n texts,\n}: {\n message: ChatMessageViewModel;\n texts: Pick<ChatMessageTexts, 'copyMessageLabel' | 'copiedMessageLabel'>;\n}) {\n const messageText = useMemo(() => {\n return message.parts\n .map((part) => {\n if (part.type === 'markdown') return part.text;\n if (part.type === 'unknown') return part.text;\n return '';\n })\n .filter((text) => !!text && text.trim().length > 0)\n .join('\\n\\n');\n }, [message.parts]);\n\n const { copied, copy } = useCopyFeedback({ text: messageText });\n\n if (!messageText) return null;\n\n return (\n <button\n type=\"button\"\n onClick={() => void copy()}\n className=\"text-gray-400 hover:text-gray-600 transition-colors p-1 rounded-md hover:bg-gray-100 flex items-center justify-center\"\n aria-label={copied ? texts.copiedMessageLabel : texts.copyMessageLabel}\n title={copied ? texts.copiedMessageLabel : texts.copyMessageLabel}\n >\n {copied ? <Check className=\"h-3.5 w-3.5\" /> : <Copy className=\"h-3.5 w-3.5\" />}\n </button>\n );\n}\n","import type { ChatMessageListProps } from '@agent-chat-ui/components/chat/view-models/chat-ui.types';\nimport { cn } from '@agent-chat-ui/components/chat/internal/cn';\nimport { ChatMessageAvatar } from './chat-message-avatar';\nimport { ChatMessage } from './chat-message';\nimport { ChatMessageMeta } from './chat-message-meta';\nimport { ChatMessageActionCopy } from './chat-message-action-copy';\n\nconst INVISIBLE_ONLY_TEXT_PATTERN = /\\u200B|\\u200C|\\u200D|\\u2060|\\uFEFF/g;\nconst TYPING_TEXT_SHEEN_CSS = `\n@keyframes nextclaw-chat-typing-text-sheen {\n 0% {\n background-position: 160% 0;\n }\n 100% {\n background-position: -60% 0;\n }\n}\n\n.nextclaw-chat-typing-indicator__text {\n background-image: linear-gradient(\n 100deg,\n #6b7280 0%,\n #6b7280 34%,\n #a6adba 43%,\n #f8fafc 50%,\n #a6adba 57%,\n #6b7280 66%,\n #6b7280 100%\n );\n background-size: 240% 100%;\n background-position: 160% 0;\n -webkit-background-clip: text;\n background-clip: text;\n color: transparent;\n -webkit-text-fill-color: transparent;\n animation: nextclaw-chat-typing-text-sheen 2.5s linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .nextclaw-chat-typing-indicator__text {\n animation: none;\n background-image: none;\n color: #6b7280;\n -webkit-text-fill-color: currentColor;\n }\n}\n`;\n\nfunction hasRenderableText(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed) {\n return false;\n }\n return trimmed.replace(INVISIBLE_ONLY_TEXT_PATTERN, '').trim().length > 0;\n}\n\nfunction hasRenderableMessageContent(message: ChatMessageListProps['messages'][number]): boolean {\n return message.parts.some((part) => {\n if (part.type === 'markdown' || part.type === 'reasoning') {\n return hasRenderableText(part.text);\n }\n return true;\n });\n}\n\nfunction ChatMessageTypingFooter() {\n return (\n <div className=\"flex items-center gap-2 px-1 py-0.5 text-[11px] text-gray-400\">\n <div className=\"flex space-x-1 items-center h-full\">\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse\"></div>\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:200ms]\"></div>\n <div className=\"h-1.5 w-1.5 rounded-full bg-gray-400 animate-pulse [animation-delay:400ms]\"></div>\n </div>\n </div>\n );\n}\n\nfunction ChatTypingIndicator({ label }: { label: string }) {\n return (\n <div className=\"rounded-2xl border border-gray-200 bg-white px-4 py-3 text-sm text-gray-500 shadow-sm\">\n <style>{TYPING_TEXT_SHEEN_CSS}</style>\n <span className=\"nextclaw-chat-typing-indicator__text\">{label}</span>\n </div>\n );\n}\n\nexport function ChatMessageList(props: ChatMessageListProps) {\n const visibleMessages = props.messages.filter(hasRenderableMessageContent);\n const hasRenderableAssistantDraft = visibleMessages.some(\n (message) =>\n message.role === 'assistant' &&\n (message.status === 'streaming' || message.status === 'pending')\n );\n\n return (\n <div className={cn('space-y-5', props.className)}>\n {visibleMessages.map((message) => {\n const isUser = message.role === 'user';\n const isGenerating = !isUser && (message.status === 'streaming' || message.status === 'pending');\n\n return (\n <div key={message.id} className={cn('flex gap-3', isUser ? 'justify-end' : 'justify-start')}>\n {!isUser ? <ChatMessageAvatar role={message.role} /> : null}\n <div className={cn('w-fit max-w-[92%] space-y-2', isUser && 'flex flex-col items-end')}>\n <ChatMessage\n message={message}\n texts={props.texts}\n onToolAction={props.onToolAction}\n onFileOpen={props.onFileOpen}\n renderToolAgent={props.renderToolAgent}\n />\n <div className={cn('flex items-center gap-2', isUser && 'justify-end')}>\n {isGenerating ? (\n <ChatMessageTypingFooter />\n ) : (\n <>\n <ChatMessageMeta roleLabel={message.roleLabel} timestampLabel={message.timestampLabel} isUser={isUser} />\n {!isUser ? <ChatMessageActionCopy message={message} texts={props.texts} /> : null}\n </>\n )}\n </div>\n </div>\n {isUser ? <ChatMessageAvatar role={message.role} /> : null}\n </div>\n );\n })}\n\n {props.isSending && !hasRenderableAssistantDraft ? (\n <div className=\"flex justify-start gap-3\">\n <ChatMessageAvatar role=\"assistant\" />\n <ChatTypingIndicator label={props.texts.typingLabel} />\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
|