{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "firebase-thinking-model",
  "type": "registry:block",
  "title": "Firebase Thinking Model",
  "description": "A chat interface showcasing AI reasoning with Firebase Gemini thinking model",
  "dependencies": [
    "@ai-sdk/react",
    "@mui/material",
    "lucide-react",
    "sonner",
    "@emotion/react",
    "@emotion/styled"
  ],
  "registryDependencies": [
    "https://www.mui-treasury.com/r/ai-actions.json",
    "https://www.mui-treasury.com/r/ai-conversation.json",
    "https://www.mui-treasury.com/r/ai-loader.json",
    "https://www.mui-treasury.com/r/ai-message.json",
    "https://www.mui-treasury.com/r/ai-prompt-input.json",
    "https://www.mui-treasury.com/r/ai-reasoning.json",
    "https://www.mui-treasury.com/r/ai-response.json",
    "https://www.mui-treasury.com/r/ai-suggestion.json",
    "https://www.mui-treasury.com/r/firebase-chat-transport.json"
  ],
  "files": [
    {
      "path": "firebase/firebase-thinking-model/firebase-thinking-model.tsx",
      "target": "src/mui-treasury/firebase/firebase-thinking-model/firebase-thinking-model.tsx",
      "content": "'use client';\n\nimport React, { useState } from 'react';\n\nimport { UIMessage, useChat } from '@ai-sdk/react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Typography from '@mui/material/Typography';\nimport { Bot, CopyIcon, RefreshCwIcon, SquareIcon } from 'lucide-react';\nimport { toast } from 'sonner';\n\nimport { app } from '@/lib/firebase-setup';\nimport { Action, Actions } from '@/registry/components/ai-actions/ai-actions';\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from '@/registry/components/ai-conversation/ai-conversation';\nimport { Loader } from '@/registry/components/ai-loader/ai-loader';\nimport {\n  Message,\n  MessageAvatar,\n  MessageContent,\n} from '@/registry/components/ai-message/ai-message';\nimport {\n  PromptInput,\n  PromptInputBody,\n  type PromptInputMessage,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputToolbar,\n} from '@/registry/components/ai-prompt-input/ai-prompt-input';\nimport {\n  Reasoning,\n  ReasoningContent,\n  ReasoningTrigger,\n} from '@/registry/components/ai-reasoning/ai-reasoning';\nimport { Response } from '@/registry/components/ai-response/ai-response';\nimport {\n  Suggestion,\n  Suggestions,\n} from '@/registry/components/ai-suggestion/ai-suggestion';\nimport { FirebaseChatTransport } from '@/registry/firebase/firebase-chat-transport';\n\nconst SUGGESTED_PROMPTS = [\n  'What is the meaning of life?',\n  'Explain quantum computing in simple terms',\n  'How do black holes work?',\n];\n\nexport default function FirebaseThinkingModel() {\n  const [inputValue, setInputValue] = useState('');\n\n  const transport = React.useMemo(\n    () =>\n      app\n        ? new FirebaseChatTransport({\n            firebaseApp: app,\n            modelParams: {\n              model: 'gemini-2.5-flash',\n              systemInstruction: `You are a helpful AI assistant that thinks through problems step by step.\nAlways respond in a concise and clear manner.\nFormat responses in Markdown unless asked otherwise.\nIf you don't know the answer, say so honestly.`,\n              generationConfig: {\n                thinkingConfig: {\n                  includeThoughts: true,\n                  thinkingBudget: 2048,\n                },\n              },\n            },\n          })\n        : null,\n    [],\n  );\n\n  const { messages, status, error, sendMessage, stop, regenerate } =\n    useChat<UIMessage>({\n      id: 'firebase-thinking-model',\n      transport: transport!,\n    });\n\n  const handleSubmit = (\n    message: PromptInputMessage,\n    event: React.FormEvent,\n  ) => {\n    event.preventDefault();\n    if (message.text?.trim()) {\n      sendMessage({ text: message.text });\n      setInputValue('');\n    }\n  };\n\n  const handleSuggestionClick = (suggestion: string) => {\n    setInputValue(suggestion);\n  };\n\n  const handleCopy = async (text: string) => {\n    try {\n      await navigator.clipboard.writeText(text);\n      toast.success('Copied to clipboard');\n    } catch {\n      toast.error('Failed to copy to clipboard');\n    }\n  };\n\n  const showSuggestions = messages.length === 0 && status === 'ready';\n\n  if (!app) {\n    return (\n      <Box\n        sx={{\n          height: '100%',\n          display: 'flex',\n          alignItems: 'center',\n          justifyContent: 'center',\n          p: 2,\n        }}\n      >\n        <Typography\n          sx={{\n            color: 'text.secondary',\n          }}\n        >\n          Firebase not configured. Please set up Firebase config at the top of\n          the page.\n        </Typography>\n      </Box>\n    );\n  }\n\n  return (\n    <Box\n      sx={{\n        height: '100%',\n        width: '100%',\n        display: 'flex',\n        flexDirection: 'column',\n        maxWidth: 768,\n        mx: 'auto',\n      }}\n    >\n      <Box\n        sx={{\n          flex: 1,\n          display: 'flex',\n          flexDirection: 'column',\n          overflow: 'hidden',\n        }}\n      >\n        <Conversation>\n          <ConversationContent>\n            {messages.length === 0 && status === 'ready' ? (\n              <Box\n                sx={{\n                  flex: 1,\n                  display: 'flex',\n                  alignItems: 'center',\n                  justifyContent: 'center',\n                  flexDirection: 'column',\n                  gap: 2,\n                  color: 'text.tertiary',\n                }}\n              >\n                <Bot size={48} />\n                <Typography variant=\"h4\" sx={{ fontWeight: 500 }}>\n                  Thinking Model Demo\n                </Typography>\n                <Typography\n                  sx={{\n                    color: 'text.secondary',\n                  }}\n                >\n                  Ask a question and watch the AI think through it\n                </Typography>\n              </Box>\n            ) : (\n              <Box sx={{ display: 'flex', flexDirection: 'column' }}>\n                {messages.map((message) => {\n                  const messageText = message.parts\n                    ?.filter((part) => part.type === 'text')\n                    .map((part) => part.text)\n                    .join('\\n');\n\n                  return (\n                    <Message key={message.id} from={message.role}>\n                      <MessageAvatar\n                        name={message.role === 'user' ? 'You' : 'AI'}\n                      />\n                      <MessageContent variant=\"flat\">\n                        {message.parts?.map((part, index) => {\n                          if (part.type === 'reasoning') {\n                            const reasoningPart = part as {\n                              type: 'reasoning';\n                              text: string;\n                              state?: 'streaming' | 'done';\n                            };\n                            return (\n                              <Reasoning\n                                key={index}\n                                isStreaming={\n                                  reasoningPart.state === 'streaming'\n                                }\n                              >\n                                <ReasoningTrigger />\n                                <ReasoningContent>\n                                  {reasoningPart.text}\n                                </ReasoningContent>\n                              </Reasoning>\n                            );\n                          }\n                          if (part.type === 'text') {\n                            if (\n                              message.role === 'assistant' &&\n                              part.state !== 'done' &&\n                              !part.text\n                            ) {\n                              return null;\n                            }\n                            return message.role === 'assistant' ? (\n                              <Response key={index}>{part.text}</Response>\n                            ) : (\n                              <Box key={index}>{part.text}</Box>\n                            );\n                          }\n                          return null;\n                        })}\n                        {message.role === 'assistant' && messageText && (\n                          <Actions>\n                            <Action\n                              tooltip=\"Copy\"\n                              onClick={() => handleCopy(messageText)}\n                            >\n                              <CopyIcon size={16} />\n                            </Action>\n                            <Action\n                              tooltip=\"Regenerate\"\n                              onClick={() => regenerate()}\n                            >\n                              <RefreshCwIcon size={16} />\n                            </Action>\n                          </Actions>\n                        )}\n                      </MessageContent>\n                    </Message>\n                  );\n                })}\n\n                {status === 'submitted' && (\n                  <Message from=\"assistant\">\n                    <MessageAvatar name=\"AI\" />\n                    <MessageContent variant=\"flat\">\n                      <Box\n                        sx={{ display: 'flex', alignItems: 'center', gap: 1 }}\n                      >\n                        <CircularProgress size={20} />\n                        <Typography\n                          sx={{\n                            color: 'text.secondary',\n                          }}\n                        >\n                          Thinking...\n                        </Typography>\n                      </Box>\n                    </MessageContent>\n                  </Message>\n                )}\n\n                {error && (\n                  <Message from=\"assistant\">\n                    <MessageAvatar name=\"AI\" />\n                    <MessageContent variant=\"flat\">\n                      <Typography sx={{ color: 'error.text' }}>\n                        {error.message ||\n                          'An error occurred. Please try again.'}\n                      </Typography>\n                    </MessageContent>\n                  </Message>\n                )}\n              </Box>\n            )}\n            {status === 'streaming' && (\n              <Box\n                sx={{\n                  display: 'flex',\n                  alignItems: 'center',\n                  gap: 1,\n                  mt: 1,\n                }}\n              >\n                <Loader />\n                <Typography\n                  sx={{\n                    color: 'text.secondary',\n                  }}\n                >\n                  Streaming response...\n                </Typography>\n              </Box>\n            )}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n      </Box>\n      {showSuggestions && (\n        <Box sx={{ mb: 2 }}>\n          <Suggestions>\n            {SUGGESTED_PROMPTS.map((prompt, index) => (\n              <Suggestion\n                key={index}\n                suggestion={prompt}\n                onClick={handleSuggestionClick}\n              />\n            ))}\n          </Suggestions>\n        </Box>\n      )}\n      <PromptInput onSubmit={handleSubmit}>\n        <PromptInputBody>\n          <PromptInputTextarea\n            placeholder=\"Ask something that requires deep thinking...\"\n            value={inputValue}\n            onChange={(e) => setInputValue(e.target.value)}\n            disabled={status === 'submitted' || error != null}\n          />\n        </PromptInputBody>\n        <PromptInputToolbar>\n          {status === 'streaming' || status === 'submitted' ? (\n            <Button\n              variant=\"outlined\"\n              onClick={(e) => {\n                e.preventDefault();\n                stop();\n              }}\n              sx={{ minWidth: 'auto', borderRadius: 2, p: 1 }}\n            >\n              <SquareIcon size={16} />\n            </Button>\n          ) : (\n            <PromptInputSubmit\n              status={status as 'ready' | 'submitted' | 'streaming' | 'error'}\n              disabled={error != null}\n            />\n          )}\n        </PromptInputToolbar>\n      </PromptInput>\n    </Box>\n  );\n}\n",
      "type": "registry:item"
    },
    {
      "path": "firebase/firebase-thinking-model/index.ts",
      "target": "src/mui-treasury/firebase/firebase-thinking-model/index.ts",
      "content": "export * from './firebase-thinking-model';\nexport { default as FirebaseThinkingModel } from './firebase-thinking-model';\n",
      "type": "registry:item"
    }
  ],
  "meta": {
    "category": "ai",
    "subcategory": "firebase",
    "previewClassName": "h-[600px!important]"
  }
}