├── README.md ├── docker └── docker-compose.yaml ├── frontend ├── .gitignore ├── README.md ├── app │ ├── api │ │ └── chat │ │ │ └── route.ts │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── components.json ├── components │ ├── assistant-ui │ │ ├── markdown-text.tsx │ │ ├── thread-list.tsx │ │ ├── thread.tsx │ │ └── tooltip-icon-button.tsx │ └── ui │ │ ├── avatar.tsx │ │ ├── button.tsx │ │ └── tooltip.tsx ├── eslint.config.mjs ├── lib │ └── utils.ts ├── next.config.ts ├── package.json ├── pnpm-lock.yaml ├── postcss.config.mjs ├── tailwind.config.ts └── tsconfig.json └── worker ├── .gitignore ├── drizzle.config.ts ├── package.json ├── pnpm-lock.yaml ├── src ├── db │ └── schema.ts ├── index.ts └── util │ └── splitByLineStream.ts ├── tsconfig.json └── wrangler.jsonc /README.md: -------------------------------------------------------------------------------- 1 | # assistant-ui + ElectricSQL 2 | 3 | Resumable AI streams, built with: 4 | 5 | - assistant-ui 6 | - ElectricSQL 7 | - PostgreSQL 8 | - Cloudflare Workers 9 | - Drizzle ORM 10 | 11 | ## Getting started 12 | 13 | Start docker 14 | 15 | ```sh 16 | cd docker-compose && docker compose up 17 | ``` 18 | 19 | Start backend 20 | 21 | ```sh 22 | cd worker && pnpm i && pnpm drizzle-kit push && pnpm run dev 23 | ``` 24 | 25 | Start frontend 26 | 27 | ```sh 28 | cd frontend && pnpm i && pnpm run dev 29 | ``` 30 | -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | postgres: 3 | image: postgres:17-alpine 4 | environment: 5 | POSTGRES_DB: electric 6 | POSTGRES_USER: postgres 7 | POSTGRES_PASSWORD: password 8 | ports: 9 | - 54321:5432 10 | tmpfs: 11 | - /var/lib/postgresql/data 12 | - /tmp 13 | command: 14 | - -c 15 | - listen_addresses=* 16 | - -c 17 | - wal_level=logical 18 | 19 | electric: 20 | image: electricsql/electric 21 | environment: 22 | DATABASE_URL: postgresql://postgres:password@postgres:5432/electric?sslmode=disable 23 | ports: 24 | - "3000:3000" 25 | depends_on: 26 | - postgres 27 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | # env files (can opt-in for commiting if needed) 33 | .env* 34 | 35 | # vercel 36 | .vercel 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | next-env.d.ts 41 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | This is the [assistant-ui](https://github.com/Yonom/assistant-ui) starter project. 2 | 3 | ## Getting Started 4 | 5 | First, add your OpenAI API key to `.env.local` file: 6 | 7 | ``` 8 | OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 9 | ``` 10 | 11 | Then, run the development server: 12 | 13 | ```bash 14 | npm run dev 15 | # or 16 | yarn dev 17 | # or 18 | pnpm dev 19 | # or 20 | bun dev 21 | ``` 22 | 23 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 24 | 25 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 26 | -------------------------------------------------------------------------------- /frontend/app/api/chat/route.ts: -------------------------------------------------------------------------------- 1 | import { openai } from "@ai-sdk/openai"; 2 | import { jsonSchema, streamText } from "ai"; 3 | 4 | export const maxDuration = 30; 5 | 6 | export async function POST(req: Request) { 7 | const { messages, system, tools } = await req.json(); 8 | 9 | const result = streamText({ 10 | model: openai("gpt-4o"), 11 | messages, 12 | system, 13 | tools: Object.fromEntries( 14 | Object.keys(tools).map((name) => [ 15 | name, 16 | { ...tools[name], parameters: jsonSchema(tools[name].parameters) }, 17 | ]) 18 | ), 19 | }); 20 | 21 | return result.toDataStreamResponse(); 22 | } 23 | -------------------------------------------------------------------------------- /frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/assistant-ui/assistant-ui-electric/0b681604535bbb5bba859ebf16e24c8475b8e5b4/frontend/app/favicon.ico -------------------------------------------------------------------------------- /frontend/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | @layer base { 5 | :root { 6 | --background: 0 0% 100%; 7 | --foreground: 240 10% 3.9%; 8 | --card: 0 0% 100%; 9 | --card-foreground: 240 10% 3.9%; 10 | --popover: 0 0% 100%; 11 | --popover-foreground: 240 10% 3.9%; 12 | --primary: 240 5.9% 10%; 13 | --primary-foreground: 0 0% 98%; 14 | --secondary: 240 4.8% 95.9%; 15 | --secondary-foreground: 240 5.9% 10%; 16 | --muted: 240 4.8% 95.9%; 17 | --muted-foreground: 240 3.8% 46.1%; 18 | --accent: 240 4.8% 95.9%; 19 | --accent-foreground: 240 5.9% 10%; 20 | --destructive: 0 84.2% 60.2%; 21 | --destructive-foreground: 0 0% 98%; 22 | --border: 240 5.9% 90%; 23 | --input: 240 5.9% 90%; 24 | --ring: 240 10% 3.9%; 25 | --chart-1: 12 76% 61%; 26 | --chart-2: 173 58% 39%; 27 | --chart-3: 197 37% 24%; 28 | --chart-4: 43 74% 66%; 29 | --chart-5: 27 87% 67%; 30 | --radius: 0.5rem; 31 | } 32 | .dark { 33 | --background: 240 10% 3.9%; 34 | --foreground: 0 0% 98%; 35 | --card: 240 10% 3.9%; 36 | --card-foreground: 0 0% 98%; 37 | --popover: 240 10% 3.9%; 38 | --popover-foreground: 0 0% 98%; 39 | --primary: 0 0% 98%; 40 | --primary-foreground: 240 5.9% 10%; 41 | --secondary: 240 3.7% 15.9%; 42 | --secondary-foreground: 0 0% 98%; 43 | --muted: 240 3.7% 15.9%; 44 | --muted-foreground: 240 5% 64.9%; 45 | --accent: 240 3.7% 15.9%; 46 | --accent-foreground: 0 0% 98%; 47 | --destructive: 0 62.8% 30.6%; 48 | --destructive-foreground: 0 0% 98%; 49 | --border: 240 3.7% 15.9%; 50 | --input: 240 3.7% 15.9%; 51 | --ring: 240 4.9% 83.9%; 52 | --chart-1: 220 70% 50%; 53 | --chart-2: 160 60% 45%; 54 | --chart-3: 30 80% 55%; 55 | --chart-4: 280 65% 60%; 56 | --chart-5: 340 75% 55%; 57 | } 58 | } 59 | @layer base { 60 | * { 61 | @apply border-border; 62 | } 63 | body { 64 | @apply bg-background text-foreground; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /frontend/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Geist, Geist_Mono } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const geistSans = Geist({ 6 | variable: "--font-geist-sans", 7 | subsets: ["latin"], 8 | }); 9 | 10 | const geistMono = Geist_Mono({ 11 | variable: "--font-geist-mono", 12 | subsets: ["latin"], 13 | }); 14 | 15 | 16 | export const metadata: Metadata = { 17 | title: "assistant-ui App", 18 | description: "Generated by create-assistant-ui", 19 | }; 20 | 21 | export default function RootLayout({ 22 | children, 23 | }: Readonly<{ 24 | children: React.ReactNode; 25 | }>) { 26 | return ( 27 | 28 | 31 | {children} 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /frontend/app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Thread } from "@/components/assistant-ui/thread"; 3 | import { 4 | AssistantRuntimeProvider, 5 | TextContentPart, 6 | unstable_createMessageConverter, 7 | useExternalStoreRuntime, 8 | } from "@assistant-ui/react"; 9 | import { useMemo, useState } from "react"; 10 | import { parseDataStreamPart } from "ai"; 11 | import { useShape } from "@electric-sql/react"; 12 | 13 | const THREAD_ID = "TEST_THREAD_ID"; 14 | 15 | type Message = { 16 | role: "user" | "assistant"; 17 | content: [{ type: "text"; text: string }]; 18 | }; 19 | 20 | const { useThreadMessages } = unstable_createMessageConverter((m) => { 21 | return m; 22 | }); 23 | 24 | type ThreadStreamColumn = { 25 | thread_id: string; 26 | sequence: number; 27 | payload: string; 28 | }; 29 | 30 | type PayloadValue = 31 | | { 32 | type: "message"; 33 | message: Message; 34 | } 35 | | { 36 | type: "ai-chunk"; 37 | chunk: string; 38 | }; 39 | 40 | const messagesFromChunks = (chunks: ThreadStreamColumn[]) => { 41 | const messages: Message[] = []; 42 | 43 | for (const chunk of chunks) { 44 | const payload = JSON.parse(chunk.payload) as PayloadValue; 45 | if (payload.type === "message") { 46 | messages.push(payload.message); 47 | } else if (payload.type === "ai-chunk") { 48 | const parsedChunk = parseDataStreamPart(payload.chunk); 49 | if (parsedChunk.type === "text") { 50 | const lastMessage = messages.at(-1); 51 | if (lastMessage?.role !== "assistant") { 52 | messages.push({ 53 | role: "assistant", 54 | content: [{ type: "text", text: parsedChunk.value }], 55 | }); 56 | } else { 57 | lastMessage.content[0].text += parsedChunk.value; 58 | } 59 | } 60 | } 61 | } 62 | 63 | return messages; 64 | }; 65 | 66 | export default function Home() { 67 | const { data } = useShape({ 68 | url: "http://localhost:3000/v1/shape", 69 | params: { 70 | table: "threads", 71 | columns: ["thread_id", "sequence", "payload"], 72 | where: `thread_id = '${THREAD_ID}'`, 73 | }, 74 | }); 75 | 76 | const messages = useMemo(() => messagesFromChunks(data), [data]); 77 | 78 | const [isRunning, setIsRunning] = useState(false); 79 | 80 | const threadMessages = useThreadMessages(messages, isRunning); 81 | const runtime = useExternalStoreRuntime({ 82 | isRunning, 83 | messages: threadMessages, 84 | onNew: async (m) => { 85 | const newMessage: Message = { 86 | role: "user", 87 | content: [ 88 | { type: "text", text: (m.content[0] as TextContentPart).text }, 89 | ], 90 | }; 91 | const newMessages = [...messages, newMessage]; 92 | 93 | setIsRunning(true); 94 | try { 95 | await fetch("http://localhost:8787/api/chat", { 96 | method: "POST", 97 | body: JSON.stringify({ 98 | thread_id: THREAD_ID, 99 | messages: newMessages, 100 | }), 101 | }); 102 | } finally { 103 | setIsRunning(false); 104 | } 105 | }, 106 | }); 107 | 108 | return ( 109 | 110 |
111 | 112 |
113 |
114 | ); 115 | } 116 | -------------------------------------------------------------------------------- /frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /frontend/components/assistant-ui/markdown-text.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import "@assistant-ui/react-markdown/styles/dot.css"; 4 | 5 | import { 6 | CodeHeaderProps, 7 | MarkdownTextPrimitive, 8 | unstable_memoizeMarkdownComponents as memoizeMarkdownComponents, 9 | useIsMarkdownCodeBlock, 10 | } from "@assistant-ui/react-markdown"; 11 | import remarkGfm from "remark-gfm"; 12 | import { FC, memo, useState } from "react"; 13 | import { CheckIcon, CopyIcon } from "lucide-react"; 14 | 15 | import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button"; 16 | import { cn } from "@/lib/utils"; 17 | 18 | const MarkdownTextImpl = () => { 19 | return ( 20 | 25 | ); 26 | }; 27 | 28 | export const MarkdownText = memo(MarkdownTextImpl); 29 | 30 | const CodeHeader: FC = ({ language, code }) => { 31 | const { isCopied, copyToClipboard } = useCopyToClipboard(); 32 | const onCopy = () => { 33 | if (!code || isCopied) return; 34 | copyToClipboard(code); 35 | }; 36 | 37 | return ( 38 |
39 | {language} 40 | 41 | {!isCopied && } 42 | {isCopied && } 43 | 44 |
45 | ); 46 | }; 47 | 48 | const useCopyToClipboard = ({ 49 | copiedDuration = 3000, 50 | }: { 51 | copiedDuration?: number; 52 | } = {}) => { 53 | const [isCopied, setIsCopied] = useState(false); 54 | 55 | const copyToClipboard = (value: string) => { 56 | if (!value) return; 57 | 58 | navigator.clipboard.writeText(value).then(() => { 59 | setIsCopied(true); 60 | setTimeout(() => setIsCopied(false), copiedDuration); 61 | }); 62 | }; 63 | 64 | return { isCopied, copyToClipboard }; 65 | }; 66 | 67 | const defaultComponents = memoizeMarkdownComponents({ 68 | h1: ({ className, ...props }) => ( 69 |

70 | ), 71 | h2: ({ className, ...props }) => ( 72 |

73 | ), 74 | h3: ({ className, ...props }) => ( 75 |

76 | ), 77 | h4: ({ className, ...props }) => ( 78 |

79 | ), 80 | h5: ({ className, ...props }) => ( 81 |

82 | ), 83 | h6: ({ className, ...props }) => ( 84 |
85 | ), 86 | p: ({ className, ...props }) => ( 87 |

88 | ), 89 | a: ({ className, ...props }) => ( 90 | 91 | ), 92 | blockquote: ({ className, ...props }) => ( 93 |

94 | ), 95 | ul: ({ className, ...props }) => ( 96 |
    li]:mt-2", className)} {...props} /> 97 | ), 98 | ol: ({ className, ...props }) => ( 99 |
      li]:mt-2", className)} {...props} /> 100 | ), 101 | hr: ({ className, ...props }) => ( 102 |
      103 | ), 104 | table: ({ className, ...props }) => ( 105 | 106 | ), 107 | th: ({ className, ...props }) => ( 108 | td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg", className)} {...props} /> 115 | ), 116 | sup: ({ className, ...props }) => ( 117 | a]:text-xs [&>a]:no-underline", className)} {...props} /> 118 | ), 119 | pre: ({ className, ...props }) => ( 120 |
      121 |   ),
      122 |   code: function Code({ className, ...props }) {
      123 |     const isCodeBlock = useIsMarkdownCodeBlock();
      124 |     return (
      125 |       
      129 |     );
      130 |   },
      131 |   CodeHeader,
      132 | });
      133 | 
      
      
      --------------------------------------------------------------------------------
      /frontend/components/assistant-ui/thread-list.tsx:
      --------------------------------------------------------------------------------
       1 | import type { FC } from "react";
       2 | import {
       3 |   ThreadListItemPrimitive,
       4 |   ThreadListPrimitive,
       5 | } from "@assistant-ui/react";
       6 | import { ArchiveIcon, PlusIcon } from "lucide-react";
       7 | 
       8 | import { Button } from "@/components/ui/button";
       9 | import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
      10 | 
      11 | export const ThreadList: FC = () => {
      12 |   return (
      13 |     
      14 |       
      15 |       
      16 |     
      17 |   );
      18 | };
      19 | 
      20 | const ThreadListNew: FC = () => {
      21 |   return (
      22 |     
      23 |       
      27 |     
      28 |   );
      29 | };
      30 | 
      31 | const ThreadListItems: FC = () => {
      32 |   return ;
      33 | };
      34 | 
      35 | const ThreadListItem: FC = () => {
      36 |   return (
      37 |     
      38 |       
      39 |         
      40 |       
      41 |       
      42 |     
      43 |   );
      44 | };
      45 | 
      46 | const ThreadListItemTitle: FC = () => {
      47 |   return (
      48 |     

      49 | 50 |

      51 | ); 52 | }; 53 | 54 | const ThreadListItemArchive: FC = () => { 55 | return ( 56 | 57 | 62 | 63 | 64 | 65 | ); 66 | }; 67 | -------------------------------------------------------------------------------- /frontend/components/assistant-ui/thread.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | ActionBarPrimitive, 3 | BranchPickerPrimitive, 4 | ComposerPrimitive, 5 | MessagePrimitive, 6 | ThreadPrimitive, 7 | } from "@assistant-ui/react"; 8 | import type { FC } from "react"; 9 | import { 10 | ArrowDownIcon, 11 | CheckIcon, 12 | ChevronLeftIcon, 13 | ChevronRightIcon, 14 | CopyIcon, 15 | PencilIcon, 16 | RefreshCwIcon, 17 | SendHorizontalIcon, 18 | } from "lucide-react"; 19 | import { cn } from "@/lib/utils"; 20 | 21 | import { Button } from "@/components/ui/button"; 22 | import { MarkdownText } from "@/components/assistant-ui/markdown-text"; 23 | import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button"; 24 | 25 | export const Thread: FC = () => { 26 | return ( 27 | 33 | 34 | 35 | 36 | 43 | 44 | 45 |
      46 | 47 | 48 |
      49 | 50 | 51 |
      52 | 53 | 54 | ); 55 | }; 56 | 57 | const ThreadScrollToBottom: FC = () => { 58 | return ( 59 | 60 | 65 | 66 | 67 | 68 | ); 69 | }; 70 | 71 | const ThreadWelcome: FC = () => { 72 | return ( 73 | 74 |
      75 |
      76 |

      How can I help you today?

      77 |
      78 | 79 |
      80 |
      81 | ); 82 | }; 83 | 84 | const ThreadWelcomeSuggestions: FC = () => { 85 | return ( 86 |
      87 | 93 | 94 | What is the weather in Tokyo? 95 | 96 | 97 | 103 | 104 | What is assistant-ui? 105 | 106 | 107 |
      108 | ); 109 | }; 110 | 111 | const Composer: FC = () => { 112 | return ( 113 | 114 | 120 | 121 | 122 | ); 123 | }; 124 | 125 | const ComposerAction: FC = () => { 126 | return ( 127 | <> 128 | 129 | 130 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 146 | 147 | 148 | 149 | 150 | 151 | ); 152 | }; 153 | 154 | const UserMessage: FC = () => { 155 | return ( 156 | 157 | 158 | 159 |
      160 | 161 |
      162 | 163 | 164 |
      165 | ); 166 | }; 167 | 168 | const UserActionBar: FC = () => { 169 | return ( 170 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | ); 182 | }; 183 | 184 | const EditComposer: FC = () => { 185 | return ( 186 | 187 | 188 | 189 |
      190 | 191 | 192 | 193 | 194 | 195 | 196 |
      197 |
      198 | ); 199 | }; 200 | 201 | const AssistantMessage: FC = () => { 202 | return ( 203 | 204 |
      205 | 206 |
      207 | 208 | 209 | 210 | 211 |
      212 | ); 213 | }; 214 | 215 | const AssistantActionBar: FC = () => { 216 | return ( 217 | 223 | {/* 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | */} 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | ); 254 | }; 255 | 256 | const BranchPicker: FC = ({ 257 | className, 258 | ...rest 259 | }) => { 260 | return ( 261 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | / 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | ); 284 | }; 285 | 286 | const CircleStopIcon = () => { 287 | return ( 288 | 295 | 296 | 297 | ); 298 | }; 299 | -------------------------------------------------------------------------------- /frontend/components/assistant-ui/tooltip-icon-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ComponentPropsWithoutRef, forwardRef } from "react"; 4 | 5 | import { 6 | Tooltip, 7 | TooltipContent, 8 | TooltipProvider, 9 | TooltipTrigger, 10 | } from "@/components/ui/tooltip"; 11 | import { Button } from "@/components/ui/button"; 12 | import { cn } from "@/lib/utils"; 13 | 14 | export type TooltipIconButtonProps = ComponentPropsWithoutRef & { 15 | tooltip: string; 16 | side?: "top" | "bottom" | "left" | "right"; 17 | }; 18 | 19 | export const TooltipIconButton = forwardRef< 20 | HTMLButtonElement, 21 | TooltipIconButtonProps 22 | >(({ children, tooltip, side = "bottom", className, ...rest }, ref) => { 23 | return ( 24 | 25 | 26 | 27 | 37 | 38 | {tooltip} 39 | 40 | 41 | ); 42 | }); 43 | 44 | TooltipIconButton.displayName = "TooltipIconButton"; 45 | -------------------------------------------------------------------------------- /frontend/components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as AvatarPrimitive from "@radix-ui/react-avatar" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Avatar = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | )) 21 | Avatar.displayName = AvatarPrimitive.Root.displayName 22 | 23 | const AvatarImage = React.forwardRef< 24 | React.ElementRef, 25 | React.ComponentPropsWithoutRef 26 | >(({ className, ...props }, ref) => ( 27 | 32 | )) 33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName 34 | 35 | const AvatarFallback = React.forwardRef< 36 | React.ElementRef, 37 | React.ComponentPropsWithoutRef 38 | >(({ className, ...props }, ref) => ( 39 | 47 | )) 48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName 49 | 50 | export { Avatar, AvatarImage, AvatarFallback } 51 | -------------------------------------------------------------------------------- /frontend/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "bg-primary text-primary-foreground shadow hover:bg-primary/90", 14 | destructive: 15 | "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", 16 | outline: 17 | "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", 18 | secondary: 19 | "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", 20 | ghost: "hover:bg-accent hover:text-accent-foreground", 21 | link: "text-primary underline-offset-4 hover:underline", 22 | }, 23 | size: { 24 | default: "h-9 px-4 py-2", 25 | sm: "h-8 rounded-md px-3 text-xs", 26 | lg: "h-10 rounded-md px-8", 27 | icon: "h-9 w-9", 28 | }, 29 | }, 30 | defaultVariants: { 31 | variant: "default", 32 | size: "default", 33 | }, 34 | } 35 | ) 36 | 37 | export interface ButtonProps 38 | extends React.ButtonHTMLAttributes, 39 | VariantProps { 40 | asChild?: boolean 41 | } 42 | 43 | const Button = React.forwardRef( 44 | ({ className, variant, size, asChild = false, ...props }, ref) => { 45 | const Comp = asChild ? Slot : "button" 46 | return ( 47 | 52 | ) 53 | } 54 | ) 55 | Button.displayName = "Button" 56 | 57 | export { Button, buttonVariants } 58 | -------------------------------------------------------------------------------- /frontend/components/ui/tooltip.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const TooltipProvider = TooltipPrimitive.Provider 9 | 10 | const Tooltip = TooltipPrimitive.Root 11 | 12 | const TooltipTrigger = TooltipPrimitive.Trigger 13 | 14 | const TooltipContent = React.forwardRef< 15 | React.ElementRef, 16 | React.ComponentPropsWithoutRef 17 | >(({ className, sideOffset = 4, ...props }, ref) => ( 18 | 19 | 28 | 29 | )) 30 | TooltipContent.displayName = TooltipPrimitive.Content.displayName 31 | 32 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } 33 | -------------------------------------------------------------------------------- /frontend/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /frontend/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } -------------------------------------------------------------------------------- /frontend/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "assistant-ui-starter", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbo", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@ai-sdk/openai": "^1.1.15", 13 | "@assistant-ui/react": "^0.8.2", 14 | "@assistant-ui/react-ai-sdk": "^0.8.0", 15 | "@assistant-ui/react-markdown": "^0.8.0", 16 | "@electric-sql/react": "^1.0.0", 17 | "@radix-ui/react-avatar": "^1.1.3", 18 | "@radix-ui/react-slot": "^1.1.2", 19 | "@radix-ui/react-tooltip": "^1.1.8", 20 | "ai": "^4.1.46", 21 | "class-variance-authority": "^0.7.1", 22 | "clsx": "^2.1.1", 23 | "lucide-react": "^0.477.0", 24 | "next": "15.2.0", 25 | "react": "^19.0.0", 26 | "react-dom": "^19.0.0", 27 | "remark-gfm": "^4.0.1", 28 | "tailwind-merge": "^3.0.2", 29 | "tailwindcss-animate": "^1.0.7", 30 | "zod": "^3.24.2" 31 | }, 32 | "devDependencies": { 33 | "@eslint/eslintrc": "^3", 34 | "@types/node": "^22", 35 | "@types/react": "^19", 36 | "@types/react-dom": "^19", 37 | "eslint": "^8", 38 | "eslint-config-next": "15.2.0", 39 | "postcss": "^8", 40 | "tailwindcss": "^3.4.1", 41 | "typescript": "^5" 42 | }, 43 | "packageManager": "pnpm@10.6.3+sha512.bb45e34d50a9a76e858a95837301bfb6bd6d35aea2c5d52094fa497a467c43f5c440103ce2511e9e0a2f89c3d6071baac3358fc68ac6fb75e2ceb3d2736065e6", 44 | "pnpm": { 45 | "onlyBuiltDependencies": [ 46 | "sharp" 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /frontend/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /frontend/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config = { 4 | darkMode: ["class"], 5 | content: [ 6 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 8 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 9 | ], 10 | theme: { 11 | extend: { 12 | borderRadius: { 13 | lg: "var(--radius)", 14 | md: "calc(var(--radius) - 2px)", 15 | sm: "calc(var(--radius) - 4px)", 16 | }, 17 | colors: { 18 | background: "hsl(var(--background))", 19 | foreground: "hsl(var(--foreground))", 20 | card: { 21 | DEFAULT: "hsl(var(--card))", 22 | foreground: "hsl(var(--card-foreground))", 23 | }, 24 | popover: { 25 | DEFAULT: "hsl(var(--popover))", 26 | foreground: "hsl(var(--popover-foreground))", 27 | }, 28 | primary: { 29 | DEFAULT: "hsl(var(--primary))", 30 | foreground: "hsl(var(--primary-foreground))", 31 | }, 32 | secondary: { 33 | DEFAULT: "hsl(var(--secondary))", 34 | foreground: "hsl(var(--secondary-foreground))", 35 | }, 36 | muted: { 37 | DEFAULT: "hsl(var(--muted))", 38 | foreground: "hsl(var(--muted-foreground))", 39 | }, 40 | accent: { 41 | DEFAULT: "hsl(var(--accent))", 42 | foreground: "hsl(var(--accent-foreground))", 43 | }, 44 | destructive: { 45 | DEFAULT: "hsl(var(--destructive))", 46 | foreground: "hsl(var(--destructive-foreground))", 47 | }, 48 | border: "hsl(var(--border))", 49 | input: "hsl(var(--input))", 50 | ring: "hsl(var(--ring))", 51 | chart: { 52 | "1": "hsl(var(--chart-1))", 53 | "2": "hsl(var(--chart-2))", 54 | "3": "hsl(var(--chart-3))", 55 | "4": "hsl(var(--chart-4))", 56 | "5": "hsl(var(--chart-5))", 57 | }, 58 | }, 59 | }, 60 | plugins: ['require("tailwindcss-animate")'], 61 | }, 62 | } satisfies Config; 63 | 64 | export default config; 65 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /worker/.gitignore: -------------------------------------------------------------------------------- 1 | # prod 2 | dist/ 3 | 4 | # dev 5 | .yarn/ 6 | !.yarn/releases 7 | .vscode/* 8 | !.vscode/launch.json 9 | !.vscode/*.code-snippets 10 | .idea/workspace.xml 11 | .idea/usage.statistics.xml 12 | .idea/shelf 13 | 14 | # deps 15 | node_modules/ 16 | .wrangler 17 | 18 | # env 19 | .env 20 | .env.production 21 | .dev.vars 22 | 23 | # logs 24 | logs/ 25 | *.log 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | pnpm-debug.log* 30 | lerna-debug.log* 31 | 32 | # misc 33 | .DS_Store 34 | -------------------------------------------------------------------------------- /worker/drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | import { defineConfig } from 'drizzle-kit'; 3 | 4 | export default defineConfig({ 5 | out: './drizzle', 6 | schema: './src/db/schema.ts', 7 | dialect: 'postgresql', 8 | dbCredentials: { 9 | url: process.env.DATABASE_URL!, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /worker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "worker", 3 | "scripts": { 4 | "dev": "wrangler dev", 5 | "deploy": "wrangler deploy --minify" 6 | }, 7 | "dependencies": { 8 | "@ai-sdk/openai": "^1.2.5", 9 | "@electric-sql/client": "^1.0.0-beta.5", 10 | "@types/uuid": "^10.0.0", 11 | "ai": "^4.1.61", 12 | "dotenv": "^16.4.7", 13 | "drizzle-orm": "^0.40.0", 14 | "hono": "^4.7.4", 15 | "pg": "^8.14.0", 16 | "uuid": "^11.1.0", 17 | "zod": "^3.24.2" 18 | }, 19 | "devDependencies": { 20 | "@cloudflare/workers-types": "^4.20250313.0", 21 | "@types/pg": "^8.11.11", 22 | "drizzle-kit": "^0.30.5", 23 | "tsx": "^4.19.3", 24 | "wrangler": "^4.0.0" 25 | }, 26 | "packageManager": "pnpm@10.6.3" 27 | } 28 | -------------------------------------------------------------------------------- /worker/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@ai-sdk/openai': 12 | specifier: ^1.2.5 13 | version: 1.2.5(zod@3.24.2) 14 | '@electric-sql/client': 15 | specifier: ^1.0.0-beta.5 16 | version: 1.0.0-beta.5 17 | '@types/uuid': 18 | specifier: ^10.0.0 19 | version: 10.0.0 20 | ai: 21 | specifier: ^4.1.61 22 | version: 4.1.61(react@19.0.0)(zod@3.24.2) 23 | dotenv: 24 | specifier: ^16.4.7 25 | version: 16.4.7 26 | drizzle-orm: 27 | specifier: ^0.40.0 28 | version: 0.40.0(@cloudflare/workers-types@4.20250313.0)(@opentelemetry/api@1.9.0)(@types/pg@8.11.11)(gel@2.0.1)(pg@8.14.0) 29 | hono: 30 | specifier: ^4.7.4 31 | version: 4.7.4 32 | pg: 33 | specifier: ^8.14.0 34 | version: 8.14.0 35 | uuid: 36 | specifier: ^11.1.0 37 | version: 11.1.0 38 | zod: 39 | specifier: ^3.24.2 40 | version: 3.24.2 41 | devDependencies: 42 | '@cloudflare/workers-types': 43 | specifier: ^4.20250313.0 44 | version: 4.20250313.0 45 | '@types/pg': 46 | specifier: ^8.11.11 47 | version: 8.11.11 48 | drizzle-kit: 49 | specifier: ^0.30.5 50 | version: 0.30.5 51 | tsx: 52 | specifier: ^4.19.3 53 | version: 4.19.3 54 | wrangler: 55 | specifier: ^4.0.0 56 | version: 4.0.0(@cloudflare/workers-types@4.20250313.0) 57 | 58 | packages: 59 | 60 | '@ai-sdk/openai@1.2.5': 61 | resolution: {integrity: sha512-COK7LzspgQQh5Yq070xfDdVMvp8WX592rXRaMaYNNqu1xpzahxDcM24aF9xgKYWuYH0UMoOw4UmWGwGxr6ygIg==} 62 | engines: {node: '>=18'} 63 | peerDependencies: 64 | zod: ^3.0.0 65 | 66 | '@ai-sdk/provider-utils@2.1.13': 67 | resolution: {integrity: sha512-kLjqsfOdONr6DGcGEntFYM1niXz1H05vyZNf9OAzK+KKKc64izyP4/q/9HX7W4+6g8hm6BnmKxu8vkr6FSOqDg==} 68 | engines: {node: '>=18'} 69 | peerDependencies: 70 | zod: ^3.0.0 71 | peerDependenciesMeta: 72 | zod: 73 | optional: true 74 | 75 | '@ai-sdk/provider@1.0.11': 76 | resolution: {integrity: sha512-CPyImHGiT3svyfmvPvAFTianZzWFtm0qK82XjwlQIA1C3IQ2iku/PMQXi7aFyrX0TyMh3VTkJPB03tjU2VXVrw==} 77 | engines: {node: '>=18'} 78 | 79 | '@ai-sdk/react@1.1.23': 80 | resolution: {integrity: sha512-R+PG9ya0GLs6orzt+1MxmjrWFuZM0gVs+l8ihBr1u+42wwkVeojY4CAtQjW4nrfGTVbdJYkl5y+r/VKfjr42aQ==} 81 | engines: {node: '>=18'} 82 | peerDependencies: 83 | react: ^18 || ^19 || ^19.0.0-rc 84 | zod: ^3.0.0 85 | peerDependenciesMeta: 86 | react: 87 | optional: true 88 | zod: 89 | optional: true 90 | 91 | '@ai-sdk/ui-utils@1.1.19': 92 | resolution: {integrity: sha512-rDHy2uxlPMt3jjS9L6mBrsfhEInZ5BVoWevmD13fsAt2s/XWy2OwwKmgmUQkdLlY4mn/eyeYAfDGK8+5CbOAgg==} 93 | engines: {node: '>=18'} 94 | peerDependencies: 95 | zod: ^3.0.0 96 | peerDependenciesMeta: 97 | zod: 98 | optional: true 99 | 100 | '@cloudflare/kv-asset-handler@0.4.0': 101 | resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} 102 | engines: {node: '>=18.0.0'} 103 | 104 | '@cloudflare/unenv-preset@2.0.2': 105 | resolution: {integrity: sha512-nyzYnlZjjV5xT3LizahG1Iu6mnrCaxglJ04rZLpDwlDVDZ7v46lNsfxhV3A/xtfgQuSHmLnc6SVI+KwBpc3Lwg==} 106 | peerDependencies: 107 | unenv: 2.0.0-rc.14 108 | workerd: ^1.20250124.0 109 | peerDependenciesMeta: 110 | workerd: 111 | optional: true 112 | 113 | '@cloudflare/workerd-darwin-64@1.20250310.0': 114 | resolution: {integrity: sha512-LkLJO6F8lRNaCbK5sQCITi66SyCirDpffRuI5/5iILDJWQU4KVvAOKPvHrd4E5h/WDm9FGd22zMJwky7SxaNjg==} 115 | engines: {node: '>=16'} 116 | cpu: [x64] 117 | os: [darwin] 118 | 119 | '@cloudflare/workerd-darwin-arm64@1.20250310.0': 120 | resolution: {integrity: sha512-WythDJQbsU3Ii1hhA7pJZLBQlHezeYWAnaMnv3gS2Exj45oF8G4chFvrO7zCzjlcJXwSeBTtQRJqxw9AiUDhyA==} 121 | engines: {node: '>=16'} 122 | cpu: [arm64] 123 | os: [darwin] 124 | 125 | '@cloudflare/workerd-linux-64@1.20250310.0': 126 | resolution: {integrity: sha512-LbP769tT4/5QBHSj4lCt99QIKTi6cU+wYhLfF7rEtYHBnZS2+nIw9xttAzxeERx/aFrU+mxLcYPFV8fUeVxGng==} 127 | engines: {node: '>=16'} 128 | cpu: [x64] 129 | os: [linux] 130 | 131 | '@cloudflare/workerd-linux-arm64@1.20250310.0': 132 | resolution: {integrity: sha512-FzWeKM6id20EMZACaDg0Kkvg1C4lvXZgLBXVI6h6xaXTNFReoyEp4v4eMrRTuja5ec5k+m5iGKjP4/bMWJp9ew==} 133 | engines: {node: '>=16'} 134 | cpu: [arm64] 135 | os: [linux] 136 | 137 | '@cloudflare/workerd-windows-64@1.20250310.0': 138 | resolution: {integrity: sha512-04OgaDzm8/8nkjF3tovB+WywZLjSdAHCQT2omXKCwH3EDd1kpd8vvzE1pErtdIyKCOf9/sArY4BhPdxRj7ijlg==} 139 | engines: {node: '>=16'} 140 | cpu: [x64] 141 | os: [win32] 142 | 143 | '@cloudflare/workers-types@4.20250313.0': 144 | resolution: {integrity: sha512-iqyzZwogC+3yL8h58vMhjYQUHUZA8XazE3Q+ofR59wDOnsPe/u9W6+aCl408N0iNBhMPvpJQQ3/lkz0iJN2fhA==} 145 | 146 | '@cspotcode/source-map-support@0.8.1': 147 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 148 | engines: {node: '>=12'} 149 | 150 | '@drizzle-team/brocli@0.10.2': 151 | resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} 152 | 153 | '@electric-sql/client@1.0.0-beta.5': 154 | resolution: {integrity: sha512-sP4yBBt4sDWE7FhMMVkVceKULLPStumFzlgltUqb7AzzXP6AK2qs4bZ2QrabY6feBgRgrMP19bOzxI/WOSnTAA==} 155 | 156 | '@emnapi/runtime@1.3.1': 157 | resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} 158 | 159 | '@esbuild-kit/core-utils@3.3.2': 160 | resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} 161 | deprecated: 'Merged into tsx: https://tsx.is' 162 | 163 | '@esbuild-kit/esm-loader@2.6.5': 164 | resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} 165 | deprecated: 'Merged into tsx: https://tsx.is' 166 | 167 | '@esbuild/aix-ppc64@0.19.12': 168 | resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} 169 | engines: {node: '>=12'} 170 | cpu: [ppc64] 171 | os: [aix] 172 | 173 | '@esbuild/aix-ppc64@0.24.2': 174 | resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} 175 | engines: {node: '>=18'} 176 | cpu: [ppc64] 177 | os: [aix] 178 | 179 | '@esbuild/aix-ppc64@0.25.1': 180 | resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} 181 | engines: {node: '>=18'} 182 | cpu: [ppc64] 183 | os: [aix] 184 | 185 | '@esbuild/android-arm64@0.18.20': 186 | resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} 187 | engines: {node: '>=12'} 188 | cpu: [arm64] 189 | os: [android] 190 | 191 | '@esbuild/android-arm64@0.19.12': 192 | resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} 193 | engines: {node: '>=12'} 194 | cpu: [arm64] 195 | os: [android] 196 | 197 | '@esbuild/android-arm64@0.24.2': 198 | resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} 199 | engines: {node: '>=18'} 200 | cpu: [arm64] 201 | os: [android] 202 | 203 | '@esbuild/android-arm64@0.25.1': 204 | resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} 205 | engines: {node: '>=18'} 206 | cpu: [arm64] 207 | os: [android] 208 | 209 | '@esbuild/android-arm@0.18.20': 210 | resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} 211 | engines: {node: '>=12'} 212 | cpu: [arm] 213 | os: [android] 214 | 215 | '@esbuild/android-arm@0.19.12': 216 | resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} 217 | engines: {node: '>=12'} 218 | cpu: [arm] 219 | os: [android] 220 | 221 | '@esbuild/android-arm@0.24.2': 222 | resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} 223 | engines: {node: '>=18'} 224 | cpu: [arm] 225 | os: [android] 226 | 227 | '@esbuild/android-arm@0.25.1': 228 | resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} 229 | engines: {node: '>=18'} 230 | cpu: [arm] 231 | os: [android] 232 | 233 | '@esbuild/android-x64@0.18.20': 234 | resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} 235 | engines: {node: '>=12'} 236 | cpu: [x64] 237 | os: [android] 238 | 239 | '@esbuild/android-x64@0.19.12': 240 | resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} 241 | engines: {node: '>=12'} 242 | cpu: [x64] 243 | os: [android] 244 | 245 | '@esbuild/android-x64@0.24.2': 246 | resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} 247 | engines: {node: '>=18'} 248 | cpu: [x64] 249 | os: [android] 250 | 251 | '@esbuild/android-x64@0.25.1': 252 | resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} 253 | engines: {node: '>=18'} 254 | cpu: [x64] 255 | os: [android] 256 | 257 | '@esbuild/darwin-arm64@0.18.20': 258 | resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} 259 | engines: {node: '>=12'} 260 | cpu: [arm64] 261 | os: [darwin] 262 | 263 | '@esbuild/darwin-arm64@0.19.12': 264 | resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} 265 | engines: {node: '>=12'} 266 | cpu: [arm64] 267 | os: [darwin] 268 | 269 | '@esbuild/darwin-arm64@0.24.2': 270 | resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} 271 | engines: {node: '>=18'} 272 | cpu: [arm64] 273 | os: [darwin] 274 | 275 | '@esbuild/darwin-arm64@0.25.1': 276 | resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} 277 | engines: {node: '>=18'} 278 | cpu: [arm64] 279 | os: [darwin] 280 | 281 | '@esbuild/darwin-x64@0.18.20': 282 | resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} 283 | engines: {node: '>=12'} 284 | cpu: [x64] 285 | os: [darwin] 286 | 287 | '@esbuild/darwin-x64@0.19.12': 288 | resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} 289 | engines: {node: '>=12'} 290 | cpu: [x64] 291 | os: [darwin] 292 | 293 | '@esbuild/darwin-x64@0.24.2': 294 | resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} 295 | engines: {node: '>=18'} 296 | cpu: [x64] 297 | os: [darwin] 298 | 299 | '@esbuild/darwin-x64@0.25.1': 300 | resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} 301 | engines: {node: '>=18'} 302 | cpu: [x64] 303 | os: [darwin] 304 | 305 | '@esbuild/freebsd-arm64@0.18.20': 306 | resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} 307 | engines: {node: '>=12'} 308 | cpu: [arm64] 309 | os: [freebsd] 310 | 311 | '@esbuild/freebsd-arm64@0.19.12': 312 | resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} 313 | engines: {node: '>=12'} 314 | cpu: [arm64] 315 | os: [freebsd] 316 | 317 | '@esbuild/freebsd-arm64@0.24.2': 318 | resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} 319 | engines: {node: '>=18'} 320 | cpu: [arm64] 321 | os: [freebsd] 322 | 323 | '@esbuild/freebsd-arm64@0.25.1': 324 | resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} 325 | engines: {node: '>=18'} 326 | cpu: [arm64] 327 | os: [freebsd] 328 | 329 | '@esbuild/freebsd-x64@0.18.20': 330 | resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} 331 | engines: {node: '>=12'} 332 | cpu: [x64] 333 | os: [freebsd] 334 | 335 | '@esbuild/freebsd-x64@0.19.12': 336 | resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} 337 | engines: {node: '>=12'} 338 | cpu: [x64] 339 | os: [freebsd] 340 | 341 | '@esbuild/freebsd-x64@0.24.2': 342 | resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} 343 | engines: {node: '>=18'} 344 | cpu: [x64] 345 | os: [freebsd] 346 | 347 | '@esbuild/freebsd-x64@0.25.1': 348 | resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} 349 | engines: {node: '>=18'} 350 | cpu: [x64] 351 | os: [freebsd] 352 | 353 | '@esbuild/linux-arm64@0.18.20': 354 | resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} 355 | engines: {node: '>=12'} 356 | cpu: [arm64] 357 | os: [linux] 358 | 359 | '@esbuild/linux-arm64@0.19.12': 360 | resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} 361 | engines: {node: '>=12'} 362 | cpu: [arm64] 363 | os: [linux] 364 | 365 | '@esbuild/linux-arm64@0.24.2': 366 | resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} 367 | engines: {node: '>=18'} 368 | cpu: [arm64] 369 | os: [linux] 370 | 371 | '@esbuild/linux-arm64@0.25.1': 372 | resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} 373 | engines: {node: '>=18'} 374 | cpu: [arm64] 375 | os: [linux] 376 | 377 | '@esbuild/linux-arm@0.18.20': 378 | resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} 379 | engines: {node: '>=12'} 380 | cpu: [arm] 381 | os: [linux] 382 | 383 | '@esbuild/linux-arm@0.19.12': 384 | resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} 385 | engines: {node: '>=12'} 386 | cpu: [arm] 387 | os: [linux] 388 | 389 | '@esbuild/linux-arm@0.24.2': 390 | resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} 391 | engines: {node: '>=18'} 392 | cpu: [arm] 393 | os: [linux] 394 | 395 | '@esbuild/linux-arm@0.25.1': 396 | resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} 397 | engines: {node: '>=18'} 398 | cpu: [arm] 399 | os: [linux] 400 | 401 | '@esbuild/linux-ia32@0.18.20': 402 | resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} 403 | engines: {node: '>=12'} 404 | cpu: [ia32] 405 | os: [linux] 406 | 407 | '@esbuild/linux-ia32@0.19.12': 408 | resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} 409 | engines: {node: '>=12'} 410 | cpu: [ia32] 411 | os: [linux] 412 | 413 | '@esbuild/linux-ia32@0.24.2': 414 | resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} 415 | engines: {node: '>=18'} 416 | cpu: [ia32] 417 | os: [linux] 418 | 419 | '@esbuild/linux-ia32@0.25.1': 420 | resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} 421 | engines: {node: '>=18'} 422 | cpu: [ia32] 423 | os: [linux] 424 | 425 | '@esbuild/linux-loong64@0.18.20': 426 | resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} 427 | engines: {node: '>=12'} 428 | cpu: [loong64] 429 | os: [linux] 430 | 431 | '@esbuild/linux-loong64@0.19.12': 432 | resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} 433 | engines: {node: '>=12'} 434 | cpu: [loong64] 435 | os: [linux] 436 | 437 | '@esbuild/linux-loong64@0.24.2': 438 | resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} 439 | engines: {node: '>=18'} 440 | cpu: [loong64] 441 | os: [linux] 442 | 443 | '@esbuild/linux-loong64@0.25.1': 444 | resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} 445 | engines: {node: '>=18'} 446 | cpu: [loong64] 447 | os: [linux] 448 | 449 | '@esbuild/linux-mips64el@0.18.20': 450 | resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} 451 | engines: {node: '>=12'} 452 | cpu: [mips64el] 453 | os: [linux] 454 | 455 | '@esbuild/linux-mips64el@0.19.12': 456 | resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} 457 | engines: {node: '>=12'} 458 | cpu: [mips64el] 459 | os: [linux] 460 | 461 | '@esbuild/linux-mips64el@0.24.2': 462 | resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} 463 | engines: {node: '>=18'} 464 | cpu: [mips64el] 465 | os: [linux] 466 | 467 | '@esbuild/linux-mips64el@0.25.1': 468 | resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} 469 | engines: {node: '>=18'} 470 | cpu: [mips64el] 471 | os: [linux] 472 | 473 | '@esbuild/linux-ppc64@0.18.20': 474 | resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} 475 | engines: {node: '>=12'} 476 | cpu: [ppc64] 477 | os: [linux] 478 | 479 | '@esbuild/linux-ppc64@0.19.12': 480 | resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} 481 | engines: {node: '>=12'} 482 | cpu: [ppc64] 483 | os: [linux] 484 | 485 | '@esbuild/linux-ppc64@0.24.2': 486 | resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} 487 | engines: {node: '>=18'} 488 | cpu: [ppc64] 489 | os: [linux] 490 | 491 | '@esbuild/linux-ppc64@0.25.1': 492 | resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} 493 | engines: {node: '>=18'} 494 | cpu: [ppc64] 495 | os: [linux] 496 | 497 | '@esbuild/linux-riscv64@0.18.20': 498 | resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} 499 | engines: {node: '>=12'} 500 | cpu: [riscv64] 501 | os: [linux] 502 | 503 | '@esbuild/linux-riscv64@0.19.12': 504 | resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} 505 | engines: {node: '>=12'} 506 | cpu: [riscv64] 507 | os: [linux] 508 | 509 | '@esbuild/linux-riscv64@0.24.2': 510 | resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} 511 | engines: {node: '>=18'} 512 | cpu: [riscv64] 513 | os: [linux] 514 | 515 | '@esbuild/linux-riscv64@0.25.1': 516 | resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} 517 | engines: {node: '>=18'} 518 | cpu: [riscv64] 519 | os: [linux] 520 | 521 | '@esbuild/linux-s390x@0.18.20': 522 | resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} 523 | engines: {node: '>=12'} 524 | cpu: [s390x] 525 | os: [linux] 526 | 527 | '@esbuild/linux-s390x@0.19.12': 528 | resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} 529 | engines: {node: '>=12'} 530 | cpu: [s390x] 531 | os: [linux] 532 | 533 | '@esbuild/linux-s390x@0.24.2': 534 | resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} 535 | engines: {node: '>=18'} 536 | cpu: [s390x] 537 | os: [linux] 538 | 539 | '@esbuild/linux-s390x@0.25.1': 540 | resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} 541 | engines: {node: '>=18'} 542 | cpu: [s390x] 543 | os: [linux] 544 | 545 | '@esbuild/linux-x64@0.18.20': 546 | resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} 547 | engines: {node: '>=12'} 548 | cpu: [x64] 549 | os: [linux] 550 | 551 | '@esbuild/linux-x64@0.19.12': 552 | resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} 553 | engines: {node: '>=12'} 554 | cpu: [x64] 555 | os: [linux] 556 | 557 | '@esbuild/linux-x64@0.24.2': 558 | resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} 559 | engines: {node: '>=18'} 560 | cpu: [x64] 561 | os: [linux] 562 | 563 | '@esbuild/linux-x64@0.25.1': 564 | resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} 565 | engines: {node: '>=18'} 566 | cpu: [x64] 567 | os: [linux] 568 | 569 | '@esbuild/netbsd-arm64@0.24.2': 570 | resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} 571 | engines: {node: '>=18'} 572 | cpu: [arm64] 573 | os: [netbsd] 574 | 575 | '@esbuild/netbsd-arm64@0.25.1': 576 | resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} 577 | engines: {node: '>=18'} 578 | cpu: [arm64] 579 | os: [netbsd] 580 | 581 | '@esbuild/netbsd-x64@0.18.20': 582 | resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} 583 | engines: {node: '>=12'} 584 | cpu: [x64] 585 | os: [netbsd] 586 | 587 | '@esbuild/netbsd-x64@0.19.12': 588 | resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} 589 | engines: {node: '>=12'} 590 | cpu: [x64] 591 | os: [netbsd] 592 | 593 | '@esbuild/netbsd-x64@0.24.2': 594 | resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} 595 | engines: {node: '>=18'} 596 | cpu: [x64] 597 | os: [netbsd] 598 | 599 | '@esbuild/netbsd-x64@0.25.1': 600 | resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} 601 | engines: {node: '>=18'} 602 | cpu: [x64] 603 | os: [netbsd] 604 | 605 | '@esbuild/openbsd-arm64@0.24.2': 606 | resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} 607 | engines: {node: '>=18'} 608 | cpu: [arm64] 609 | os: [openbsd] 610 | 611 | '@esbuild/openbsd-arm64@0.25.1': 612 | resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} 613 | engines: {node: '>=18'} 614 | cpu: [arm64] 615 | os: [openbsd] 616 | 617 | '@esbuild/openbsd-x64@0.18.20': 618 | resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} 619 | engines: {node: '>=12'} 620 | cpu: [x64] 621 | os: [openbsd] 622 | 623 | '@esbuild/openbsd-x64@0.19.12': 624 | resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} 625 | engines: {node: '>=12'} 626 | cpu: [x64] 627 | os: [openbsd] 628 | 629 | '@esbuild/openbsd-x64@0.24.2': 630 | resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} 631 | engines: {node: '>=18'} 632 | cpu: [x64] 633 | os: [openbsd] 634 | 635 | '@esbuild/openbsd-x64@0.25.1': 636 | resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} 637 | engines: {node: '>=18'} 638 | cpu: [x64] 639 | os: [openbsd] 640 | 641 | '@esbuild/sunos-x64@0.18.20': 642 | resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} 643 | engines: {node: '>=12'} 644 | cpu: [x64] 645 | os: [sunos] 646 | 647 | '@esbuild/sunos-x64@0.19.12': 648 | resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} 649 | engines: {node: '>=12'} 650 | cpu: [x64] 651 | os: [sunos] 652 | 653 | '@esbuild/sunos-x64@0.24.2': 654 | resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} 655 | engines: {node: '>=18'} 656 | cpu: [x64] 657 | os: [sunos] 658 | 659 | '@esbuild/sunos-x64@0.25.1': 660 | resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} 661 | engines: {node: '>=18'} 662 | cpu: [x64] 663 | os: [sunos] 664 | 665 | '@esbuild/win32-arm64@0.18.20': 666 | resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} 667 | engines: {node: '>=12'} 668 | cpu: [arm64] 669 | os: [win32] 670 | 671 | '@esbuild/win32-arm64@0.19.12': 672 | resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} 673 | engines: {node: '>=12'} 674 | cpu: [arm64] 675 | os: [win32] 676 | 677 | '@esbuild/win32-arm64@0.24.2': 678 | resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} 679 | engines: {node: '>=18'} 680 | cpu: [arm64] 681 | os: [win32] 682 | 683 | '@esbuild/win32-arm64@0.25.1': 684 | resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} 685 | engines: {node: '>=18'} 686 | cpu: [arm64] 687 | os: [win32] 688 | 689 | '@esbuild/win32-ia32@0.18.20': 690 | resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} 691 | engines: {node: '>=12'} 692 | cpu: [ia32] 693 | os: [win32] 694 | 695 | '@esbuild/win32-ia32@0.19.12': 696 | resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} 697 | engines: {node: '>=12'} 698 | cpu: [ia32] 699 | os: [win32] 700 | 701 | '@esbuild/win32-ia32@0.24.2': 702 | resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} 703 | engines: {node: '>=18'} 704 | cpu: [ia32] 705 | os: [win32] 706 | 707 | '@esbuild/win32-ia32@0.25.1': 708 | resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} 709 | engines: {node: '>=18'} 710 | cpu: [ia32] 711 | os: [win32] 712 | 713 | '@esbuild/win32-x64@0.18.20': 714 | resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} 715 | engines: {node: '>=12'} 716 | cpu: [x64] 717 | os: [win32] 718 | 719 | '@esbuild/win32-x64@0.19.12': 720 | resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} 721 | engines: {node: '>=12'} 722 | cpu: [x64] 723 | os: [win32] 724 | 725 | '@esbuild/win32-x64@0.24.2': 726 | resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} 727 | engines: {node: '>=18'} 728 | cpu: [x64] 729 | os: [win32] 730 | 731 | '@esbuild/win32-x64@0.25.1': 732 | resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} 733 | engines: {node: '>=18'} 734 | cpu: [x64] 735 | os: [win32] 736 | 737 | '@fastify/busboy@2.1.1': 738 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 739 | engines: {node: '>=14'} 740 | 741 | '@img/sharp-darwin-arm64@0.33.5': 742 | resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} 743 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 744 | cpu: [arm64] 745 | os: [darwin] 746 | 747 | '@img/sharp-darwin-x64@0.33.5': 748 | resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} 749 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 750 | cpu: [x64] 751 | os: [darwin] 752 | 753 | '@img/sharp-libvips-darwin-arm64@1.0.4': 754 | resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} 755 | cpu: [arm64] 756 | os: [darwin] 757 | 758 | '@img/sharp-libvips-darwin-x64@1.0.4': 759 | resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} 760 | cpu: [x64] 761 | os: [darwin] 762 | 763 | '@img/sharp-libvips-linux-arm64@1.0.4': 764 | resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} 765 | cpu: [arm64] 766 | os: [linux] 767 | 768 | '@img/sharp-libvips-linux-arm@1.0.5': 769 | resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} 770 | cpu: [arm] 771 | os: [linux] 772 | 773 | '@img/sharp-libvips-linux-s390x@1.0.4': 774 | resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} 775 | cpu: [s390x] 776 | os: [linux] 777 | 778 | '@img/sharp-libvips-linux-x64@1.0.4': 779 | resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} 780 | cpu: [x64] 781 | os: [linux] 782 | 783 | '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 784 | resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} 785 | cpu: [arm64] 786 | os: [linux] 787 | 788 | '@img/sharp-libvips-linuxmusl-x64@1.0.4': 789 | resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} 790 | cpu: [x64] 791 | os: [linux] 792 | 793 | '@img/sharp-linux-arm64@0.33.5': 794 | resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} 795 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 796 | cpu: [arm64] 797 | os: [linux] 798 | 799 | '@img/sharp-linux-arm@0.33.5': 800 | resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} 801 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 802 | cpu: [arm] 803 | os: [linux] 804 | 805 | '@img/sharp-linux-s390x@0.33.5': 806 | resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} 807 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 808 | cpu: [s390x] 809 | os: [linux] 810 | 811 | '@img/sharp-linux-x64@0.33.5': 812 | resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} 813 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 814 | cpu: [x64] 815 | os: [linux] 816 | 817 | '@img/sharp-linuxmusl-arm64@0.33.5': 818 | resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} 819 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 820 | cpu: [arm64] 821 | os: [linux] 822 | 823 | '@img/sharp-linuxmusl-x64@0.33.5': 824 | resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} 825 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 826 | cpu: [x64] 827 | os: [linux] 828 | 829 | '@img/sharp-wasm32@0.33.5': 830 | resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} 831 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 832 | cpu: [wasm32] 833 | 834 | '@img/sharp-win32-ia32@0.33.5': 835 | resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} 836 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 837 | cpu: [ia32] 838 | os: [win32] 839 | 840 | '@img/sharp-win32-x64@0.33.5': 841 | resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} 842 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 843 | cpu: [x64] 844 | os: [win32] 845 | 846 | '@jridgewell/resolve-uri@3.1.2': 847 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 848 | engines: {node: '>=6.0.0'} 849 | 850 | '@jridgewell/sourcemap-codec@1.5.0': 851 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 852 | 853 | '@jridgewell/trace-mapping@0.3.9': 854 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 855 | 856 | '@opentelemetry/api@1.9.0': 857 | resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} 858 | engines: {node: '>=8.0.0'} 859 | 860 | '@petamoriken/float16@3.9.2': 861 | resolution: {integrity: sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==} 862 | 863 | '@rollup/rollup-darwin-arm64@4.35.0': 864 | resolution: {integrity: sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==} 865 | cpu: [arm64] 866 | os: [darwin] 867 | 868 | '@types/diff-match-patch@1.0.36': 869 | resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} 870 | 871 | '@types/node@22.13.10': 872 | resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} 873 | 874 | '@types/pg@8.11.11': 875 | resolution: {integrity: sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==} 876 | 877 | '@types/uuid@10.0.0': 878 | resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} 879 | 880 | acorn-walk@8.3.2: 881 | resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} 882 | engines: {node: '>=0.4.0'} 883 | 884 | acorn@8.14.0: 885 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} 886 | engines: {node: '>=0.4.0'} 887 | hasBin: true 888 | 889 | ai@4.1.61: 890 | resolution: {integrity: sha512-Y9SAyGJEeW23F6C7PSHZXYNEvbH2cqJm0rVW2AoeFaXFT13ttx8rAqs8wz2w466C1UB329yl5PXayFcHqofSEA==} 891 | engines: {node: '>=18'} 892 | peerDependencies: 893 | react: ^18 || ^19 || ^19.0.0-rc 894 | zod: ^3.0.0 895 | peerDependenciesMeta: 896 | react: 897 | optional: true 898 | zod: 899 | optional: true 900 | 901 | as-table@1.0.55: 902 | resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} 903 | 904 | blake3-wasm@2.1.5: 905 | resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} 906 | 907 | buffer-from@1.1.2: 908 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 909 | 910 | chalk@5.4.1: 911 | resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 912 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 913 | 914 | color-convert@2.0.1: 915 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 916 | engines: {node: '>=7.0.0'} 917 | 918 | color-name@1.1.4: 919 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 920 | 921 | color-string@1.9.1: 922 | resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} 923 | 924 | color@4.2.3: 925 | resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} 926 | engines: {node: '>=12.5.0'} 927 | 928 | cookie@0.5.0: 929 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 930 | engines: {node: '>= 0.6'} 931 | 932 | data-uri-to-buffer@2.0.2: 933 | resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} 934 | 935 | debug@4.4.0: 936 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 937 | engines: {node: '>=6.0'} 938 | peerDependencies: 939 | supports-color: '*' 940 | peerDependenciesMeta: 941 | supports-color: 942 | optional: true 943 | 944 | defu@6.1.4: 945 | resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 946 | 947 | dequal@2.0.3: 948 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} 949 | engines: {node: '>=6'} 950 | 951 | detect-libc@2.0.3: 952 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 953 | engines: {node: '>=8'} 954 | 955 | diff-match-patch@1.0.5: 956 | resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} 957 | 958 | dotenv@16.4.7: 959 | resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} 960 | engines: {node: '>=12'} 961 | 962 | drizzle-kit@0.30.5: 963 | resolution: {integrity: sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA==} 964 | hasBin: true 965 | 966 | drizzle-orm@0.40.0: 967 | resolution: {integrity: sha512-7ptk/HQiMSrEZHnAsSlBESXWj52VwgMmyTEfoNmpNN2ZXpcz13LwHfXTIghsAEud7Z5UJhDOp8U07ujcqme7wg==} 968 | peerDependencies: 969 | '@aws-sdk/client-rds-data': '>=3' 970 | '@cloudflare/workers-types': '>=4' 971 | '@electric-sql/pglite': '>=0.2.0' 972 | '@libsql/client': '>=0.10.0' 973 | '@libsql/client-wasm': '>=0.10.0' 974 | '@neondatabase/serverless': '>=0.10.0' 975 | '@op-engineering/op-sqlite': '>=2' 976 | '@opentelemetry/api': ^1.4.1 977 | '@planetscale/database': '>=1' 978 | '@prisma/client': '*' 979 | '@tidbcloud/serverless': '*' 980 | '@types/better-sqlite3': '*' 981 | '@types/pg': '*' 982 | '@types/sql.js': '*' 983 | '@vercel/postgres': '>=0.8.0' 984 | '@xata.io/client': '*' 985 | better-sqlite3: '>=7' 986 | bun-types: '*' 987 | expo-sqlite: '>=14.0.0' 988 | gel: '>=2' 989 | knex: '*' 990 | kysely: '*' 991 | mysql2: '>=2' 992 | pg: '>=8' 993 | postgres: '>=3' 994 | prisma: '*' 995 | sql.js: '>=1' 996 | sqlite3: '>=5' 997 | peerDependenciesMeta: 998 | '@aws-sdk/client-rds-data': 999 | optional: true 1000 | '@cloudflare/workers-types': 1001 | optional: true 1002 | '@electric-sql/pglite': 1003 | optional: true 1004 | '@libsql/client': 1005 | optional: true 1006 | '@libsql/client-wasm': 1007 | optional: true 1008 | '@neondatabase/serverless': 1009 | optional: true 1010 | '@op-engineering/op-sqlite': 1011 | optional: true 1012 | '@opentelemetry/api': 1013 | optional: true 1014 | '@planetscale/database': 1015 | optional: true 1016 | '@prisma/client': 1017 | optional: true 1018 | '@tidbcloud/serverless': 1019 | optional: true 1020 | '@types/better-sqlite3': 1021 | optional: true 1022 | '@types/pg': 1023 | optional: true 1024 | '@types/sql.js': 1025 | optional: true 1026 | '@vercel/postgres': 1027 | optional: true 1028 | '@xata.io/client': 1029 | optional: true 1030 | better-sqlite3: 1031 | optional: true 1032 | bun-types: 1033 | optional: true 1034 | expo-sqlite: 1035 | optional: true 1036 | gel: 1037 | optional: true 1038 | knex: 1039 | optional: true 1040 | kysely: 1041 | optional: true 1042 | mysql2: 1043 | optional: true 1044 | pg: 1045 | optional: true 1046 | postgres: 1047 | optional: true 1048 | prisma: 1049 | optional: true 1050 | sql.js: 1051 | optional: true 1052 | sqlite3: 1053 | optional: true 1054 | 1055 | env-paths@3.0.0: 1056 | resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} 1057 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1058 | 1059 | esbuild-register@3.6.0: 1060 | resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} 1061 | peerDependencies: 1062 | esbuild: '>=0.12 <1' 1063 | 1064 | esbuild@0.18.20: 1065 | resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} 1066 | engines: {node: '>=12'} 1067 | hasBin: true 1068 | 1069 | esbuild@0.19.12: 1070 | resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} 1071 | engines: {node: '>=12'} 1072 | hasBin: true 1073 | 1074 | esbuild@0.24.2: 1075 | resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} 1076 | engines: {node: '>=18'} 1077 | hasBin: true 1078 | 1079 | esbuild@0.25.1: 1080 | resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} 1081 | engines: {node: '>=18'} 1082 | hasBin: true 1083 | 1084 | eventsource-parser@3.0.0: 1085 | resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} 1086 | engines: {node: '>=18.0.0'} 1087 | 1088 | exit-hook@2.2.1: 1089 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} 1090 | engines: {node: '>=6'} 1091 | 1092 | exsolve@1.0.4: 1093 | resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==} 1094 | 1095 | fsevents@2.3.3: 1096 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1097 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1098 | os: [darwin] 1099 | 1100 | gel@2.0.1: 1101 | resolution: {integrity: sha512-gfem3IGvqKqXwEq7XseBogyaRwGsQGuE7Cw/yQsjLGdgiyqX92G1xENPCE0ltunPGcsJIa6XBOTx/PK169mOqw==} 1102 | engines: {node: '>= 18.0.0'} 1103 | hasBin: true 1104 | 1105 | get-source@2.0.12: 1106 | resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} 1107 | 1108 | get-tsconfig@4.10.0: 1109 | resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} 1110 | 1111 | glob-to-regexp@0.4.1: 1112 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 1113 | 1114 | hono@4.7.4: 1115 | resolution: {integrity: sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg==} 1116 | engines: {node: '>=16.9.0'} 1117 | 1118 | is-arrayish@0.3.2: 1119 | resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} 1120 | 1121 | isexe@3.1.1: 1122 | resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} 1123 | engines: {node: '>=16'} 1124 | 1125 | json-schema@0.4.0: 1126 | resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} 1127 | 1128 | jsondiffpatch@0.6.0: 1129 | resolution: {integrity: sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==} 1130 | engines: {node: ^18.0.0 || >=20.0.0} 1131 | hasBin: true 1132 | 1133 | mime@3.0.0: 1134 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} 1135 | engines: {node: '>=10.0.0'} 1136 | hasBin: true 1137 | 1138 | miniflare@4.20250310.0: 1139 | resolution: {integrity: sha512-WL4hKQIfXyTxKyQzxJyyy/v+OYSiF51s3Qe1Q4W4MjHJbtiN8Kg7+oeTdHYgqYehanN2zYoSKJ/xooIy8q5+XA==} 1140 | engines: {node: '>=18.0.0'} 1141 | hasBin: true 1142 | 1143 | ms@2.1.3: 1144 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1145 | 1146 | mustache@4.2.0: 1147 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 1148 | hasBin: true 1149 | 1150 | nanoid@3.3.10: 1151 | resolution: {integrity: sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==} 1152 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1153 | hasBin: true 1154 | 1155 | obuf@1.1.2: 1156 | resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} 1157 | 1158 | ohash@2.0.11: 1159 | resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} 1160 | 1161 | path-to-regexp@6.3.0: 1162 | resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} 1163 | 1164 | pathe@2.0.3: 1165 | resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1166 | 1167 | pg-cloudflare@1.1.1: 1168 | resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} 1169 | 1170 | pg-connection-string@2.7.0: 1171 | resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} 1172 | 1173 | pg-int8@1.0.1: 1174 | resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} 1175 | engines: {node: '>=4.0.0'} 1176 | 1177 | pg-numeric@1.0.2: 1178 | resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} 1179 | engines: {node: '>=4'} 1180 | 1181 | pg-pool@3.8.0: 1182 | resolution: {integrity: sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==} 1183 | peerDependencies: 1184 | pg: '>=8.0' 1185 | 1186 | pg-protocol@1.8.0: 1187 | resolution: {integrity: sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==} 1188 | 1189 | pg-types@2.2.0: 1190 | resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} 1191 | engines: {node: '>=4'} 1192 | 1193 | pg-types@4.0.2: 1194 | resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} 1195 | engines: {node: '>=10'} 1196 | 1197 | pg@8.14.0: 1198 | resolution: {integrity: sha512-nXbVpyoaXVmdqlKEzToFf37qzyeeh7mbiXsnoWvstSqohj88yaa/I/Rq/HEVn2QPSZEuLIJa/jSpRDyzjEx4FQ==} 1199 | engines: {node: '>= 8.0.0'} 1200 | peerDependencies: 1201 | pg-native: '>=3.0.1' 1202 | peerDependenciesMeta: 1203 | pg-native: 1204 | optional: true 1205 | 1206 | pgpass@1.0.5: 1207 | resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} 1208 | 1209 | postgres-array@2.0.0: 1210 | resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} 1211 | engines: {node: '>=4'} 1212 | 1213 | postgres-array@3.0.4: 1214 | resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==} 1215 | engines: {node: '>=12'} 1216 | 1217 | postgres-bytea@1.0.0: 1218 | resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} 1219 | engines: {node: '>=0.10.0'} 1220 | 1221 | postgres-bytea@3.0.0: 1222 | resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} 1223 | engines: {node: '>= 6'} 1224 | 1225 | postgres-date@1.0.7: 1226 | resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} 1227 | engines: {node: '>=0.10.0'} 1228 | 1229 | postgres-date@2.1.0: 1230 | resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} 1231 | engines: {node: '>=12'} 1232 | 1233 | postgres-interval@1.2.0: 1234 | resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} 1235 | engines: {node: '>=0.10.0'} 1236 | 1237 | postgres-interval@3.0.0: 1238 | resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} 1239 | engines: {node: '>=12'} 1240 | 1241 | postgres-range@1.1.4: 1242 | resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} 1243 | 1244 | printable-characters@1.0.42: 1245 | resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} 1246 | 1247 | react@19.0.0: 1248 | resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} 1249 | engines: {node: '>=0.10.0'} 1250 | 1251 | resolve-pkg-maps@1.0.0: 1252 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 1253 | 1254 | secure-json-parse@2.7.0: 1255 | resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} 1256 | 1257 | semver@7.7.1: 1258 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 1259 | engines: {node: '>=10'} 1260 | hasBin: true 1261 | 1262 | sharp@0.33.5: 1263 | resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} 1264 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 1265 | 1266 | shell-quote@1.8.2: 1267 | resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} 1268 | engines: {node: '>= 0.4'} 1269 | 1270 | simple-swizzle@0.2.2: 1271 | resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} 1272 | 1273 | source-map-support@0.5.21: 1274 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} 1275 | 1276 | source-map@0.6.1: 1277 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1278 | engines: {node: '>=0.10.0'} 1279 | 1280 | split2@4.2.0: 1281 | resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 1282 | engines: {node: '>= 10.x'} 1283 | 1284 | stacktracey@2.1.8: 1285 | resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} 1286 | 1287 | stoppable@1.1.0: 1288 | resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} 1289 | engines: {node: '>=4', npm: '>=6'} 1290 | 1291 | swr@2.3.3: 1292 | resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} 1293 | peerDependencies: 1294 | react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1295 | 1296 | throttleit@2.1.0: 1297 | resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} 1298 | engines: {node: '>=18'} 1299 | 1300 | tslib@2.8.1: 1301 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1302 | 1303 | tsx@4.19.3: 1304 | resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} 1305 | engines: {node: '>=18.0.0'} 1306 | hasBin: true 1307 | 1308 | ufo@1.5.4: 1309 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} 1310 | 1311 | undici-types@6.20.0: 1312 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 1313 | 1314 | undici@5.28.5: 1315 | resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==} 1316 | engines: {node: '>=14.0'} 1317 | 1318 | unenv@2.0.0-rc.14: 1319 | resolution: {integrity: sha512-od496pShMen7nOy5VmVJCnq8rptd45vh6Nx/r2iPbrba6pa6p+tS2ywuIHRZ/OBvSbQZB0kWvpO9XBNVFXHD3Q==} 1320 | 1321 | use-sync-external-store@1.4.0: 1322 | resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} 1323 | peerDependencies: 1324 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1325 | 1326 | uuid@11.1.0: 1327 | resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} 1328 | hasBin: true 1329 | 1330 | which@4.0.0: 1331 | resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} 1332 | engines: {node: ^16.13.0 || >=18.0.0} 1333 | hasBin: true 1334 | 1335 | workerd@1.20250310.0: 1336 | resolution: {integrity: sha512-bAaZ9Bmts3mArbIrXYAtr+ZRsAJAAUEsCtvwfBavIYXaZ5sgdEOJBEiBbvsHp6CsVObegOM85tIWpYLpbTxQrQ==} 1337 | engines: {node: '>=16'} 1338 | hasBin: true 1339 | 1340 | wrangler@4.0.0: 1341 | resolution: {integrity: sha512-9QqqoznS5sfLNqPKPkeEkwPAIe4lPfWLzPxVATmAbMQl4sh3/8iKEYSjZXQxdtcTgiS8iGOUbHq/rdiOFU8H1w==} 1342 | engines: {node: '>=18.0.0'} 1343 | hasBin: true 1344 | peerDependencies: 1345 | '@cloudflare/workers-types': ^4.20250310.0 1346 | peerDependenciesMeta: 1347 | '@cloudflare/workers-types': 1348 | optional: true 1349 | 1350 | ws@8.18.0: 1351 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 1352 | engines: {node: '>=10.0.0'} 1353 | peerDependencies: 1354 | bufferutil: ^4.0.1 1355 | utf-8-validate: '>=5.0.2' 1356 | peerDependenciesMeta: 1357 | bufferutil: 1358 | optional: true 1359 | utf-8-validate: 1360 | optional: true 1361 | 1362 | xtend@4.0.2: 1363 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 1364 | engines: {node: '>=0.4'} 1365 | 1366 | youch@3.2.3: 1367 | resolution: {integrity: sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==} 1368 | 1369 | zod-to-json-schema@3.24.4: 1370 | resolution: {integrity: sha512-0uNlcvgabyrni9Ag8Vghj21drk7+7tp7VTwwR7KxxXXc/3pbXz2PHlDgj3cICahgF1kHm4dExBFj7BXrZJXzig==} 1371 | peerDependencies: 1372 | zod: ^3.24.1 1373 | 1374 | zod@3.22.3: 1375 | resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} 1376 | 1377 | zod@3.24.2: 1378 | resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} 1379 | 1380 | snapshots: 1381 | 1382 | '@ai-sdk/openai@1.2.5(zod@3.24.2)': 1383 | dependencies: 1384 | '@ai-sdk/provider': 1.0.11 1385 | '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) 1386 | zod: 3.24.2 1387 | 1388 | '@ai-sdk/provider-utils@2.1.13(zod@3.24.2)': 1389 | dependencies: 1390 | '@ai-sdk/provider': 1.0.11 1391 | eventsource-parser: 3.0.0 1392 | nanoid: 3.3.10 1393 | secure-json-parse: 2.7.0 1394 | optionalDependencies: 1395 | zod: 3.24.2 1396 | 1397 | '@ai-sdk/provider@1.0.11': 1398 | dependencies: 1399 | json-schema: 0.4.0 1400 | 1401 | '@ai-sdk/react@1.1.23(react@19.0.0)(zod@3.24.2)': 1402 | dependencies: 1403 | '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) 1404 | '@ai-sdk/ui-utils': 1.1.19(zod@3.24.2) 1405 | swr: 2.3.3(react@19.0.0) 1406 | throttleit: 2.1.0 1407 | optionalDependencies: 1408 | react: 19.0.0 1409 | zod: 3.24.2 1410 | 1411 | '@ai-sdk/ui-utils@1.1.19(zod@3.24.2)': 1412 | dependencies: 1413 | '@ai-sdk/provider': 1.0.11 1414 | '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) 1415 | zod-to-json-schema: 3.24.4(zod@3.24.2) 1416 | optionalDependencies: 1417 | zod: 3.24.2 1418 | 1419 | '@cloudflare/kv-asset-handler@0.4.0': 1420 | dependencies: 1421 | mime: 3.0.0 1422 | 1423 | '@cloudflare/unenv-preset@2.0.2(unenv@2.0.0-rc.14)(workerd@1.20250310.0)': 1424 | dependencies: 1425 | unenv: 2.0.0-rc.14 1426 | optionalDependencies: 1427 | workerd: 1.20250310.0 1428 | 1429 | '@cloudflare/workerd-darwin-64@1.20250310.0': 1430 | optional: true 1431 | 1432 | '@cloudflare/workerd-darwin-arm64@1.20250310.0': 1433 | optional: true 1434 | 1435 | '@cloudflare/workerd-linux-64@1.20250310.0': 1436 | optional: true 1437 | 1438 | '@cloudflare/workerd-linux-arm64@1.20250310.0': 1439 | optional: true 1440 | 1441 | '@cloudflare/workerd-windows-64@1.20250310.0': 1442 | optional: true 1443 | 1444 | '@cloudflare/workers-types@4.20250313.0': {} 1445 | 1446 | '@cspotcode/source-map-support@0.8.1': 1447 | dependencies: 1448 | '@jridgewell/trace-mapping': 0.3.9 1449 | 1450 | '@drizzle-team/brocli@0.10.2': {} 1451 | 1452 | '@electric-sql/client@1.0.0-beta.5': 1453 | optionalDependencies: 1454 | '@rollup/rollup-darwin-arm64': 4.35.0 1455 | 1456 | '@emnapi/runtime@1.3.1': 1457 | dependencies: 1458 | tslib: 2.8.1 1459 | optional: true 1460 | 1461 | '@esbuild-kit/core-utils@3.3.2': 1462 | dependencies: 1463 | esbuild: 0.18.20 1464 | source-map-support: 0.5.21 1465 | 1466 | '@esbuild-kit/esm-loader@2.6.5': 1467 | dependencies: 1468 | '@esbuild-kit/core-utils': 3.3.2 1469 | get-tsconfig: 4.10.0 1470 | 1471 | '@esbuild/aix-ppc64@0.19.12': 1472 | optional: true 1473 | 1474 | '@esbuild/aix-ppc64@0.24.2': 1475 | optional: true 1476 | 1477 | '@esbuild/aix-ppc64@0.25.1': 1478 | optional: true 1479 | 1480 | '@esbuild/android-arm64@0.18.20': 1481 | optional: true 1482 | 1483 | '@esbuild/android-arm64@0.19.12': 1484 | optional: true 1485 | 1486 | '@esbuild/android-arm64@0.24.2': 1487 | optional: true 1488 | 1489 | '@esbuild/android-arm64@0.25.1': 1490 | optional: true 1491 | 1492 | '@esbuild/android-arm@0.18.20': 1493 | optional: true 1494 | 1495 | '@esbuild/android-arm@0.19.12': 1496 | optional: true 1497 | 1498 | '@esbuild/android-arm@0.24.2': 1499 | optional: true 1500 | 1501 | '@esbuild/android-arm@0.25.1': 1502 | optional: true 1503 | 1504 | '@esbuild/android-x64@0.18.20': 1505 | optional: true 1506 | 1507 | '@esbuild/android-x64@0.19.12': 1508 | optional: true 1509 | 1510 | '@esbuild/android-x64@0.24.2': 1511 | optional: true 1512 | 1513 | '@esbuild/android-x64@0.25.1': 1514 | optional: true 1515 | 1516 | '@esbuild/darwin-arm64@0.18.20': 1517 | optional: true 1518 | 1519 | '@esbuild/darwin-arm64@0.19.12': 1520 | optional: true 1521 | 1522 | '@esbuild/darwin-arm64@0.24.2': 1523 | optional: true 1524 | 1525 | '@esbuild/darwin-arm64@0.25.1': 1526 | optional: true 1527 | 1528 | '@esbuild/darwin-x64@0.18.20': 1529 | optional: true 1530 | 1531 | '@esbuild/darwin-x64@0.19.12': 1532 | optional: true 1533 | 1534 | '@esbuild/darwin-x64@0.24.2': 1535 | optional: true 1536 | 1537 | '@esbuild/darwin-x64@0.25.1': 1538 | optional: true 1539 | 1540 | '@esbuild/freebsd-arm64@0.18.20': 1541 | optional: true 1542 | 1543 | '@esbuild/freebsd-arm64@0.19.12': 1544 | optional: true 1545 | 1546 | '@esbuild/freebsd-arm64@0.24.2': 1547 | optional: true 1548 | 1549 | '@esbuild/freebsd-arm64@0.25.1': 1550 | optional: true 1551 | 1552 | '@esbuild/freebsd-x64@0.18.20': 1553 | optional: true 1554 | 1555 | '@esbuild/freebsd-x64@0.19.12': 1556 | optional: true 1557 | 1558 | '@esbuild/freebsd-x64@0.24.2': 1559 | optional: true 1560 | 1561 | '@esbuild/freebsd-x64@0.25.1': 1562 | optional: true 1563 | 1564 | '@esbuild/linux-arm64@0.18.20': 1565 | optional: true 1566 | 1567 | '@esbuild/linux-arm64@0.19.12': 1568 | optional: true 1569 | 1570 | '@esbuild/linux-arm64@0.24.2': 1571 | optional: true 1572 | 1573 | '@esbuild/linux-arm64@0.25.1': 1574 | optional: true 1575 | 1576 | '@esbuild/linux-arm@0.18.20': 1577 | optional: true 1578 | 1579 | '@esbuild/linux-arm@0.19.12': 1580 | optional: true 1581 | 1582 | '@esbuild/linux-arm@0.24.2': 1583 | optional: true 1584 | 1585 | '@esbuild/linux-arm@0.25.1': 1586 | optional: true 1587 | 1588 | '@esbuild/linux-ia32@0.18.20': 1589 | optional: true 1590 | 1591 | '@esbuild/linux-ia32@0.19.12': 1592 | optional: true 1593 | 1594 | '@esbuild/linux-ia32@0.24.2': 1595 | optional: true 1596 | 1597 | '@esbuild/linux-ia32@0.25.1': 1598 | optional: true 1599 | 1600 | '@esbuild/linux-loong64@0.18.20': 1601 | optional: true 1602 | 1603 | '@esbuild/linux-loong64@0.19.12': 1604 | optional: true 1605 | 1606 | '@esbuild/linux-loong64@0.24.2': 1607 | optional: true 1608 | 1609 | '@esbuild/linux-loong64@0.25.1': 1610 | optional: true 1611 | 1612 | '@esbuild/linux-mips64el@0.18.20': 1613 | optional: true 1614 | 1615 | '@esbuild/linux-mips64el@0.19.12': 1616 | optional: true 1617 | 1618 | '@esbuild/linux-mips64el@0.24.2': 1619 | optional: true 1620 | 1621 | '@esbuild/linux-mips64el@0.25.1': 1622 | optional: true 1623 | 1624 | '@esbuild/linux-ppc64@0.18.20': 1625 | optional: true 1626 | 1627 | '@esbuild/linux-ppc64@0.19.12': 1628 | optional: true 1629 | 1630 | '@esbuild/linux-ppc64@0.24.2': 1631 | optional: true 1632 | 1633 | '@esbuild/linux-ppc64@0.25.1': 1634 | optional: true 1635 | 1636 | '@esbuild/linux-riscv64@0.18.20': 1637 | optional: true 1638 | 1639 | '@esbuild/linux-riscv64@0.19.12': 1640 | optional: true 1641 | 1642 | '@esbuild/linux-riscv64@0.24.2': 1643 | optional: true 1644 | 1645 | '@esbuild/linux-riscv64@0.25.1': 1646 | optional: true 1647 | 1648 | '@esbuild/linux-s390x@0.18.20': 1649 | optional: true 1650 | 1651 | '@esbuild/linux-s390x@0.19.12': 1652 | optional: true 1653 | 1654 | '@esbuild/linux-s390x@0.24.2': 1655 | optional: true 1656 | 1657 | '@esbuild/linux-s390x@0.25.1': 1658 | optional: true 1659 | 1660 | '@esbuild/linux-x64@0.18.20': 1661 | optional: true 1662 | 1663 | '@esbuild/linux-x64@0.19.12': 1664 | optional: true 1665 | 1666 | '@esbuild/linux-x64@0.24.2': 1667 | optional: true 1668 | 1669 | '@esbuild/linux-x64@0.25.1': 1670 | optional: true 1671 | 1672 | '@esbuild/netbsd-arm64@0.24.2': 1673 | optional: true 1674 | 1675 | '@esbuild/netbsd-arm64@0.25.1': 1676 | optional: true 1677 | 1678 | '@esbuild/netbsd-x64@0.18.20': 1679 | optional: true 1680 | 1681 | '@esbuild/netbsd-x64@0.19.12': 1682 | optional: true 1683 | 1684 | '@esbuild/netbsd-x64@0.24.2': 1685 | optional: true 1686 | 1687 | '@esbuild/netbsd-x64@0.25.1': 1688 | optional: true 1689 | 1690 | '@esbuild/openbsd-arm64@0.24.2': 1691 | optional: true 1692 | 1693 | '@esbuild/openbsd-arm64@0.25.1': 1694 | optional: true 1695 | 1696 | '@esbuild/openbsd-x64@0.18.20': 1697 | optional: true 1698 | 1699 | '@esbuild/openbsd-x64@0.19.12': 1700 | optional: true 1701 | 1702 | '@esbuild/openbsd-x64@0.24.2': 1703 | optional: true 1704 | 1705 | '@esbuild/openbsd-x64@0.25.1': 1706 | optional: true 1707 | 1708 | '@esbuild/sunos-x64@0.18.20': 1709 | optional: true 1710 | 1711 | '@esbuild/sunos-x64@0.19.12': 1712 | optional: true 1713 | 1714 | '@esbuild/sunos-x64@0.24.2': 1715 | optional: true 1716 | 1717 | '@esbuild/sunos-x64@0.25.1': 1718 | optional: true 1719 | 1720 | '@esbuild/win32-arm64@0.18.20': 1721 | optional: true 1722 | 1723 | '@esbuild/win32-arm64@0.19.12': 1724 | optional: true 1725 | 1726 | '@esbuild/win32-arm64@0.24.2': 1727 | optional: true 1728 | 1729 | '@esbuild/win32-arm64@0.25.1': 1730 | optional: true 1731 | 1732 | '@esbuild/win32-ia32@0.18.20': 1733 | optional: true 1734 | 1735 | '@esbuild/win32-ia32@0.19.12': 1736 | optional: true 1737 | 1738 | '@esbuild/win32-ia32@0.24.2': 1739 | optional: true 1740 | 1741 | '@esbuild/win32-ia32@0.25.1': 1742 | optional: true 1743 | 1744 | '@esbuild/win32-x64@0.18.20': 1745 | optional: true 1746 | 1747 | '@esbuild/win32-x64@0.19.12': 1748 | optional: true 1749 | 1750 | '@esbuild/win32-x64@0.24.2': 1751 | optional: true 1752 | 1753 | '@esbuild/win32-x64@0.25.1': 1754 | optional: true 1755 | 1756 | '@fastify/busboy@2.1.1': {} 1757 | 1758 | '@img/sharp-darwin-arm64@0.33.5': 1759 | optionalDependencies: 1760 | '@img/sharp-libvips-darwin-arm64': 1.0.4 1761 | optional: true 1762 | 1763 | '@img/sharp-darwin-x64@0.33.5': 1764 | optionalDependencies: 1765 | '@img/sharp-libvips-darwin-x64': 1.0.4 1766 | optional: true 1767 | 1768 | '@img/sharp-libvips-darwin-arm64@1.0.4': 1769 | optional: true 1770 | 1771 | '@img/sharp-libvips-darwin-x64@1.0.4': 1772 | optional: true 1773 | 1774 | '@img/sharp-libvips-linux-arm64@1.0.4': 1775 | optional: true 1776 | 1777 | '@img/sharp-libvips-linux-arm@1.0.5': 1778 | optional: true 1779 | 1780 | '@img/sharp-libvips-linux-s390x@1.0.4': 1781 | optional: true 1782 | 1783 | '@img/sharp-libvips-linux-x64@1.0.4': 1784 | optional: true 1785 | 1786 | '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 1787 | optional: true 1788 | 1789 | '@img/sharp-libvips-linuxmusl-x64@1.0.4': 1790 | optional: true 1791 | 1792 | '@img/sharp-linux-arm64@0.33.5': 1793 | optionalDependencies: 1794 | '@img/sharp-libvips-linux-arm64': 1.0.4 1795 | optional: true 1796 | 1797 | '@img/sharp-linux-arm@0.33.5': 1798 | optionalDependencies: 1799 | '@img/sharp-libvips-linux-arm': 1.0.5 1800 | optional: true 1801 | 1802 | '@img/sharp-linux-s390x@0.33.5': 1803 | optionalDependencies: 1804 | '@img/sharp-libvips-linux-s390x': 1.0.4 1805 | optional: true 1806 | 1807 | '@img/sharp-linux-x64@0.33.5': 1808 | optionalDependencies: 1809 | '@img/sharp-libvips-linux-x64': 1.0.4 1810 | optional: true 1811 | 1812 | '@img/sharp-linuxmusl-arm64@0.33.5': 1813 | optionalDependencies: 1814 | '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 1815 | optional: true 1816 | 1817 | '@img/sharp-linuxmusl-x64@0.33.5': 1818 | optionalDependencies: 1819 | '@img/sharp-libvips-linuxmusl-x64': 1.0.4 1820 | optional: true 1821 | 1822 | '@img/sharp-wasm32@0.33.5': 1823 | dependencies: 1824 | '@emnapi/runtime': 1.3.1 1825 | optional: true 1826 | 1827 | '@img/sharp-win32-ia32@0.33.5': 1828 | optional: true 1829 | 1830 | '@img/sharp-win32-x64@0.33.5': 1831 | optional: true 1832 | 1833 | '@jridgewell/resolve-uri@3.1.2': {} 1834 | 1835 | '@jridgewell/sourcemap-codec@1.5.0': {} 1836 | 1837 | '@jridgewell/trace-mapping@0.3.9': 1838 | dependencies: 1839 | '@jridgewell/resolve-uri': 3.1.2 1840 | '@jridgewell/sourcemap-codec': 1.5.0 1841 | 1842 | '@opentelemetry/api@1.9.0': {} 1843 | 1844 | '@petamoriken/float16@3.9.2': {} 1845 | 1846 | '@rollup/rollup-darwin-arm64@4.35.0': 1847 | optional: true 1848 | 1849 | '@types/diff-match-patch@1.0.36': {} 1850 | 1851 | '@types/node@22.13.10': 1852 | dependencies: 1853 | undici-types: 6.20.0 1854 | 1855 | '@types/pg@8.11.11': 1856 | dependencies: 1857 | '@types/node': 22.13.10 1858 | pg-protocol: 1.8.0 1859 | pg-types: 4.0.2 1860 | 1861 | '@types/uuid@10.0.0': {} 1862 | 1863 | acorn-walk@8.3.2: {} 1864 | 1865 | acorn@8.14.0: {} 1866 | 1867 | ai@4.1.61(react@19.0.0)(zod@3.24.2): 1868 | dependencies: 1869 | '@ai-sdk/provider': 1.0.11 1870 | '@ai-sdk/provider-utils': 2.1.13(zod@3.24.2) 1871 | '@ai-sdk/react': 1.1.23(react@19.0.0)(zod@3.24.2) 1872 | '@ai-sdk/ui-utils': 1.1.19(zod@3.24.2) 1873 | '@opentelemetry/api': 1.9.0 1874 | eventsource-parser: 3.0.0 1875 | jsondiffpatch: 0.6.0 1876 | optionalDependencies: 1877 | react: 19.0.0 1878 | zod: 3.24.2 1879 | 1880 | as-table@1.0.55: 1881 | dependencies: 1882 | printable-characters: 1.0.42 1883 | 1884 | blake3-wasm@2.1.5: {} 1885 | 1886 | buffer-from@1.1.2: {} 1887 | 1888 | chalk@5.4.1: {} 1889 | 1890 | color-convert@2.0.1: 1891 | dependencies: 1892 | color-name: 1.1.4 1893 | optional: true 1894 | 1895 | color-name@1.1.4: 1896 | optional: true 1897 | 1898 | color-string@1.9.1: 1899 | dependencies: 1900 | color-name: 1.1.4 1901 | simple-swizzle: 0.2.2 1902 | optional: true 1903 | 1904 | color@4.2.3: 1905 | dependencies: 1906 | color-convert: 2.0.1 1907 | color-string: 1.9.1 1908 | optional: true 1909 | 1910 | cookie@0.5.0: {} 1911 | 1912 | data-uri-to-buffer@2.0.2: {} 1913 | 1914 | debug@4.4.0: 1915 | dependencies: 1916 | ms: 2.1.3 1917 | 1918 | defu@6.1.4: {} 1919 | 1920 | dequal@2.0.3: {} 1921 | 1922 | detect-libc@2.0.3: 1923 | optional: true 1924 | 1925 | diff-match-patch@1.0.5: {} 1926 | 1927 | dotenv@16.4.7: {} 1928 | 1929 | drizzle-kit@0.30.5: 1930 | dependencies: 1931 | '@drizzle-team/brocli': 0.10.2 1932 | '@esbuild-kit/esm-loader': 2.6.5 1933 | esbuild: 0.19.12 1934 | esbuild-register: 3.6.0(esbuild@0.19.12) 1935 | gel: 2.0.1 1936 | transitivePeerDependencies: 1937 | - supports-color 1938 | 1939 | drizzle-orm@0.40.0(@cloudflare/workers-types@4.20250313.0)(@opentelemetry/api@1.9.0)(@types/pg@8.11.11)(gel@2.0.1)(pg@8.14.0): 1940 | optionalDependencies: 1941 | '@cloudflare/workers-types': 4.20250313.0 1942 | '@opentelemetry/api': 1.9.0 1943 | '@types/pg': 8.11.11 1944 | gel: 2.0.1 1945 | pg: 8.14.0 1946 | 1947 | env-paths@3.0.0: {} 1948 | 1949 | esbuild-register@3.6.0(esbuild@0.19.12): 1950 | dependencies: 1951 | debug: 4.4.0 1952 | esbuild: 0.19.12 1953 | transitivePeerDependencies: 1954 | - supports-color 1955 | 1956 | esbuild@0.18.20: 1957 | optionalDependencies: 1958 | '@esbuild/android-arm': 0.18.20 1959 | '@esbuild/android-arm64': 0.18.20 1960 | '@esbuild/android-x64': 0.18.20 1961 | '@esbuild/darwin-arm64': 0.18.20 1962 | '@esbuild/darwin-x64': 0.18.20 1963 | '@esbuild/freebsd-arm64': 0.18.20 1964 | '@esbuild/freebsd-x64': 0.18.20 1965 | '@esbuild/linux-arm': 0.18.20 1966 | '@esbuild/linux-arm64': 0.18.20 1967 | '@esbuild/linux-ia32': 0.18.20 1968 | '@esbuild/linux-loong64': 0.18.20 1969 | '@esbuild/linux-mips64el': 0.18.20 1970 | '@esbuild/linux-ppc64': 0.18.20 1971 | '@esbuild/linux-riscv64': 0.18.20 1972 | '@esbuild/linux-s390x': 0.18.20 1973 | '@esbuild/linux-x64': 0.18.20 1974 | '@esbuild/netbsd-x64': 0.18.20 1975 | '@esbuild/openbsd-x64': 0.18.20 1976 | '@esbuild/sunos-x64': 0.18.20 1977 | '@esbuild/win32-arm64': 0.18.20 1978 | '@esbuild/win32-ia32': 0.18.20 1979 | '@esbuild/win32-x64': 0.18.20 1980 | 1981 | esbuild@0.19.12: 1982 | optionalDependencies: 1983 | '@esbuild/aix-ppc64': 0.19.12 1984 | '@esbuild/android-arm': 0.19.12 1985 | '@esbuild/android-arm64': 0.19.12 1986 | '@esbuild/android-x64': 0.19.12 1987 | '@esbuild/darwin-arm64': 0.19.12 1988 | '@esbuild/darwin-x64': 0.19.12 1989 | '@esbuild/freebsd-arm64': 0.19.12 1990 | '@esbuild/freebsd-x64': 0.19.12 1991 | '@esbuild/linux-arm': 0.19.12 1992 | '@esbuild/linux-arm64': 0.19.12 1993 | '@esbuild/linux-ia32': 0.19.12 1994 | '@esbuild/linux-loong64': 0.19.12 1995 | '@esbuild/linux-mips64el': 0.19.12 1996 | '@esbuild/linux-ppc64': 0.19.12 1997 | '@esbuild/linux-riscv64': 0.19.12 1998 | '@esbuild/linux-s390x': 0.19.12 1999 | '@esbuild/linux-x64': 0.19.12 2000 | '@esbuild/netbsd-x64': 0.19.12 2001 | '@esbuild/openbsd-x64': 0.19.12 2002 | '@esbuild/sunos-x64': 0.19.12 2003 | '@esbuild/win32-arm64': 0.19.12 2004 | '@esbuild/win32-ia32': 0.19.12 2005 | '@esbuild/win32-x64': 0.19.12 2006 | 2007 | esbuild@0.24.2: 2008 | optionalDependencies: 2009 | '@esbuild/aix-ppc64': 0.24.2 2010 | '@esbuild/android-arm': 0.24.2 2011 | '@esbuild/android-arm64': 0.24.2 2012 | '@esbuild/android-x64': 0.24.2 2013 | '@esbuild/darwin-arm64': 0.24.2 2014 | '@esbuild/darwin-x64': 0.24.2 2015 | '@esbuild/freebsd-arm64': 0.24.2 2016 | '@esbuild/freebsd-x64': 0.24.2 2017 | '@esbuild/linux-arm': 0.24.2 2018 | '@esbuild/linux-arm64': 0.24.2 2019 | '@esbuild/linux-ia32': 0.24.2 2020 | '@esbuild/linux-loong64': 0.24.2 2021 | '@esbuild/linux-mips64el': 0.24.2 2022 | '@esbuild/linux-ppc64': 0.24.2 2023 | '@esbuild/linux-riscv64': 0.24.2 2024 | '@esbuild/linux-s390x': 0.24.2 2025 | '@esbuild/linux-x64': 0.24.2 2026 | '@esbuild/netbsd-arm64': 0.24.2 2027 | '@esbuild/netbsd-x64': 0.24.2 2028 | '@esbuild/openbsd-arm64': 0.24.2 2029 | '@esbuild/openbsd-x64': 0.24.2 2030 | '@esbuild/sunos-x64': 0.24.2 2031 | '@esbuild/win32-arm64': 0.24.2 2032 | '@esbuild/win32-ia32': 0.24.2 2033 | '@esbuild/win32-x64': 0.24.2 2034 | 2035 | esbuild@0.25.1: 2036 | optionalDependencies: 2037 | '@esbuild/aix-ppc64': 0.25.1 2038 | '@esbuild/android-arm': 0.25.1 2039 | '@esbuild/android-arm64': 0.25.1 2040 | '@esbuild/android-x64': 0.25.1 2041 | '@esbuild/darwin-arm64': 0.25.1 2042 | '@esbuild/darwin-x64': 0.25.1 2043 | '@esbuild/freebsd-arm64': 0.25.1 2044 | '@esbuild/freebsd-x64': 0.25.1 2045 | '@esbuild/linux-arm': 0.25.1 2046 | '@esbuild/linux-arm64': 0.25.1 2047 | '@esbuild/linux-ia32': 0.25.1 2048 | '@esbuild/linux-loong64': 0.25.1 2049 | '@esbuild/linux-mips64el': 0.25.1 2050 | '@esbuild/linux-ppc64': 0.25.1 2051 | '@esbuild/linux-riscv64': 0.25.1 2052 | '@esbuild/linux-s390x': 0.25.1 2053 | '@esbuild/linux-x64': 0.25.1 2054 | '@esbuild/netbsd-arm64': 0.25.1 2055 | '@esbuild/netbsd-x64': 0.25.1 2056 | '@esbuild/openbsd-arm64': 0.25.1 2057 | '@esbuild/openbsd-x64': 0.25.1 2058 | '@esbuild/sunos-x64': 0.25.1 2059 | '@esbuild/win32-arm64': 0.25.1 2060 | '@esbuild/win32-ia32': 0.25.1 2061 | '@esbuild/win32-x64': 0.25.1 2062 | 2063 | eventsource-parser@3.0.0: {} 2064 | 2065 | exit-hook@2.2.1: {} 2066 | 2067 | exsolve@1.0.4: {} 2068 | 2069 | fsevents@2.3.3: 2070 | optional: true 2071 | 2072 | gel@2.0.1: 2073 | dependencies: 2074 | '@petamoriken/float16': 3.9.2 2075 | debug: 4.4.0 2076 | env-paths: 3.0.0 2077 | semver: 7.7.1 2078 | shell-quote: 1.8.2 2079 | which: 4.0.0 2080 | transitivePeerDependencies: 2081 | - supports-color 2082 | 2083 | get-source@2.0.12: 2084 | dependencies: 2085 | data-uri-to-buffer: 2.0.2 2086 | source-map: 0.6.1 2087 | 2088 | get-tsconfig@4.10.0: 2089 | dependencies: 2090 | resolve-pkg-maps: 1.0.0 2091 | 2092 | glob-to-regexp@0.4.1: {} 2093 | 2094 | hono@4.7.4: {} 2095 | 2096 | is-arrayish@0.3.2: 2097 | optional: true 2098 | 2099 | isexe@3.1.1: {} 2100 | 2101 | json-schema@0.4.0: {} 2102 | 2103 | jsondiffpatch@0.6.0: 2104 | dependencies: 2105 | '@types/diff-match-patch': 1.0.36 2106 | chalk: 5.4.1 2107 | diff-match-patch: 1.0.5 2108 | 2109 | mime@3.0.0: {} 2110 | 2111 | miniflare@4.20250310.0: 2112 | dependencies: 2113 | '@cspotcode/source-map-support': 0.8.1 2114 | acorn: 8.14.0 2115 | acorn-walk: 8.3.2 2116 | exit-hook: 2.2.1 2117 | glob-to-regexp: 0.4.1 2118 | stoppable: 1.1.0 2119 | undici: 5.28.5 2120 | workerd: 1.20250310.0 2121 | ws: 8.18.0 2122 | youch: 3.2.3 2123 | zod: 3.22.3 2124 | transitivePeerDependencies: 2125 | - bufferutil 2126 | - utf-8-validate 2127 | 2128 | ms@2.1.3: {} 2129 | 2130 | mustache@4.2.0: {} 2131 | 2132 | nanoid@3.3.10: {} 2133 | 2134 | obuf@1.1.2: {} 2135 | 2136 | ohash@2.0.11: {} 2137 | 2138 | path-to-regexp@6.3.0: {} 2139 | 2140 | pathe@2.0.3: {} 2141 | 2142 | pg-cloudflare@1.1.1: 2143 | optional: true 2144 | 2145 | pg-connection-string@2.7.0: {} 2146 | 2147 | pg-int8@1.0.1: {} 2148 | 2149 | pg-numeric@1.0.2: {} 2150 | 2151 | pg-pool@3.8.0(pg@8.14.0): 2152 | dependencies: 2153 | pg: 8.14.0 2154 | 2155 | pg-protocol@1.8.0: {} 2156 | 2157 | pg-types@2.2.0: 2158 | dependencies: 2159 | pg-int8: 1.0.1 2160 | postgres-array: 2.0.0 2161 | postgres-bytea: 1.0.0 2162 | postgres-date: 1.0.7 2163 | postgres-interval: 1.2.0 2164 | 2165 | pg-types@4.0.2: 2166 | dependencies: 2167 | pg-int8: 1.0.1 2168 | pg-numeric: 1.0.2 2169 | postgres-array: 3.0.4 2170 | postgres-bytea: 3.0.0 2171 | postgres-date: 2.1.0 2172 | postgres-interval: 3.0.0 2173 | postgres-range: 1.1.4 2174 | 2175 | pg@8.14.0: 2176 | dependencies: 2177 | pg-connection-string: 2.7.0 2178 | pg-pool: 3.8.0(pg@8.14.0) 2179 | pg-protocol: 1.8.0 2180 | pg-types: 2.2.0 2181 | pgpass: 1.0.5 2182 | optionalDependencies: 2183 | pg-cloudflare: 1.1.1 2184 | 2185 | pgpass@1.0.5: 2186 | dependencies: 2187 | split2: 4.2.0 2188 | 2189 | postgres-array@2.0.0: {} 2190 | 2191 | postgres-array@3.0.4: {} 2192 | 2193 | postgres-bytea@1.0.0: {} 2194 | 2195 | postgres-bytea@3.0.0: 2196 | dependencies: 2197 | obuf: 1.1.2 2198 | 2199 | postgres-date@1.0.7: {} 2200 | 2201 | postgres-date@2.1.0: {} 2202 | 2203 | postgres-interval@1.2.0: 2204 | dependencies: 2205 | xtend: 4.0.2 2206 | 2207 | postgres-interval@3.0.0: {} 2208 | 2209 | postgres-range@1.1.4: {} 2210 | 2211 | printable-characters@1.0.42: {} 2212 | 2213 | react@19.0.0: {} 2214 | 2215 | resolve-pkg-maps@1.0.0: {} 2216 | 2217 | secure-json-parse@2.7.0: {} 2218 | 2219 | semver@7.7.1: {} 2220 | 2221 | sharp@0.33.5: 2222 | dependencies: 2223 | color: 4.2.3 2224 | detect-libc: 2.0.3 2225 | semver: 7.7.1 2226 | optionalDependencies: 2227 | '@img/sharp-darwin-arm64': 0.33.5 2228 | '@img/sharp-darwin-x64': 0.33.5 2229 | '@img/sharp-libvips-darwin-arm64': 1.0.4 2230 | '@img/sharp-libvips-darwin-x64': 1.0.4 2231 | '@img/sharp-libvips-linux-arm': 1.0.5 2232 | '@img/sharp-libvips-linux-arm64': 1.0.4 2233 | '@img/sharp-libvips-linux-s390x': 1.0.4 2234 | '@img/sharp-libvips-linux-x64': 1.0.4 2235 | '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 2236 | '@img/sharp-libvips-linuxmusl-x64': 1.0.4 2237 | '@img/sharp-linux-arm': 0.33.5 2238 | '@img/sharp-linux-arm64': 0.33.5 2239 | '@img/sharp-linux-s390x': 0.33.5 2240 | '@img/sharp-linux-x64': 0.33.5 2241 | '@img/sharp-linuxmusl-arm64': 0.33.5 2242 | '@img/sharp-linuxmusl-x64': 0.33.5 2243 | '@img/sharp-wasm32': 0.33.5 2244 | '@img/sharp-win32-ia32': 0.33.5 2245 | '@img/sharp-win32-x64': 0.33.5 2246 | optional: true 2247 | 2248 | shell-quote@1.8.2: {} 2249 | 2250 | simple-swizzle@0.2.2: 2251 | dependencies: 2252 | is-arrayish: 0.3.2 2253 | optional: true 2254 | 2255 | source-map-support@0.5.21: 2256 | dependencies: 2257 | buffer-from: 1.1.2 2258 | source-map: 0.6.1 2259 | 2260 | source-map@0.6.1: {} 2261 | 2262 | split2@4.2.0: {} 2263 | 2264 | stacktracey@2.1.8: 2265 | dependencies: 2266 | as-table: 1.0.55 2267 | get-source: 2.0.12 2268 | 2269 | stoppable@1.1.0: {} 2270 | 2271 | swr@2.3.3(react@19.0.0): 2272 | dependencies: 2273 | dequal: 2.0.3 2274 | react: 19.0.0 2275 | use-sync-external-store: 1.4.0(react@19.0.0) 2276 | 2277 | throttleit@2.1.0: {} 2278 | 2279 | tslib@2.8.1: 2280 | optional: true 2281 | 2282 | tsx@4.19.3: 2283 | dependencies: 2284 | esbuild: 0.25.1 2285 | get-tsconfig: 4.10.0 2286 | optionalDependencies: 2287 | fsevents: 2.3.3 2288 | 2289 | ufo@1.5.4: {} 2290 | 2291 | undici-types@6.20.0: {} 2292 | 2293 | undici@5.28.5: 2294 | dependencies: 2295 | '@fastify/busboy': 2.1.1 2296 | 2297 | unenv@2.0.0-rc.14: 2298 | dependencies: 2299 | defu: 6.1.4 2300 | exsolve: 1.0.4 2301 | ohash: 2.0.11 2302 | pathe: 2.0.3 2303 | ufo: 1.5.4 2304 | 2305 | use-sync-external-store@1.4.0(react@19.0.0): 2306 | dependencies: 2307 | react: 19.0.0 2308 | 2309 | uuid@11.1.0: {} 2310 | 2311 | which@4.0.0: 2312 | dependencies: 2313 | isexe: 3.1.1 2314 | 2315 | workerd@1.20250310.0: 2316 | optionalDependencies: 2317 | '@cloudflare/workerd-darwin-64': 1.20250310.0 2318 | '@cloudflare/workerd-darwin-arm64': 1.20250310.0 2319 | '@cloudflare/workerd-linux-64': 1.20250310.0 2320 | '@cloudflare/workerd-linux-arm64': 1.20250310.0 2321 | '@cloudflare/workerd-windows-64': 1.20250310.0 2322 | 2323 | wrangler@4.0.0(@cloudflare/workers-types@4.20250313.0): 2324 | dependencies: 2325 | '@cloudflare/kv-asset-handler': 0.4.0 2326 | '@cloudflare/unenv-preset': 2.0.2(unenv@2.0.0-rc.14)(workerd@1.20250310.0) 2327 | blake3-wasm: 2.1.5 2328 | esbuild: 0.24.2 2329 | miniflare: 4.20250310.0 2330 | path-to-regexp: 6.3.0 2331 | unenv: 2.0.0-rc.14 2332 | workerd: 1.20250310.0 2333 | optionalDependencies: 2334 | '@cloudflare/workers-types': 4.20250313.0 2335 | fsevents: 2.3.3 2336 | sharp: 0.33.5 2337 | transitivePeerDependencies: 2338 | - bufferutil 2339 | - utf-8-validate 2340 | 2341 | ws@8.18.0: {} 2342 | 2343 | xtend@4.0.2: {} 2344 | 2345 | youch@3.2.3: 2346 | dependencies: 2347 | cookie: 0.5.0 2348 | mustache: 4.2.0 2349 | stacktracey: 2.1.8 2350 | 2351 | zod-to-json-schema@3.24.4(zod@3.24.2): 2352 | dependencies: 2353 | zod: 3.24.2 2354 | 2355 | zod@3.22.3: {} 2356 | 2357 | zod@3.24.2: {} 2358 | -------------------------------------------------------------------------------- /worker/src/db/schema.ts: -------------------------------------------------------------------------------- 1 | import { InferSelectModel } from "drizzle-orm"; 2 | import { 3 | index, 4 | integer, 5 | pgTable, 6 | primaryKey, 7 | varchar, 8 | } from "drizzle-orm/pg-core"; 9 | 10 | export const threadsTable = pgTable( 11 | "threads", 12 | { 13 | thread_id: varchar("thread_id", { length: 255 }).notNull(), 14 | sequence: integer("sequence").notNull(), 15 | payload: varchar("payload", { length: 65536 }).notNull(), 16 | }, 17 | (table) => ({ 18 | pk: primaryKey({ columns: [table.thread_id, table.sequence] }), 19 | threadIdSequenceIdx: index("threads_thread_id_sequence_idx").on( 20 | table.thread_id, 21 | table.sequence 22 | ), 23 | }) 24 | ); 25 | 26 | export type ThreadStreamChunksTableRow = InferSelectModel; 27 | -------------------------------------------------------------------------------- /worker/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from "hono"; 2 | import { ShapeStream } from "@electric-sql/client"; 3 | import { threadsTable, ThreadStreamChunksTableRow } from "./db/schema"; 4 | import { streamText } from "ai"; 5 | import { createOpenAI } from "@ai-sdk/openai"; 6 | import { cors } from "hono/cors"; 7 | import { drizzle } from "drizzle-orm/node-postgres"; 8 | import { sql } from "drizzle-orm"; 9 | import { chunkByLineStream } from "./util/splitByLineStream"; 10 | 11 | type Bindings = { 12 | OPENAI_API_KEY: string; 13 | DATABASE_URL: string; 14 | ELECTRIC_URL: string; 15 | }; 16 | 17 | const app = new Hono<{ Bindings: Bindings }>(); 18 | 19 | app.use(cors()); 20 | 21 | const insertPayload = ( 22 | db: ReturnType, 23 | thread_id: string, 24 | payload: unknown 25 | ) => { 26 | return db.insert(threadsTable).values({ 27 | thread_id, 28 | sequence: sql`(SELECT COALESCE(MAX(sequence), -1) + 1 FROM ${threadsTable} WHERE ${threadsTable.thread_id} = ${thread_id})`, 29 | payload: JSON.stringify(payload), 30 | }); 31 | }; 32 | 33 | app.post("/api/chat", async (c) => { 34 | const { thread_id, messages } = await c.req.json(); 35 | 36 | const userMessage = messages.at(-1); 37 | const openai = createOpenAI({ 38 | apiKey: c.env.OPENAI_API_KEY, 39 | }); 40 | 41 | const db = drizzle(c.env.DATABASE_URL); 42 | 43 | const result = streamText({ 44 | model: openai("gpt-4o-mini"), 45 | messages, 46 | }); 47 | 48 | c.executionCtx.waitUntil( 49 | result 50 | .toDataStream() 51 | .pipeThrough(new TextDecoderStream()) 52 | .pipeThrough(chunkByLineStream()) 53 | .pipeTo( 54 | new WritableStream({ 55 | start: async () => { 56 | // append the user message 57 | await insertPayload(db, thread_id, { 58 | type: "message", 59 | message: userMessage, 60 | }); 61 | }, 62 | write: async (chunk) => { 63 | await insertPayload(db, thread_id, { type: "ai-chunk", chunk }); 64 | }, 65 | }) 66 | ) 67 | ); 68 | 69 | return result.toDataStreamResponse(); 70 | }); 71 | 72 | export default app; 73 | -------------------------------------------------------------------------------- /worker/src/util/splitByLineStream.ts: -------------------------------------------------------------------------------- 1 | export function chunkByLineStream() { 2 | let buffer = ""; 3 | 4 | return new TransformStream({ 5 | transform(chunk, controller) { 6 | buffer += chunk; 7 | const lines = buffer.split("\n"); 8 | 9 | // Process all complete lines 10 | for (let i = 0; i < lines.length - 1; i++) { 11 | controller.enqueue(lines[i]); 12 | } 13 | 14 | // Keep the last incomplete line in the buffer 15 | buffer = lines[lines.length - 1]!; 16 | }, 17 | flush(controller) { 18 | // flush any remaining content in the buffer 19 | if (buffer) { 20 | controller.enqueue(buffer); 21 | } 22 | }, 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /worker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "strict": true, 7 | "skipLibCheck": true, 8 | "lib": [ 9 | "ESNext" 10 | ], 11 | "types": [ 12 | "@cloudflare/workers-types/2023-07-01" 13 | ], 14 | "jsx": "react-jsx", 15 | "jsxImportSource": "hono/jsx" 16 | }, 17 | } -------------------------------------------------------------------------------- /worker/wrangler.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/wrangler/config-schema.json", 3 | "name": "worker", 4 | "main": "src/index.ts", 5 | "compatibility_date": "2025-03-17", 6 | "compatibility_flags": ["nodejs_compat"] 7 | // "vars": { 8 | // "MY_VAR": "my-variable" 9 | // }, 10 | // "kv_namespaces": [ 11 | // { 12 | // "binding": "MY_KV_NAMESPACE", 13 | // "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 14 | // } 15 | // ], 16 | // "r2_buckets": [ 17 | // { 18 | // "binding": "MY_BUCKET", 19 | // "bucket_name": "my-bucket" 20 | // } 21 | // ], 22 | // "d1_databases": [ 23 | // { 24 | // "binding": "MY_DB", 25 | // "database_name": "my-database", 26 | // "database_id": "" 27 | // } 28 | // ], 29 | // "ai": { 30 | // "binding": "AI" 31 | // }, 32 | // "observability": { 33 | // "enabled": true, 34 | // "head_sampling_rate": 1 35 | // } 36 | } 37 | --------------------------------------------------------------------------------
      109 | ), 110 | td: ({ className, ...props }) => ( 111 | 112 | ), 113 | tr: ({ className, ...props }) => ( 114 |