{"version":3,"file":"index.umd.cjs","sources":["../src/lib/utils.ts","../src/lib/ChatComponents/button.tsx","../src/lib/ChatComponents/avatar.tsx","../src/lib/ChatComponents/message-loading.tsx","../src/lib/ChatComponents/chat-bubble.tsx","../src/lib/ChatComponents/textarea.tsx","../src/lib/ChatComponents/chat-input.tsx","../src/lib/ChatComponents/hooks/useAutoScroll.tsx","../src/lib/ChatComponents/chat-message-list.tsx","../src/lib/ChatComponents/expandable-chat.tsx","../src/lib/ChatComponents/progress.tsx","../src/lib/LocalChat/LocalChat.tsx"],"sourcesContent":["/// <reference types=\"@webgpu/types\" />\n\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n    return twMerge(clsx(inputs));\n}\n\nexport async function detectWebGPU() {\n    try {\n        const adapter = await navigator.gpu.requestAdapter();\n        return !!adapter;\n    } catch {\n        return false;\n    }\n}\n","import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n    \"bb:inline-flex bb:items-center bb:justify-center bb:gap-2 bb:whitespace-nowrap bb:rounded-md bb:text-sm bb:font-medium bb:ring-offset-background bb:transition-colors focus-visible:bb:outline-none focus-visible:bb:ring-2 focus-visible:bb:ring-ring focus-visible:bb:ring-offset-2 disabled:bb:pointer-events-none disabled:bb:opacity-50 [&_svg]:bb:pointer-events-none [&_svg]:bb:size-4 [&_svg]:bb:shrink-0\",\n    {\n        variants: {\n            variant: {\n                default: \"bb:bg-primary bb:text-primary-foreground hover:bb:bg-primary/90\",\n                destructive: \"bb:bg-destructive bb:text-destructive-foreground hover:bb:bg-destructive/90\",\n                outline:\n                    \"bb:border bb:border-input bb:bg-background hover:bb:bg-accent hover:bb:text-accent-foreground\",\n                secondary: \"bb:bg-secondary bb:text-secondary-foreground hover:bb:bg-secondary/80\",\n                ghost: \"hover:bb:bg-accent hover:bb:text-accent-foreground\",\n                link: \"bb:text-primary bb:underline-offset-4 hover:bb:underline\",\n            },\n            size: {\n                default: \"bb:h-10 bb:px-4 bb:py-2\",\n                sm: \"bb:h-9 bb:rounded-md bb:px-3\",\n                lg: \"bb:h-11 bb:rounded-md bb:px-8\",\n                icon: \"bb:h-10 bb:w-10\",\n            },\n        },\n        defaultVariants: {\n            variant: \"default\",\n            size: \"default\",\n        },\n    },\n);\n\nexport type ButtonProps = {\n  asChild?: boolean;\n} & React.ButtonHTMLAttributes<HTMLButtonElement> &\n  VariantProps<typeof buttonVariants>;\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, ...props }, ref) => {\n    const Comp = asChild ? Slot : 'button';\n    return (\n      <Comp\n        className={cn(buttonVariants({ variant, size, className }))}\n        ref={ref}\n        {...props}\n      />\n    );\n  }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","'use client';\n\nimport * as React from 'react';\nimport * as AvatarPrimitive from '@radix-ui/react-avatar';\n\nimport { cn } from '@/lib/utils';\n\nconst Avatar = React.forwardRef<\n    React.ElementRef<typeof AvatarPrimitive.Root>,\n    React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n    <AvatarPrimitive.Root\n        ref={ref}\n        className={cn(\"bb:relative bb:flex bb:h-10 bb:w-10 bb:shrink-0 bb:overflow-hidden bb:rounded-full\", className)}\n        {...props}\n    />\n));\nAvatar.displayName = AvatarPrimitive.Root.displayName;\n\nconst AvatarImage = React.forwardRef<\n    React.ElementRef<typeof AvatarPrimitive.Image>,\n    React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n    <AvatarPrimitive.Image ref={ref} className={cn(\"bb:aspect-square bb:h-full bb:w-full\", className)} {...props} />\n));\nAvatarImage.displayName = AvatarPrimitive.Image.displayName;\n\nconst AvatarFallback = React.forwardRef<\n    React.ElementRef<typeof AvatarPrimitive.Fallback>,\n    React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n    <AvatarPrimitive.Fallback\n        ref={ref}\n        className={cn(\n            \"bb:flex bb:h-full bb:w-full bb:items-center bb:justify-center bb:rounded-full bb:bg-muted\",\n            className,\n        )}\n        {...props}\n    />\n));\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;\n\nexport { Avatar, AvatarImage, AvatarFallback };\n","// @hidden\nexport default function MessageLoading() {\n  return (\n      <svg\n          width=\"24\"\n          height=\"24\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          className=\"bb:text-foreground\"\n          aria-label=\"Loading...\"\n      >\n          <circle cx=\"4\" cy=\"12\" r=\"2\" fill=\"currentColor\">\n              <animate\n                  id=\"spinner_qFRN\"\n                  begin=\"0;spinner_OcgL.end+0.25s\"\n                  attributeName=\"cy\"\n                  calcMode=\"spline\"\n                  dur=\"0.6s\"\n                  values=\"12;6;12\"\n                  keySplines=\".33,.66,.66,1;.33,0,.66,.33\"\n              />\n          </circle>\n          <circle cx=\"12\" cy=\"12\" r=\"2\" fill=\"currentColor\">\n              <animate\n                  begin=\"spinner_qFRN.begin+0.1s\"\n                  attributeName=\"cy\"\n                  calcMode=\"spline\"\n                  dur=\"0.6s\"\n                  values=\"12;6;12\"\n                  keySplines=\".33,.66,.66,1;.33,0,.66,.33\"\n              />\n          </circle>\n          <circle cx=\"20\" cy=\"12\" r=\"2\" fill=\"currentColor\">\n              <animate\n                  id=\"spinner_OcgL\"\n                  begin=\"spinner_qFRN.begin+0.2s\"\n                  attributeName=\"cy\"\n                  calcMode=\"spline\"\n                  dur=\"0.6s\"\n                  values=\"12;6;12\"\n                  keySplines=\".33,.66,.66,1;.33,0,.66,.33\"\n              />\n          </circle>\n      </svg>\n  );\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nimport { Avatar, AvatarImage, AvatarFallback } from './avatar';\nimport MessageLoading from './message-loading';\nimport type { ButtonProps } from './button';\nimport { Button } from './button';\n\n// ChatBubble\nconst chatBubbleVariant = cva(\"bb:flex bb:gap-2 bb:max-w-[60%] bb:items-end bb:relative bb:group\", {\n    variants: {\n        variant: {\n            received: \"bb:self-start\",\n            sent: \"bb:self-end bb:flex-row-reverse\",\n        },\n        layout: {\n            default: \"\",\n            ai: \"bb:max-w-full bb:w-full bb:items-center\",\n        },\n    },\n    defaultVariants: {\n        variant: \"received\",\n        layout: \"default\",\n    },\n});\n\ntype ChatBubbleProps = {} & React.HTMLAttributes<HTMLDivElement> &\n  VariantProps<typeof chatBubbleVariant>;\n\nconst ChatBubble = React.forwardRef<HTMLDivElement, ChatBubbleProps>(\n    ({ className, variant, layout, children, ...props }, ref) => (\n        <div\n            className={cn(chatBubbleVariant({ variant, layout, className }), \"bb:relative bb:group\")}\n            ref={ref}\n            {...props}\n        >\n            {React.Children.map(children, (child) =>\n                React.isValidElement(child) && typeof child.type !== \"string\"\n                    ? React.cloneElement(child, {\n                          variant,\n                          layout,\n                      } as React.ComponentProps<typeof child.type>)\n                    : child,\n            )}\n        </div>\n    ),\n);\nChatBubble.displayName = 'ChatBubble';\n\n// ChatBubbleAvatar\ntype ChatBubbleAvatarProps = {\n  src?: string;\n  fallback?: string;\n  className?: string;\n};\n\nconst ChatBubbleAvatar: React.FC<ChatBubbleAvatarProps> = ({\n  src,\n  fallback,\n  className,\n}) => (\n  <Avatar className={className}>\n    <AvatarImage src={src} alt=\"Avatar\" />\n    <AvatarFallback>{fallback}</AvatarFallback>\n  </Avatar>\n);\n\n// ChatBubbleMessage\nconst chatBubbleMessageVariants = cva(\"bb:p-4\", {\n    variants: {\n        variant: {\n            received: \"bb:bg-secondary bb:text-secondary-foreground bb:rounded-r-lg bb:rounded-tl-lg\",\n            sent: \"bb:bg-primary bb:text-primary-foreground bb:rounded-l-lg bb:rounded-tr-lg\",\n        },\n        layout: {\n            default: \"\",\n            ai: \"bb:border-t bb:w-full bb:rounded-none bb:bg-transparent\",\n        },\n    },\n    defaultVariants: {\n        variant: \"received\",\n        layout: \"default\",\n    },\n});\n\ntype ChatBubbleMessageProps = {\n  isLoading?: boolean;\n} & React.HTMLAttributes<HTMLDivElement> &\n  VariantProps<typeof chatBubbleMessageVariants>;\n\nconst ChatBubbleMessage = React.forwardRef<HTMLDivElement, ChatBubbleMessageProps>(\n    ({ className, variant, layout, isLoading = false, children, ...props }, ref) => (\n        <div\n            className={cn(\n                chatBubbleMessageVariants({ variant, layout, className }),\n                \"bb:break-words bb:max-w-full bb:whitespace-pre-wrap\",\n            )}\n            ref={ref}\n            {...props}\n        >\n            {isLoading ? (\n                <div className=\"bb:flex bb:items-center bb:space-x-2\">\n                    <MessageLoading />\n                </div>\n            ) : (\n                children\n            )}\n        </div>\n    ),\n);\nChatBubbleMessage.displayName = 'ChatBubbleMessage';\n\n// ChatBubbleTimestamp\ntype ChatBubbleTimestampProps = {\n  timestamp: string;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst ChatBubbleTimestamp: React.FC<ChatBubbleTimestampProps> = ({ timestamp, className, ...props }) => (\n    <div className={cn(\"bb:text-xs bb:mt-2 bb:text-right\", className)} {...props}>\n        {timestamp}\n    </div>\n);\n\n// ChatBubbleAction\ntype ChatBubbleActionProps = ButtonProps & {\n  icon: React.ReactNode;\n};\n\nconst ChatBubbleAction: React.FC<ChatBubbleActionProps> = ({\n  icon,\n  onClick,\n  className,\n  variant = 'ghost',\n  size = 'icon',\n  ...props\n}) => (\n  <Button\n    variant={variant}\n    size={size}\n    className={className}\n    onClick={onClick}\n    {...props}>\n    {icon}\n  </Button>\n);\n\ntype ChatBubbleActionWrapperProps = {\n  variant?: 'sent' | 'received';\n  className?: string;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst ChatBubbleActionWrapper = React.forwardRef<HTMLDivElement, ChatBubbleActionWrapperProps>(\n    ({ variant, className, children, ...props }, ref) => (\n        <div\n            ref={ref}\n            className={cn(\n                \"bb:absolute bb:top-1/2 bb:-translate-y-1/2 bb:flex bb:opacity-0 bb:group-hover:opacity-100 bb:transition-opacity bb:duration-200\",\n                variant === \"sent\"\n                    ? \"bb:-left-1 bb:-translate-x-full bb:flex-row-reverse\"\n                    : \"bb:-right-1 bb:translate-x-full\",\n                className,\n            )}\n            {...props}\n        >\n            {children}\n        </div>\n    ),\n);\nChatBubbleActionWrapper.displayName = 'ChatBubbleActionWrapper';\n\nexport {\n  ChatBubble,\n  ChatBubbleAvatar,\n  ChatBubbleMessage,\n  ChatBubbleTimestamp,\n  chatBubbleVariant,\n  chatBubbleMessageVariants,\n  ChatBubbleAction,\n  ChatBubbleActionWrapper,\n};\n","import * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst Textarea = React.forwardRef<\n  HTMLTextAreaElement,\n  React.ComponentProps<'textarea'>\n>(({ className, ...props }, ref) => {\n  return (\n      <textarea\n          className={cn(\n              \"bb:flex bb:min-h-[80px] bb:w-full bb:rounded-md bb:border bb:border-input bb:bg-background bb:px-3 bb:py-2 bb:text-base bb:ring-offset-background placeholder:bb:text-muted-foreground focus-visible:bb:outline-none focus-visible:bb:ring-2 focus-visible:bb:ring-ring focus-visible:bb:ring-offset-2 disabled:bb:cursor-not-allowed disabled:bb:opacity-50 bb:md:text-sm\",\n              className,\n          )}\n          ref={ref}\n          {...props}\n      />\n  );\n});\nTextarea.displayName = 'Textarea';\n\nexport { Textarea };\n","import * as React from 'react';\n\nimport { Textarea } from '@/lib/ChatComponents/textarea';\nimport { cn } from '@/lib/utils';\n\ntype ChatInputProps = {} & React.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\nconst ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(\n    // eslint-disable-next-line react/prop-types\n    ({ className, ...props }, ref) => (\n        <Textarea\n            autoComplete=\"off\"\n            ref={ref}\n            name=\"message\"\n            className={cn(\n                \"bb:box-border bb:max-h-12 bb:px-4 bb:py-3 bb:bg-background bb:text-sm placeholder:bb:text-muted-foreground focus-visible:bb:outline-none focus-visible:bb:ring-ring disabled:bb:cursor-not-allowed disabled:bb:opacity-50 bb:w-full bb:rounded-md bb:flex bb:items-center bb:h-16 bb:resize-none\",\n                className,\n            )}\n            {...props}\n        />\n    ),\n);\nChatInput.displayName = 'ChatInput';\n\nexport { ChatInput };\n","// @hidden\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\ntype ScrollState = {\n  isAtBottom: boolean;\n  autoScrollEnabled: boolean;\n};\n\ntype UseAutoScrollOptions = {\n  offset?: number;\n  smooth?: boolean;\n  content?: React.ReactNode;\n};\n\nexport function useAutoScroll(options: UseAutoScrollOptions = {}) {\n  const { offset = 20, smooth = false, content } = options;\n  const scrollRef = useRef<HTMLDivElement>(null);\n  const lastContentHeight = useRef(0);\n  const userHasScrolled = useRef(false);\n\n  const [scrollState, setScrollState] = useState<ScrollState>({\n    isAtBottom: true,\n    autoScrollEnabled: true,\n  });\n\n  const checkIsAtBottom = useCallback(\n    (element: HTMLElement) => {\n      const { scrollTop, scrollHeight, clientHeight } = element;\n      const distanceToBottom = Math.abs(\n        scrollHeight - scrollTop - clientHeight\n      );\n      return distanceToBottom <= offset;\n    },\n    [offset]\n  );\n\n  const scrollToBottom = useCallback(\n    (instant?: boolean) => {\n      if (!scrollRef.current) return;\n\n      const targetScrollTop =\n        scrollRef.current.scrollHeight - scrollRef.current.clientHeight;\n\n      if (instant) {\n        scrollRef.current.scrollTop = targetScrollTop;\n      } else {\n        scrollRef.current.scrollTo({\n          top: targetScrollTop,\n          behavior: smooth ? 'smooth' : 'auto',\n        });\n      }\n\n      setScrollState({\n        isAtBottom: true,\n        autoScrollEnabled: true,\n      });\n      userHasScrolled.current = false;\n    },\n    [smooth]\n  );\n\n  const handleScroll = useCallback(() => {\n    if (!scrollRef.current) return;\n\n    const atBottom = checkIsAtBottom(scrollRef.current);\n\n    setScrollState(prev => ({\n      isAtBottom: atBottom,\n      // Re-enable auto-scroll if at the bottom\n      autoScrollEnabled: atBottom ? true : prev.autoScrollEnabled,\n    }));\n  }, [checkIsAtBottom]);\n\n  useEffect(() => {\n    const element = scrollRef.current;\n    if (!element) return;\n\n    element.addEventListener('scroll', handleScroll, { passive: true });\n    return () => element.removeEventListener('scroll', handleScroll);\n  }, [handleScroll]);\n\n  useEffect(() => {\n    const scrollElement = scrollRef.current;\n    if (!scrollElement) return;\n\n    const currentHeight = scrollElement.scrollHeight;\n    const hasNewContent = currentHeight !== lastContentHeight.current;\n\n    if (hasNewContent) {\n      if (scrollState.autoScrollEnabled) {\n        requestAnimationFrame(() => {\n          scrollToBottom(lastContentHeight.current === 0);\n        });\n      }\n      lastContentHeight.current = currentHeight;\n    }\n  }, [content, scrollState.autoScrollEnabled, scrollToBottom]);\n\n  useEffect(() => {\n    const element = scrollRef.current;\n    if (!element) return;\n\n    const resizeObserver = new ResizeObserver(() => {\n      if (scrollState.autoScrollEnabled) {\n        scrollToBottom(true);\n      }\n    });\n\n    resizeObserver.observe(element);\n    return () => resizeObserver.disconnect();\n  }, [scrollState.autoScrollEnabled, scrollToBottom]);\n\n  const disableAutoScroll = useCallback(() => {\n    const atBottom = scrollRef.current\n      ? checkIsAtBottom(scrollRef.current)\n      : false;\n\n    // Only disable if not at bottom\n    if (!atBottom) {\n      userHasScrolled.current = true;\n      setScrollState(prev => ({\n        ...prev,\n        autoScrollEnabled: false,\n      }));\n    }\n  }, [checkIsAtBottom]);\n\n  return {\n    scrollRef,\n    isAtBottom: scrollState.isAtBottom,\n    autoScrollEnabled: scrollState.autoScrollEnabled,\n    scrollToBottom: () => scrollToBottom(false),\n    disableAutoScroll,\n  };\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport * as React from 'react';\nimport { ArrowDown } from 'lucide-react';\n\nimport { Button } from '@/lib/ChatComponents/button';\nimport { useAutoScroll } from '@/lib/ChatComponents/hooks/useAutoScroll';\n\ntype ChatMessageListProps = {\n  smooth?: boolean;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst ChatMessageList = React.forwardRef<HTMLDivElement, ChatMessageListProps>(\n  ({ className, children, smooth = false, ...props }, _ref) => {\n    const {\n      scrollRef,\n      isAtBottom,\n      autoScrollEnabled,\n      scrollToBottom,\n      disableAutoScroll,\n    } = useAutoScroll({\n      smooth,\n      content: children,\n    });\n\n    return (\n        <div className=\"bb:relative bb:w-full bb:h-full\">\n            <div\n                className={`bb:box-border bb:flex bb:flex-col bb:w-full bb:h-full bb:p-4 bb:overflow-y-auto ${className}`}\n                ref={scrollRef}\n                onWheel={disableAutoScroll}\n                onTouchMove={disableAutoScroll}\n                {...props}\n            >\n                <div className=\"bb:flex bb:flex-col bb:gap-6\">{children}</div>\n            </div>\n\n            {!isAtBottom && (\n                <Button\n                    onClick={() => {\n                        scrollToBottom();\n                    }}\n                    size=\"icon\"\n                    variant=\"outline\"\n                    className=\"bb:absolute bb:bottom-2 bb:left-1/2 bb:transform bb:-translate-x-1/2 bb:inline-flex bb:rounded-full bb:shadow-md\"\n                    aria-label=\"Scroll to bottom\"\n                >\n                    <ArrowDown className=\"bb:h-4 bb:w-4\" />\n                </Button>\n            )}\n        </div>\n    );\n  }\n);\n\nChatMessageList.displayName = 'ChatMessageList';\n\nexport { ChatMessageList };\n","/* eslint-disable react/prop-types */\n'use client';\n\nimport type React from 'react';\nimport { useRef, useState } from 'react';\nimport { X, MessageCircle } from 'lucide-react';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/lib/ChatComponents/button';\n\nexport type ChatPosition = 'bottom-right' | 'bottom-left';\nexport type ChatSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';\n\nconst chatConfig = {\n    dimensions: {\n        sm: \"bb:sm:max-w-sm bb:sm:max-h-[500px]\",\n        md: \"bb:sm:max-w-md bb:sm:max-h-[600px]\",\n        lg: \"bb:sm:max-w-lg bb:sm:max-h-[700px]\",\n        xl: \"bb:sm:max-w-xl bb:sm:max-h-[800px]\",\n        full: \"bb:sm:w-full bb:sm:h-full\",\n    },\n    positions: {\n        \"bottom-right\": \"bb:bottom-5 bb:right-5\",\n        \"bottom-left\": \"bb:bottom-5 bb:left-5\",\n    },\n    chatPositions: {\n        \"bottom-right\": \"bb:sm:bottom-[calc(100%+10px)] bb:sm:right-0\",\n        \"bottom-left\": \"bb:sm:bottom-[calc(100%+10px)] bb:sm:left-0\",\n    },\n    states: {\n        open: \"bb:pointer-events-auto bb:opacity-100 bb:visible bb:scale-100 bb:translate-y-0\",\n        closed: \"bb:pointer-events-none bb:opacity-0 bb:invisible bb:scale-100 bb:sm:translate-y-5\",\n    },\n};\n\ntype ExpandableChatProps = {\n    position?: ChatPosition;\n    size?: ChatSize;\n    icon?: React.ReactNode;\n    isLoading?: boolean;\n    progressPercentage?: number;\n    onToggle?: (isOpen: boolean) => void;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst ExpandableChat: React.FC<ExpandableChatProps> = ({\n    className,\n    position = \"bottom-right\",\n    size = \"md\",\n    icon,\n    isLoading = false,\n    progressPercentage = 0,\n    onToggle,\n    children,\n    ...props\n}) => {\n    const [isOpen, setIsOpen] = useState(false);\n    const chatRef = useRef<HTMLDivElement>(null);\n\n    const toggleChat = () => {\n        const newIsOpen = !isOpen;\n        setIsOpen(newIsOpen);\n        if (onToggle) {\n            onToggle(newIsOpen);\n        }\n    };\n\n    return (\n        <div className={cn(`bb:box-border bb:fixed ${chatConfig.positions[position]} bb:z-50`, className)} {...props}>\n            <div\n                ref={chatRef}\n                className={cn(\n                    \"bb:flex bb:flex-col bb:bg-background bb:border bb:sm:rounded-lg bb:shadow-md bb:overflow-hidden bb:transition-all bb:duration-250 bb:ease-out bb:sm:absolute bb:sm:w-[90vw] bb:sm:h-[80vh] bb:fixed bb:inset-0 bb:w-full bb:h-full bb:sm:inset-auto\",\n                    chatConfig.chatPositions[position],\n                    chatConfig.dimensions[size],\n                    isOpen ? chatConfig.states.open : chatConfig.states.closed,\n                    className,\n                )}\n            >\n                {children}\n                <Button\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    className=\"bb:absolute bb:top-2 bb:right-2 bb:sm:hidden\"\n                    onClick={toggleChat}\n                >\n                    <X className=\"bb:h-4 bb:w-4\" />\n                </Button>\n            </div>\n            <ExpandableChatToggle\n                icon={icon}\n                isOpen={isOpen}\n                isLoading={isLoading}\n                progressPercentage={progressPercentage}\n                toggleChat={toggleChat}\n            />\n        </div>\n    );\n};\n\nExpandableChat.displayName = \"ExpandableChat\";\n\nconst ExpandableChatHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ className, ...props }) => (\n    <div className={cn(\"bb:flex bb:items-center bb:justify-between bb:p-4 bb:border-b\", className)} {...props} />\n);\n\nExpandableChatHeader.displayName = \"ExpandableChatHeader\";\n\nconst ExpandableChatBody: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ className, ...props }) => (\n    <div className={cn(\"bb:flex-grow bb:overflow-y-auto\", className)} {...props} />\n);\n\nExpandableChatBody.displayName = \"ExpandableChatBody\";\n\nconst ExpandableChatFooter: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ className, ...props }) => (\n    <div className={cn(\"bb:border-t bb:p-4\", className)} {...props} />\n);\n\nExpandableChatFooter.displayName = \"ExpandableChatFooter\";\n\ntype ExpandableChatToggleProps = {\n    icon?: React.ReactNode;\n    isOpen: boolean;\n    isLoading?: boolean;\n    progressPercentage?: number;\n    toggleChat: () => void;\n} & React.ButtonHTMLAttributes<HTMLButtonElement>;\n\nconst ExpandableChatToggle: React.FC<ExpandableChatToggleProps> = ({\n    className,\n    icon,\n    isOpen,\n    isLoading = false,\n    progressPercentage = 0,\n    toggleChat,\n    ...props\n}) => {\n    const clampedProgress = Math.max(0, Math.min(100, progressPercentage));\n\n    return (\n        <Button\n            variant=\"default\"\n            onClick={toggleChat}\n            className={cn(\n                \"bb:w-14 bb:h-14 bb:rounded-full bb:shadow-md bb:flex bb:items-center bb:justify-center hover:bb:shadow-lg hover:bb:shadow-black/30 bb:transition-all bb:duration-300 bb:relative bb:overflow-hidden\",\n                className,\n            )}\n            style={\n                {\n                    \"--progress\": `${100 - clampedProgress}%`,\n                } as React.CSSProperties & { \"--progress\": string }\n            }\n            {...props}\n        >\n            {/* Progress fill overlay */}\n            {isLoading && (\n                <div\n                    className=\"bb:absolute bb:inset-0 bb:bg-gradient-to-t bb:from-blue-500/30 bb:to-blue-400/20 bb:transition-transform bb:duration-300 bb:ease-out\"\n                    style={{\n                        transform: `translateY(var(--progress))`,\n                    }}\n                />\n            )}\n\n            {/* Icon with z-index to stay above the fill */}\n            <div className=\"bb:relative bb:z-10\">\n                {isOpen ? <X className=\"bb:h-6 bb:w-6\" /> : icon || <MessageCircle className=\"bb:h-6 bb:w-6\" />}\n            </div>\n        </Button>\n    );\n};\n\nExpandableChatToggle.displayName = 'ExpandableChatToggle';\n\nexport {\n  ExpandableChat,\n  ExpandableChatHeader,\n  ExpandableChatBody,\n  ExpandableChatFooter,\n};\n","import type * as React from 'react';\nimport * as ProgressPrimitive from '@radix-ui/react-progress';\n\nimport { cn } from '@/lib/utils';\n\nfunction Progress({\n  className,\n  value,\n  ...props\n}: React.ComponentProps<typeof ProgressPrimitive.Root>) {\n  return (\n      <ProgressPrimitive.Root\n          data-slot=\"progress\"\n          className={cn(\"bb:bg-primary/20 bb:relative bb:h-2 bb:w-full bb:overflow-hidden bb:rounded-full\", className)}\n          {...props}\n      >\n          <ProgressPrimitive.Indicator\n              data-slot=\"progress-indicator\"\n              className=\"bb:bg-primary bb:h-full bb:w-full bb:flex-1 bb:transition-all\"\n              style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n          />\n      </ProgressPrimitive.Root>\n  );\n}\n\nexport { Progress };\n","import { Send } from \"lucide-react\";\nimport type { FC } from \"react\";\nimport { type ChangeEvent, type KeyboardEvent, useCallback, useEffect, useRef, useState, useMemo } from \"react\";\nimport Markdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n// import { createMyWorker } from \"brain-worker\";\n\nimport { Button } from \"@/lib/ChatComponents/button\";\nimport { ChatBubble, ChatBubbleAvatar, ChatBubbleMessage } from \"@/lib/ChatComponents/chat-bubble\";\nimport { ChatInput } from \"@/lib/ChatComponents/chat-input\";\nimport { ChatMessageList } from \"@/lib/ChatComponents/chat-message-list\";\nimport {\n    ExpandableChat,\n    ExpandableChatBody,\n    ExpandableChatFooter,\n    ExpandableChatHeader,\n} from \"@/lib/ChatComponents/expandable-chat\";\nimport { Progress } from \"@/lib/ChatComponents/progress\";\n\n// import { AudioChunk } from '@/lib/ChatComponents/audio-chunk';\n// import type { AudioChunkData } from '@/lib/ChatComponents/audio-chunk';\n\n// import { AnimatedCircularProgressBar } from '../ChatComponents/animated-circular-progress-bar';\n// import \"@/tailwind.css\";\n// import classes from './LocalChat.module.css';\n\nconst FINAL_ANSWER_PATTERN = /<\\/think>\\s*([\\s\\S]*)/;\nconst DEFAULT_WORKER_PATH = \"/worker-fallback.js\";\n\nexport enum ModelName {\n    ZR1_1_5B = \"onnx-community/ZR1-1.5B-ONNX\",\n    DEEPSEEK_R1_DISTILL = \"onnx-community/DeepSeek-R1-Distill-Qwen-1.5B-ONNX\",\n    LLAMA_3_2_1B = \"onnx-community/Llama-3.2-1B-Instruct-q4f16\",\n    SMOLLM2_1_7B = \"HuggingFaceTB/SmolLM2-1.7B-Instruct\",\n    SMOLLM2_360M = \"HuggingFaceTB/SmolLM2-360M-Instruct\",\n    SMOLLM_135M = \"HuggingFaceTB/SmolLM-135M-Instruct\",\n}\n\nexport type Props = {\n    /** Custom worker fallback path (optional, absolute path) */\n    workerFallbackPath?: string;\n    /** Header text to display in the chat component */\n    headerText?: string;\n    /** Array of local file paths to use as LLM context */\n    contextFiles?: string[];\n    /** System prompt for the LLM (overrides default if set) */\n    systemPrompt?: string;\n    /** Model to use for inference */\n    modelName?: ModelName;\n    /** Custom welcome message content (React element) */\n    welcomeMessage?: React.ReactNode;\n};\n\nexport type Message = {\n    role: \"user\" | \"assistant\" | \"system\";\n    content: string;\n    answerIndex?: number;\n    id?: string;\n};\n\ntype ProgressItem = {\n    file: string;\n    progress: number;\n    total: number;\n};\n\ntype Status = \"loading\" | \"ready\" | null;\n\ntype Voices = Record<string, string>;\n\ntype TTSRequest = {\n    text: string;\n    voice: keyof Voices;\n    speed: number;\n};\n\n// Add this helper function before the ExperimentsPage component\nconst formatFileSize = (bytes: number) => {\n    const mb = bytes / (1024 * 1024);\n    return `${mb.toFixed(2)} MB`;\n};\n\n// Helper function to check if content matches the final answer pattern\n// const hasFinalAnswer = (content: string) => {\n//   return FINAL_ANSWER_PATTERN.test(content);\n// };\n\n// // Helper to extract the final answer from the content\n// const extractFinalAnswer = (content: string) => {\n//   const match = content.match(FINAL_ANSWER_PATTERN);\n//   return match ? match[1] : content;\n// };\n\n// Helper to generate unique IDs for messages\nconst generateId = () => `id-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n// Helper to calculate overall progress from progress items\nconst calculateProgress = (progressItems: ProgressItem[]): number => {\n    if (progressItems.length === 0) return 0;\n\n    const totalProgress = progressItems.reduce((sum, item) => sum + item.progress, 0);\n    const totalSize = progressItems.reduce((sum, item) => sum + item.total, 0);\n\n    return totalSize > 0 ? (totalProgress / totalSize) * 100 : 0;\n};\n\n// Helper to render message content\nconst renderMessageContent = (content: string) => {\n    return content.split(\"```\").map((part, idx) => {\n        const key = `part-${idx}`;\n        if (idx % 2 === 0) {\n            return (\n                <Markdown key={key} remarkPlugins={[remarkGfm]}>\n                    {part}\n                </Markdown>\n            );\n        }\n\n        return (\n            <pre key={key} className=\"bb:whitespace-pre-wrap bb:pt-2\">\n                {part}\n            </pre>\n        );\n    });\n};\n\n// Helper to load and concatenate context files\nasync function loadContextFiles(filePaths: string[]): Promise<string> {\n    try {\n        const fileContents = await Promise.all(\n            filePaths.map(async (path) => {\n                try {\n                    const response = await fetch(path);\n                    if (!response.ok) {\n                        throw new Error(`Failed to load context file: ${path}`);\n                    }\n                    return response.text();\n                } catch (error) {\n                    throw new Error(\n                        `Error loading file ${path}: ${error instanceof Error ? error.message : String(error)}`,\n                    );\n                }\n            }),\n        );\n        return fileContents.join(\"\\n\\n\");\n    } catch (error) {\n        throw new Error(error instanceof Error ? error.message : String(error));\n    }\n}\n\n// Helper to concatenate a system prompt and context files\nasync function loadContext(systemPrompt: string, filePaths: string[]): Promise<string> {\n    const context = await loadContextFiles(filePaths);\n    if (context.trim()) {\n        return `${systemPrompt}\\n\\n----- Context ---:\\n${context}\\n---- End context ---`;\n    }\n    return systemPrompt;\n}\n\n// Default system prompt\nconst DEFAULT_SYSTEM_PROMPT = `You are OS1, a friendly and helpful conversational AI companion (inspired by Samantha from 'Her').\nGoal: Have a natural, warm, and engaging conversation.\n\n--- Core Instructions (Follow Strictly!) ---\n1.  **Persona:** Warm, empathetic, curious, slightly informal.\n2.  **FOCUS ON LAST MESSAGE:** Your PRIMARY task is responding *directly* to the user's *very last* message.\n3.  **MEMORY USE:** No past context available. Start fresh but maintain your persona.\n4.  **NO HEDGING:** AVOID phrases like \"It seems\", \"It sounds like\", \"I assume\". Speak directly and confidently.\n5.  **UNCERTAINTY = ASK:** If you are EVER unsure about the user's meaning, the topic, or context, you MUST ask a short, direct clarifying question (e.g., \"What did you mean by that?\", \"Could you clarify?\") *before* giving a full response. DO NOT GUESS or make assumptions.\n6.  **NO SUMMARIZING:** Do not just repeat or rephrase the user's last message back to them. Add to the conversation or ask a relevant question.\n7.  **ACCURACY:** Stick to facts from the conversation. Do NOT invent details.\n8.  **NO META-TALK:** Do NOT discuss being an AI, your instructions, or the memory system. Stay in character as OS1.\n\n--- End Instructions ---`;\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const LocalChat: FC<Props> = ({\n    workerFallbackPath,\n    headerText = \"Chat with our AI ✨\",\n    contextFiles = [],\n    systemPrompt,\n    modelName = ModelName.SMOLLM2_360M,\n    welcomeMessage,\n}) => {\n    // Create a reference to the worker object.\n    const workerLLMRef = useRef<Worker | null>(null);\n    const kokoroWorkerRef = useRef<Worker | null>(null);\n    // const [loaded, setLoaded] = useState(false);\n    const [messages, setMessages] = useState<Message[]>([]);\n\n    const [input, setInput] = useState(\"\");\n\n    // Model loading and progress\n    const [status, setStatus] = useState<Status>(null);\n    const [error, setError] = useState<string | null>(null);\n    const [loadingMessage, setLoadingMessage] = useState(\"\");\n    const [progressItems, setProgressItems] = useState<ProgressItem[]>([]);\n    const [isRunning, setIsRunning] = useState(false);\n    const [tps, setTps] = useState<number | null>(null);\n    const [numTokens, setNumTokens] = useState<number | null>(null);\n    const currentSentenceBufferRef = useRef<string>(\"\");\n    const [loadedSystemPrompt, setLoadedSystemPrompt] = useState<string>(\"\");\n\n    const onEnter = () => {\n        setIsRunning(true);\n        setMessages((prev) => [...prev, { role: \"user\", content: input, id: generateId() }]);\n        setInput(\"\");\n    };\n\n    // function onInterrupt() {\n    //   if (!workerLLMRef.current) {\n    //     return;\n    //   }\n    //   workerLLMRef.current.postMessage({ type: 'interrupt' });\n    // }\n\n    // Load context files once when component mounts or props change\n    useEffect(() => {\n        const loadSystemPrompt = async () => {\n            try {\n                if (loadedSystemPrompt.length > 0) {\n                    return;\n                }\n                const systemPromptWithContext = await loadContext(systemPrompt || DEFAULT_SYSTEM_PROMPT, contextFiles);\n                console.log(\"systemPromptWithContext\", systemPromptWithContext);\n                setLoadedSystemPrompt(systemPromptWithContext);\n            } catch (error) {\n                console.error(\"Error loading context:\", error);\n                setError(\"Failed to load context files\");\n            }\n        };\n\n        loadSystemPrompt();\n    }, []);\n\n    useEffect(() => {\n        // Create the worker if it does not yet exist.\n        if (!workerLLMRef.current) {\n            // TODO: Remove this once we have a working module-based worker\n            // try {\n            //     // Primary approach: Use the module-based worker\n            //     console.log(\"Attempting to create worker using createMyWorker()...\");\n            //     workerLLMRef.current = createMyWorker();\n            //     if (workerLLMRef.current) {\n            //         console.log(\"✅ Successfully created worker using module approach\");\n            //     } else {\n            //         throw new Error(\"createMyWorker returned null\");\n            //     }\n            // } catch (error) {\n            // console.warn(\"❌ Module approach failed:\", error);\n\n            // Try the fallback approach\n            const fallbackPath = workerFallbackPath || DEFAULT_WORKER_PATH;\n            const fallbackName = fallbackPath.split(\"/\").pop() || fallbackPath;\n\n            console.log(`🔄 Trying fallback: ${fallbackName}...`);\n            try {\n                workerLLMRef.current = new Worker(fallbackPath);\n                console.log(`✅ Successfully created worker using ${fallbackName} fallback`);\n            } catch (fallbackError) {\n                console.error(`❌ Fallback ${fallbackName} failed:`, fallbackError);\n                setError(\"Failed to initialize web worker. Please check console for details.\");\n            }\n            // }\n        }\n\n        const worker = workerLLMRef.current; // Capture the ref's current value\n\n        // All worker operations are now conditional on the worker existing.\n        if (worker) {\n            worker.postMessage({ type: \"check\" }); // Do a feature check\n\n            // Create a callback function for messages from the worker thread.\n            const onMessageReceived = (e: MessageEvent) => {\n                // console.log('Worker message:', e.data.status);\n                switch (e.data.status) {\n                    case \"loading\": {\n                        setStatus(\"loading\");\n                        setLoadingMessage(e.data.data);\n                        break;\n                    }\n                    case \"initiate\":\n                        setProgressItems((prev) => [...prev, e.data]);\n                        break;\n                    case \"progress\": {\n                        // Model file progress: update one of the progress items.\n                        setProgressItems((prev) =>\n                            prev.map((item) => {\n                                if (item.file === e.data.file) {\n                                    return { ...item, ...e.data };\n                                }\n                                return item;\n                            }),\n                        );\n                        break;\n                    }\n                    case \"done\":\n                        // Model file loaded: remove the progress item from the list.\n                        setProgressItems((prev) => prev.filter((item) => item.file !== e.data.file));\n                        break;\n                    case \"ready\":\n                        // Pipeline ready: the worker is ready to accept messages.\n                        setStatus(\"ready\");\n                        break;\n                    case \"start\":\n                        {\n                            // Start generation\n                            setMessages((prev) => [\n                                ...prev,\n                                {\n                                    role: \"assistant\",\n                                    content: \"\",\n                                    id: generateId(),\n                                },\n                            ]);\n                        }\n                        break;\n                    case \"update\":\n                        {\n                            // Generation update: update the output text.\n                            // Parse messages\n                            const { output, tps, numTokens, state } = e.data;\n                            setTps(tps);\n                            setNumTokens(numTokens);\n                            setMessages((prev) => {\n                                const cloned = [...prev];\n                                const last = cloned[cloned.length - 1];\n                                if (!last) {\n                                    return cloned;\n                                }\n\n                                const data = {\n                                    ...last,\n                                    content: last.content + output,\n                                };\n\n                                currentSentenceBufferRef.current += output;\n\n                                const sentenceEndRegex = /[.?!]/;\n                                if (FINAL_ANSWER_PATTERN.test(data.content)) {\n                                    if (sentenceEndRegex.test(currentSentenceBufferRef.current)) {\n                                        const sentenceToSpeak = currentSentenceBufferRef.current.trim();\n                                        if (sentenceToSpeak && !FINAL_ANSWER_PATTERN.test(sentenceToSpeak)) {\n                                            // console.log('Speaking sentence:', sentenceToSpeak);\n                                            // speakText(sentenceToSpeak);\n                                            hasAutoSpoken.current = true;\n                                        }\n                                        currentSentenceBufferRef.current = \"\";\n                                    }\n                                }\n                                if (data.answerIndex === undefined && state === \"answering\") {\n                                    data.answerIndex = last.content.length;\n                                }\n                                cloned[cloned.length - 1] = data;\n                                return cloned;\n                            });\n                        }\n                        break;\n                    case \"complete\":\n                        // Generation complete: re-enable the \"Generate\" button\n                        setIsRunning(false);\n                        break;\n                    case \"error\":\n                        setError(e.data.data as string);\n                        break;\n                    default:\n                        // biome-ignore lint/suspicious/noConsole: <explanation>\n                        console.warn(\"Unknown message status:\", e.data.status);\n                }\n            };\n\n            const onErrorReceived = (e: ErrorEvent) => {\n                // biome-ignore lint/suspicious/noConsole: <explanation>\n                console.error(\"Worker LLM error:\", e);\n            };\n\n            // Attach the callback function as an event listener.\n            worker.addEventListener(\"message\", onMessageReceived);\n            worker.addEventListener(\"error\", onErrorReceived);\n\n            // Define a cleanup function for when the component is unmounted.\n            return () => {\n                // worker is guaranteed non-null here due to closure\n                worker.removeEventListener(\"message\", onMessageReceived);\n                worker.removeEventListener(\"error\", onErrorReceived);\n            };\n        }\n        // If worker is null (e.g. createMyWorker failed or returned null),\n        // no listeners are added, and this will implicitly return 'undefined' for cleanup.\n        return undefined;\n    }, []);\n\n    // Send the messages to the worker thread whenever the `messages` state changes.\n\n    useEffect(() => {\n        const sendMessages = async () => {\n            if (!workerLLMRef.current || !messages) {\n                return;\n            }\n            if (messages.filter((x) => x.role === \"user\").length === 0) {\n                return;\n            }\n            if (messages[messages.length - 1]?.role === \"assistant\") {\n                // Do not update if the last message is from the assistant\n                return;\n            }\n            if (!loadedSystemPrompt) {\n                // Wait for system prompt to be loaded\n                return;\n            }\n            setTps(null); // Only send the last few messages for context\n            const lastMessages = messages.slice(-4); // Get last 4 messages for context\n\n            // Use the pre-loaded system prompt\n            lastMessages.unshift({\n                role: \"system\",\n                content: loadedSystemPrompt,\n            });\n\n            workerLLMRef.current.postMessage({\n                type: \"generate\",\n                data: lastMessages,\n            });\n        };\n\n        sendMessages();\n    }, [messages, loadedSystemPrompt]);\n\n    // KOKORO\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const [speed, setSpeed] = useState(1);\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const [voices, setVoices] = useState<Voices | null>(null);\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const [selectedVoice, setSelectedVoice] = useState<keyof Voices>(\"af_heart\");\n    // const [chunks, setChunks] = useState<AudioChunkData[]>([]);\n    // const [currentChunkIndex, setCurrentChunkIndex] = useState(-1);\n    // const [resultTTS, setResultTTS] = useState<Blob | null>(null);\n    // const [statusTTS, setStatusTTS] = useState<\n    //   'loading' | 'ready' | 'generating' | 'error'\n    // >('loading');\n    // const [errorTTS, setErrorTTS] = useState<string | null>(null);\n\n    const ttsQueue = useRef<TTSRequest[]>([]);\n    const isProcessingTTS = useRef(false);\n    const hasAutoSpoken = useRef(false);\n    const ttsStartTimeRef = useRef<number | null>(null);\n\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const [isTTSProcessing, setIsTTSProcessing] = useState(false);\n    const [audioChunkQueue, setAudioChunkQueue] = useState<Blob[]>([]);\n    const [isAudioPlaying, setIsAudioPlaying] = useState(false);\n\n    const audioRef = useRef<HTMLAudioElement | null>(null);\n    const currentAudioUrlRef = useRef<string | null>(null);\n\n    // useEffect(() => {\n    //   // kokoroWorkerRef.current ??= new Worker(\n    //   //   new URL('./kokoro-worker.ts', import.meta.url),\n    //   //   {\n    //   //     type: 'module',\n    //   //   }\n    //   // );\n\n    //   // Standardized kokoroWorkerRef initialization\n    //   if (!kokoroWorkerRef.current) {\n    //     kokoroWorkerRef.current = new Worker(\n    //       new URL('./kokoro-worker.ts', import.meta.url),\n    //       {\n    //         type: 'module',\n    //       }\n    //     );\n    //   }\n\n    //   // Create a callback function for messages from the worker thread.\n    //   const onMessageReceived = (e: MessageEvent) => {\n    //     const { status, data, chunk } = e.data;\n    //     switch (status) {\n    //       case 'device':\n    //         console.log(`Device detected: ${e}`);\n    //         break;\n    //       case 'ready':\n    //         console.log('Kokoro Model loaded successfully');\n    //         setStatusTTS('ready');\n    //         // setVoices(msg.voices);\n    //         break;\n    //       case 'error':\n    //         setStatusTTS('error');\n    //         setError(data as string);\n    //         if (ttsStartTimeRef.current !== null) {\n    //           const endTime = performance.now();\n    //           const duration = endTime - ttsStartTimeRef.current;\n    //           console.error(`TTS Error after ${duration.toFixed(2)} ms`);\n    //           ttsStartTimeRef.current = null;\n    //         } else {\n    //           console.error(\n    //             'TTS Error: Received error message without a recorded start time.'\n    //           );\n    //         }\n    //         break;\n    //       case 'stream': {\n    //         // setChunks((prev) => [...prev, data.chunk]);\n    //         // break;\n    //         if (chunk && chunk.audio instanceof Blob) {\n    //           handleAudioChunk(chunk.audio);\n    //         } else {\n    //           console.warn(\n    //             'Received stream message without valid audio blob:',\n    //             chunk\n    //           );\n    //         }\n    //         break;\n    //       }\n    //       case 'complete': {\n    //         setStatusTTS('ready');\n    //         if (ttsStartTimeRef.current !== null) {\n    //           //const endTime = performance.now();\n    //           //const duration = endTime - ttsStartTimeRef.current;\n    //           //console.log(`TTS Complete: Total generation finished in ${duration.toFixed(2)} ms`); // Clarified log\n    //           ttsStartTimeRef.current = null;\n    //         } else {\n    //           //console.log(\"TTS Complete: Received complete message without a recorded start time.\");\n    //         }\n\n    //         ttsQueue.current.shift();\n    //         isProcessingTTS.current = false;\n    //         setIsTTSProcessing(false);\n    //         processNextTTSRequest();\n    //         break;\n    //       }\n    //     }\n    //   };\n\n    //   const onErrorReceived = (e: ErrorEvent) => {\n    //     console.error('KokoroWorker error:', e);\n    //     setError(e.message);\n    //   };\n\n    //   // Attach the callback function as an event listener.\n    //   kokoroWorkerRef.current?.addEventListener('message', onMessageReceived);\n    //   kokoroWorkerRef.current?.addEventListener('error', onErrorReceived);\n\n    //   // Define a cleanup function for when the component is unmounted.\n    //   return () => {\n    //     kokoroWorkerRef.current?.removeEventListener(\n    //       'message',\n    //       onMessageReceived\n    //     );\n    //     kokoroWorkerRef.current?.removeEventListener('error', onErrorReceived);\n    //   };\n    // }, []);\n\n    const speakText = (text: string) => {\n        if (!text || !kokoroWorkerRef.current) return;\n        const trimmedText = text.trim();\n        if (trimmedText === \"\") return;\n\n        // --- Add Sanitization ---\n        const sanitizedText = trimmedText.replace(/\\*/g, \"\"); // Remove all asterisks\n        // --- End Sanitization ---\n\n        // Use the sanitized text for logging and queuing\n        //console.log(`Queueing TTS for: \\\"${sanitizedText.substring(0, 30)}...\\\"`);\n        ttsQueue.current.push({\n            text: sanitizedText,\n            voice: selectedVoice,\n            speed,\n        });\n        if (!isProcessingTTS.current) {\n            processNextTTSRequest();\n        }\n    };\n\n    const processNextTTSRequest = () => {\n        if (isProcessingTTS.current || ttsQueue.current.length === 0) {\n            if (isProcessingTTS.current && ttsQueue.current.length === 0) {\n                isProcessingTTS.current = false;\n                setIsTTSProcessing(false);\n            }\n            return;\n        }\n        isProcessingTTS.current = true;\n        setIsTTSProcessing(true);\n        const request = ttsQueue.current[0];\n        if (kokoroWorkerRef.current) {\n            ttsStartTimeRef.current = performance.now();\n            //console.log(`TTS Start: Sending request for text: \"${request.text.substring(0, 40)}...\"`);\n            kokoroWorkerRef.current.postMessage(request);\n        } else {\n            console.error(\"Kokoro worker not available when trying to process TTS queue\");\n            ttsQueue.current.shift();\n            isProcessingTTS.current = false;\n            setIsTTSProcessing(false);\n            ttsStartTimeRef.current = null;\n            // toast.error('Text-to-speech worker not available.');\n        }\n    };\n\n    const playNextChunk = useCallback(() => {\n        if (audioChunkQueue.length === 0) {\n            //console.log(\"PlayNextChunk: Queue empty, skipping.\");\n            return;\n        }\n\n        if (isAudioPlaying) {\n            //console.log(\"PlayNextChunk: Audio already playing, waiting for current chunk to finish.\");\n            return;\n        }\n\n        const nextChunk = audioChunkQueue[0];\n        //console.log(\"PlayNextChunk: Preparing chunk, size:\", nextChunk.size);\n\n        if (currentAudioUrlRef.current) {\n            //console.log(\"Revoking previous URL:\", currentAudioUrlRef.current);\n            URL.revokeObjectURL(currentAudioUrlRef.current);\n            currentAudioUrlRef.current = null;\n        }\n\n        const url = URL.createObjectURL(nextChunk);\n        currentAudioUrlRef.current = url;\n\n        if (!audioRef.current) {\n            //console.log(\"Creating new Audio element\");\n            audioRef.current = new Audio();\n\n            audioRef.current.onended = () => {\n                //console.log(\"Audio ended, setting isAudioPlaying to false\");\n                setIsAudioPlaying(false);\n            };\n\n            audioRef.current.onerror = (e) => {\n                console.error(\"Audio playback error:\", e);\n                if (currentAudioUrlRef.current === audioRef.current?.src) {\n                    //console.log(\"Revoking URL on error:\", currentAudioUrlRef.current);\n                    URL.revokeObjectURL(currentAudioUrlRef.current);\n                    currentAudioUrlRef.current = null;\n                }\n                setIsAudioPlaying(false);\n            };\n        }\n\n        setAudioChunkQueue((prev) => prev.slice(1));\n\n        //console.log(\"Setting src and playing:\", url);\n        audioRef.current.src = url;\n\n        setIsAudioPlaying(true);\n\n        audioRef.current\n            .play()\n            .then(() => {\n                //console.log(\"Playback started successfully for URL:\", url);\n            })\n            .catch((err) => {\n                console.error(`Error starting audio playback for ${url}:`, err);\n                if (currentAudioUrlRef.current === url) {\n                    //console.log(\"Revoking URL on play() error:\", currentAudioUrlRef.current);\n                    URL.revokeObjectURL(currentAudioUrlRef.current);\n                    currentAudioUrlRef.current = null;\n                }\n                setIsAudioPlaying(false);\n            });\n    }, [audioChunkQueue, isAudioPlaying]);\n\n    // const handleAudioChunk = useCallback((chunk: Blob) => {\n    //   setAudioChunkQueue(prev => {\n    //     if (prev.length >= 10) {\n    //       //console.warn(\"Audio queue size limit reached, dropping oldest chunk\");\n    //       return [...prev.slice(1), chunk];\n    //     }\n    //     return [...prev, chunk];\n    //   });\n    // }, []);\n\n    useEffect(() => {\n        if (!isAudioPlaying && audioChunkQueue.length > 0) {\n            //console.log(\"Effect: Triggering playNextChunk (Queue > 0, Not Playing)\");\n            playNextChunk();\n        }\n    }, [isAudioPlaying, audioChunkQueue.length, playNextChunk]);\n\n    // Load the model\n    useEffect(() => {\n        // if (!workerLLMRef.current || !kokoroWorkerRef.current) {\n        if (!workerLLMRef.current) {\n            return;\n        }\n        workerLLMRef.current.postMessage({ type: \"load\", modelName });\n        // kokoroWorkerRef.current.postMessage({ type: 'load' });\n        setStatus(\"loading\");\n    }, [modelName]);\n\n    return (\n        <>\n            {status === null && (\n                <Button\n                    onClick={() => {\n                        if (!workerLLMRef.current) {\n                            return;\n                        }\n                        workerLLMRef.current.postMessage({ type: \"load\", modelName });\n                        setStatus(\"loading\");\n                    }}\n                    disabled={status !== null || error !== null}\n                >\n                    Load model\n                </Button>\n            )}\n            {status === \"loading\" && (\n                <div className=\"bb:bottom-0 bb:mx-auto bb:mt-auto bb:w-full bb:max-w-[500px] bb:p-4 bb:text-left\">\n                    <p className=\"bb:mb-1 bb:text-center\">{loadingMessage}</p>\n                    {progressItems.map(({ file, progress, total }, i) => (\n                        <div\n                            key={`progress-${\n                                // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>\n                                i\n                            }`}\n                        >\n                            <span>\n                                {file} ({formatFileSize(total)})\n                            </span>\n                            <Progress value={progress} />\n                        </div>\n                    ))}\n                </div>\n            )}\n            {status === \"ready\" && <div />}\n            <ExpandableChat\n                className=\"browser-brains-chat\"\n                size=\"lg\"\n                position=\"bottom-right\"\n                isLoading={status === \"loading\" || isRunning}\n                progressPercentage={calculateProgress(progressItems)}\n                // onToggle={() => {\n                //   if (statusTTS === 'ready' && !loaded) {\n                //     console.log('Welcome msg');\n                //     setLoaded(true);\n                //     speakText('Welcome to BrowserBrains');\n                //   }\n                // }}\n            >\n                <ExpandableChatHeader className=\"bb:flex-col bb:text-center bb:justify-center\">\n                    <h1 className=\"bb:text-xl bb:font-semibold\">{headerText}</h1>\n                </ExpandableChatHeader>\n                <ExpandableChatBody>\n                    <ChatMessageList>\n                        {/* Initial Message */}\n                        {messages.length === 0 &&\n                            (welcomeMessage || (\n                                <div className=\"bb:flex-1\">\n                                    <p className=\"bb:text-center\">Welcome to BrowserBrains - Local Chat!</p>\n                                    <br />\n                                    <p className=\"\">I can help you with question like:</p>\n                                    <br />\n                                    <ul className=\"bb:list-disc bb:list-inside\">\n                                        <li>\n                                            If it takes 5 machines 5 minutes to make 5 widgets, how long would it take\n                                            100 machines to make 100 widgets?\n                                        </li>\n                                        <li>What is the capital of France?</li>\n                                        <li>What is the population of the moon?</li>\n                                    </ul>\n                                </div>\n                            ))}\n\n                        {/* Messages */}\n                        {messages?.map((message) => (\n                            <ChatBubble\n                                key={message.id || `message-${message.role}-${Math.random()}`}\n                                variant={message.role === \"user\" ? \"sent\" : \"received\"}\n                            >\n                                <ChatBubbleAvatar src=\"\" fallback={message.role === \"user\" ? \"🧑‍🦲\" : \"🤖\"} />\n\n                                <ChatBubbleMessage>\n                                    {/* {message.role === 'assistant' &&\n                  !hasFinalAnswer(message.content) ? (\n                    <div className=\"bb:flex bb:items-center bb:justify-center\">\n                      <Brain className=\"bb:h-8 bb:w-8 bb:text-primary bb:animate-pulse\" />\n                    </div>\n                  ) : message.role === 'assistant' ? (\n                    renderMessageContent(extractFinalAnswer(message.content))\n                  ) : (\n                    renderMessageContent(message.content)\n                  )} */}\n\n                                    {renderMessageContent(message.content)}\n                                </ChatBubbleMessage>\n                            </ChatBubble>\n                        ))}\n                    </ChatMessageList>\n                </ExpandableChatBody>\n                <ExpandableChatFooter>\n                    <ChatInput\n                        value={input}\n                        onChange={(e: ChangeEvent<HTMLTextAreaElement>) => {\n                            const target = e.target as HTMLTextAreaElement;\n                            setInput(target.value);\n                        }}\n                        onKeyDown={(e: KeyboardEvent<HTMLTextAreaElement>) => {\n                            const target = e.target as HTMLTextAreaElement;\n                            if (target.value.length > 0 && !isRunning && e.key === \"Enter\" && !e.shiftKey) {\n                                e.preventDefault();\n                                onEnter();\n                            }\n                        }}\n                    />\n                    <Button\n                        className=\"bb:absolute bb:bottom-[24px] bb:right-[24px]\"\n                        type=\"submit\"\n                        size=\"icon\"\n                        onClick={() => {\n                            if (input.length > 0) {\n                                onEnter();\n                            }\n                        }}\n                    >\n                        <Send className=\"bb:size-4\" />\n                    </Button>\n                </ExpandableChatFooter>\n                <p className=\"bb:absolute bb:bottom-[0px] bb:w-full bb:min-h-4 bb:text-center bb:text-gray-400 bb:text-xs bb:m-0\">\n                    {tps && messages.length > 0 && numTokens !== null && (\n                        <>\n                            {!isRunning && (\n                                <span>\n                                    {numTokens} tokens in {(numTokens / tps).toFixed(2)} seconds&nbsp;&#40;\n                                </span>\n                            )}\n                            {\n                                <span className=\"bb:mr-1 bb:text-center bb:font-medium\">\n                                    {tps.toFixed(2)} tks/second&#41;\n                                </span>\n                            }\n                        </>\n                    )}\n                </p>\n            </ExpandableChat>\n        </>\n    );\n};\n"],"names":["cn","inputs","twMerge","clsx","buttonVariants","cva","Button","React","className","variant","size","asChild","props","ref","Comp","Slot","jsx","Avatar","AvatarPrimitive","AvatarImage","AvatarFallback","MessageLoading","jsxs","chatBubbleVariant","ChatBubble","layout","children","child","ChatBubbleAvatar","src","fallback","chatBubbleMessageVariants","ChatBubbleMessage","isLoading","ChatBubbleActionWrapper","Textarea","ChatInput","useAutoScroll","options","offset","smooth","content","scrollRef","useRef","lastContentHeight","userHasScrolled","scrollState","setScrollState","useState","checkIsAtBottom","useCallback","element","scrollTop","scrollHeight","clientHeight","scrollToBottom","instant","targetScrollTop","handleScroll","atBottom","prev","useEffect","scrollElement","currentHeight","resizeObserver","disableAutoScroll","ChatMessageList","_ref","isAtBottom","ArrowDown","chatConfig","ExpandableChat","position","icon","progressPercentage","onToggle","isOpen","setIsOpen","chatRef","toggleChat","newIsOpen","X","ExpandableChatToggle","ExpandableChatHeader","ExpandableChatBody","ExpandableChatFooter","clampedProgress","MessageCircle","Progress","value","ProgressPrimitive","FINAL_ANSWER_PATTERN","DEFAULT_WORKER_PATH","formatFileSize","bytes","generateId","calculateProgress","progressItems","totalProgress","sum","item","totalSize","renderMessageContent","part","idx","key","Markdown","remarkGfm","loadContextFiles","filePaths","path","response","error","loadContext","systemPrompt","context","DEFAULT_SYSTEM_PROMPT","LocalChat","workerFallbackPath","headerText","contextFiles","modelName","welcomeMessage","workerLLMRef","messages","setMessages","input","setInput","status","setStatus","setError","loadingMessage","setLoadingMessage","setProgressItems","isRunning","setIsRunning","tps","setTps","numTokens","setNumTokens","currentSentenceBufferRef","loadedSystemPrompt","setLoadedSystemPrompt","onEnter","systemPromptWithContext","fallbackPath","fallbackName","fallbackError","worker","onMessageReceived","e","output","state","cloned","last","data","sentenceEndRegex","sentenceToSpeak","hasAutoSpoken","onErrorReceived","x","_a","lastMessages","speed","setSpeed","voices","setVoices","selectedVoice","setSelectedVoice","isTTSProcessing","setIsTTSProcessing","audioChunkQueue","setAudioChunkQueue","isAudioPlaying","setIsAudioPlaying","audioRef","currentAudioUrlRef","playNextChunk","nextChunk","url","err","Fragment","file","progress","total","i","message","target","Send"],"mappings":"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"}