diff --git a/.env.example b/.env.example index b4853049..5aa10ac3 100644 --- a/.env.example +++ b/.env.example @@ -18,3 +18,10 @@ NEXT_PUBLIC_AI_METRICS_SERVER_URL=https://leaderboard-api.livepeer.cloud # Optional dev overrides (e.g. Graph Studio sandbox; leave empty in prod) NEXT_PUBLIC_SUBGRAPH_ENDPOINT= + +# AI Chat (optional — chat feature degrades gracefully without these) +GOOGLE_GENERATIVE_AI_API_KEY= +UPSTASH_REDIS_REST_URL= +UPSTASH_REDIS_REST_TOKEN= +UPSTASH_VECTOR_REST_URL= +UPSTASH_VECTOR_REST_TOKEN= diff --git a/components/AiChat/ChatInput.tsx b/components/AiChat/ChatInput.tsx new file mode 100644 index 00000000..b589334f --- /dev/null +++ b/components/AiChat/ChatInput.tsx @@ -0,0 +1,93 @@ +import { Box, Flex } from "@livepeer/design-system"; +import React, { useCallback, useRef } from "react"; + +export default function ChatInput({ + input, + setInput, + onSubmit, + isLoading, +}: { + input: string; + setInput: (value: string) => void; + onSubmit: () => void; + isLoading: boolean; +}) { + const inputRef = useRef(null); + + const handleKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + if (input.trim() && !isLoading) { + onSubmit(); + } + } + }, + [input, isLoading, onSubmit] + ); + + return ( + + ) => + setInput(e.target.value) + } + onKeyDown={handleKeyDown} + placeholder="Ask about Livepeer..." + rows={1} + css={{ + flex: 1, + resize: "none", + border: "1px solid $neutral6", + borderRadius: "$2", + padding: "$2", + fontSize: "$2", + fontFamily: "inherit", + backgroundColor: "$neutral2", + color: "$hiContrast", + outline: "none", + maxHeight: 80, + "&:focus": { + borderColor: "$primary9", + }, + "&::placeholder": { + color: "$neutral9", + }, + }} + /> + { + if (input.trim() && !isLoading) onSubmit(); + }} + disabled={!input.trim() || isLoading} + css={{ + padding: "$2 $3", + borderRadius: "$2", + border: "none", + backgroundColor: isLoading || !input.trim() ? "$neutral6" : "$primary9", + color: "white", + cursor: isLoading || !input.trim() ? "not-allowed" : "pointer", + fontSize: "$2", + fontWeight: 600, + flexShrink: 0, + "&:hover:not(:disabled)": { + backgroundColor: "$primary10", + }, + }} + > + {isLoading ? "..." : "Send"} + + + ); +} diff --git a/components/AiChat/ChatPanel.tsx b/components/AiChat/ChatPanel.tsx new file mode 100644 index 00000000..c7f20357 --- /dev/null +++ b/components/AiChat/ChatPanel.tsx @@ -0,0 +1,150 @@ +import { useChat } from "@ai-sdk/react"; +import { Box, Flex, Text } from "@livepeer/design-system"; +import { Cross2Icon } from "@modulz/radix-icons"; +import { DefaultChatTransport } from "ai"; +import { useCallback, useMemo, useState } from "react"; + +import ChatInput from "./ChatInput"; +import MessageThread from "./MessageThread"; +import SuggestedQuestions from "./SuggestedQuestions"; + +export default function ChatPanel({ onClose }: { onClose: () => void }) { + const transport = useMemo( + () => new DefaultChatTransport({ api: "/api/ai/chat" }), + [] + ); + + const { messages, sendMessage, status, error } = useChat({ transport }); + + // Manage input state locally since v6 useChat doesn't provide it + const [input, setInput] = useState(""); + + const isLoading = status === "submitted" || status === "streaming"; + + const onSelectSuggestion = useCallback( + (question: string) => { + sendMessage({ text: question }); + }, + [sendMessage] + ); + + const onSubmitInput = useCallback(() => { + if (input.trim()) { + sendMessage({ text: input.trim() }); + setInput(""); + } + }, [input, sendMessage]); + + return ( + + {/* Header */} + + + Livepeer AI Assistant + + + + + + + {/* Messages or Suggestions */} + {messages.length === 0 ? ( + + + + Ask me anything about Livepeer + + + I can look up orchestrators, delegators, protocol stats, and more. + + + + + ) : ( + + )} + + {/* Error display */} + {error && ( + + + {error.message ?? "Something went wrong. Please try again."} + + + )} + + {/* Input */} + + + ); +} diff --git a/components/AiChat/MessageBubble.tsx b/components/AiChat/MessageBubble.tsx new file mode 100644 index 00000000..4bde95e4 --- /dev/null +++ b/components/AiChat/MessageBubble.tsx @@ -0,0 +1,131 @@ +import { Box, Text } from "@livepeer/design-system"; +import type { UIMessage } from "ai"; + +import ChartRenderer from "./renderers/ChartRenderer"; +import StatsCard from "./renderers/StatsCard"; +import TableRenderer from "./renderers/TableRenderer"; + +type ToolResult = { + type: "table" | "stats" | "chart" | "error"; + title?: string; + message?: string; + [key: string]: unknown; +}; + +function ToolResultRenderer({ result }: { result: ToolResult }) { + if (result.type === "error") { + return ( + + + {result.message ?? "An error occurred"} + + + ); + } + + if (result.type === "table") { + return ; + } + + if (result.type === "stats") { + return ; + } + + if (result.type === "chart") { + return ; + } + + return null; +} + +export default function MessageBubble({ message }: { message: UIMessage }) { + const isUser = message.role === "user"; + + // Extract text content from parts + const textContent = message.parts + .filter((p): p is { type: "text"; text: string } => p.type === "text") + .map((p) => p.text) + .join(""); + + // Extract tool invocations from parts + const toolParts = message.parts.filter( + (p) => + p.type.startsWith("tool-") || p.type === "dynamic-tool" + ); + + return ( + + {textContent && ( + + + {textContent} + + + )} + {toolParts.map((part) => { + const toolPart = part as { + type: string; + toolCallId: string; + state: string; + result?: unknown; + }; + if (toolPart.state === "result" && toolPart.result) { + return ( + + + + ); + } + if (toolPart.state === "call" || toolPart.state === "partial-call") { + return ( + + + Fetching data... + + + ); + } + return null; + })} + + ); +} diff --git a/components/AiChat/MessageThread.tsx b/components/AiChat/MessageThread.tsx new file mode 100644 index 00000000..c83752e6 --- /dev/null +++ b/components/AiChat/MessageThread.tsx @@ -0,0 +1,56 @@ +import { Box, Text } from "@livepeer/design-system"; +import type { UIMessage } from "ai"; +import { useEffect, useRef } from "react"; + +import MessageBubble from "./MessageBubble"; + +export default function MessageThread({ + messages, + isLoading, +}: { + messages: UIMessage[]; + isLoading: boolean; +}) { + const scrollRef = useRef(null); + + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + } + }, [messages, isLoading]); + + return ( + + {messages.map((message) => ( + + ))} + {isLoading && + messages.length > 0 && + messages[messages.length - 1].role === "user" && ( + + + Thinking... + + + )} + + ); +} diff --git a/components/AiChat/SuggestedQuestions.tsx b/components/AiChat/SuggestedQuestions.tsx new file mode 100644 index 00000000..c6a9c89a --- /dev/null +++ b/components/AiChat/SuggestedQuestions.tsx @@ -0,0 +1,46 @@ +import { Box, Flex, Text } from "@livepeer/design-system"; + +const suggestions = [ + "Who are the top orchestrators by stake?", + "What's the current round number?", + "What are the current protocol stats?", + "Which orchestrators support AI pipelines?", +]; + +export default function SuggestedQuestions({ + onSelect, +}: { + onSelect: (question: string) => void; +}) { + return ( + + + Try asking: + + + {suggestions.map((q) => ( + onSelect(q)} + css={{ + padding: "$2 $3", + borderRadius: "$2", + border: "1px solid $neutral6", + cursor: "pointer", + transition: "background-color 0.15s", + "&:hover": { + backgroundColor: "$neutral3", + }, + }} + > + {q} + + ))} + + + ); +} diff --git a/components/AiChat/index.tsx b/components/AiChat/index.tsx new file mode 100644 index 00000000..1f747e57 --- /dev/null +++ b/components/AiChat/index.tsx @@ -0,0 +1,52 @@ +import { Box } from "@livepeer/design-system"; +import { ChatBubbleIcon } from "@modulz/radix-icons"; + +import { useExplorerStore } from "../../hooks"; +import ChatPanel from "./ChatPanel"; + +export default function AiChat() { + const { aiChatOpen, setAiChatOpen } = useExplorerStore(); + + return ( + <> + {/* FAB - Floating Action Button */} + {!aiChatOpen && ( + setAiChatOpen(true)} + aria-label="Open AI Chat" + css={{ + position: "fixed", + bottom: 20, + right: 20, + width: 56, + height: 56, + borderRadius: "50%", + backgroundColor: "$primary9", + border: "none", + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "center", + color: "white", + boxShadow: "0 4px 14px rgba(0,0,0,0.25)", + zIndex: 999, + transition: "transform 0.2s, box-shadow 0.2s", + "&:hover": { + transform: "scale(1.05)", + boxShadow: "0 6px 20px rgba(0,0,0,0.3)", + }, + "&:active": { + transform: "scale(0.95)", + }, + }} + > + + + )} + + {/* Chat Panel */} + {aiChatOpen && setAiChatOpen(false)} />} + + ); +} diff --git a/components/AiChat/renderers/ChartRenderer.tsx b/components/AiChat/renderers/ChartRenderer.tsx new file mode 100644 index 00000000..cd5f770e --- /dev/null +++ b/components/AiChat/renderers/ChartRenderer.tsx @@ -0,0 +1,59 @@ +import { Box, Text } from "@livepeer/design-system"; +import { + Bar, + BarChart, + CartesianGrid, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from "recharts"; + +type ChartResult = { + type: "chart"; + title: string; + data: Array>; + xKey: string; + yKey: string; +}; + +export default function ChartRenderer({ data }: { data: ChartResult }) { + return ( + + + + {data.title} + + + + + + + + + + + + + + + ); +} diff --git a/components/AiChat/renderers/StatsCard.tsx b/components/AiChat/renderers/StatsCard.tsx new file mode 100644 index 00000000..e5d1af57 --- /dev/null +++ b/components/AiChat/renderers/StatsCard.tsx @@ -0,0 +1,55 @@ +import { Box, Flex, Text } from "@livepeer/design-system"; + +type StatsResult = { + type: "stats"; + title: string; + stats: Record; +}; + +export default function StatsCard({ data }: { data: StatsResult }) { + return ( + + + + {data.title} + + + + {Object.entries(data.stats).map(([key, value]) => ( + + + {key} + + + {String(value)} + + + ))} + + + ); +} diff --git a/components/AiChat/renderers/TableRenderer.tsx b/components/AiChat/renderers/TableRenderer.tsx new file mode 100644 index 00000000..4827af36 --- /dev/null +++ b/components/AiChat/renderers/TableRenderer.tsx @@ -0,0 +1,99 @@ +import { Box, Text } from "@livepeer/design-system"; + +type TableResult = { + type: "table"; + title: string; + columns: string[]; + rows: (string | number)[][]; +}; + +function formatCell(value: string | number): string { + const str = String(value); + // Truncate long addresses + if (/^0x[a-fA-F0-9]{40}$/.test(str)) { + return `${str.slice(0, 6)}...${str.slice(-4)}`; + } + return str; +} + +export default function TableRenderer({ data }: { data: TableResult }) { + return ( + + + + {data.title} + + + + + + + {data.columns.map((col) => ( + + {col} + + ))} + + + + {data.rows.map((row, i) => ( + + {row.map((cell, j) => ( + + {formatCell(cell)} + + ))} + + ))} + + + + + ); +} diff --git a/hooks/useExplorerStore.tsx b/hooks/useExplorerStore.tsx index 980a1dc2..5b5ed4ea 100644 --- a/hooks/useExplorerStore.tsx +++ b/hooks/useExplorerStore.tsx @@ -49,11 +49,13 @@ export type ExplorerState = { selectedStakingAction: StakingAction; yieldResults: YieldResults; latestTransaction: TransactionStatus | null; + aiChatOpen: boolean; setWalletModalOpen: (v: boolean) => void; setBottomDrawerOpen: (v: boolean) => void; setSelectedStakingAction: (v: StakingAction) => void; setYieldResults: (v: YieldResults) => void; + setAiChatOpen: (v: boolean) => void; setLatestTransactionDetails: ( hash: string, @@ -77,8 +79,10 @@ export const useExplorerStore = create()((set) => ({ principle: 0.0, }, latestTransaction: null, + aiChatOpen: false, setWalletModalOpen: (v: boolean) => set(() => ({ walletModalOpen: v })), + setAiChatOpen: (v: boolean) => set(() => ({ aiChatOpen: v })), setBottomDrawerOpen: (v: boolean) => set(() => ({ bottomDrawerOpen: v })), setSelectedStakingAction: (v: StakingAction) => set(() => ({ selectedStakingAction: v })), diff --git a/layouts/main.tsx b/layouts/main.tsx index a02fee05..f5d40c80 100644 --- a/layouts/main.tsx +++ b/layouts/main.tsx @@ -1,3 +1,4 @@ +import AiChat from "@components/AiChat"; import AppBar from "@components/AppBar"; import Drawer from "@components/Drawer"; import Hamburger from "@components/Hamburger"; @@ -744,6 +745,7 @@ const Layout = ({ children, title = "Livepeer Explorer" }) => { )} + diff --git a/lib/ai/cache.ts b/lib/ai/cache.ts new file mode 100644 index 00000000..8048b67b --- /dev/null +++ b/lib/ai/cache.ts @@ -0,0 +1,67 @@ +import { Index } from "@upstash/vector"; + +let vectorIndex: Index | null = null; + +function getVectorIndex(): Index | null { + if (vectorIndex) return vectorIndex; + + const url = process.env.UPSTASH_VECTOR_REST_URL; + const token = process.env.UPSTASH_VECTOR_REST_TOKEN; + + if (!url || !token) return null; + + vectorIndex = new Index({ url, token }); + return vectorIndex; +} + +const CACHE_TTL_SECONDS = 300; // 5 minutes +const SIMILARITY_THRESHOLD = 0.95; + +export async function getCachedResponse( + question: string +): Promise { + const index = getVectorIndex(); + if (!index) return null; + + try { + const results = await index.query({ + data: question, + topK: 1, + includeMetadata: true, + }); + + if ( + results.length > 0 && + results[0].score >= SIMILARITY_THRESHOLD && + results[0].metadata + ) { + const cached = results[0].metadata as { response: string; ts: number }; + const age = (Date.now() - cached.ts) / 1000; + if (age < CACHE_TTL_SECONDS) { + return cached.response; + } + } + + return null; + } catch { + return null; + } +} + +export async function setCachedResponse( + question: string, + response: string +): Promise { + const index = getVectorIndex(); + if (!index) return; + + try { + await index.upsert({ + id: `chat-${Date.now()}`, + data: question, + metadata: { response, ts: Date.now() }, + }); + } catch { + // Caching is best-effort + } +} diff --git a/lib/ai/config.ts b/lib/ai/config.ts new file mode 100644 index 00000000..1f7b5aae --- /dev/null +++ b/lib/ai/config.ts @@ -0,0 +1,25 @@ +import { google } from "@ai-sdk/google"; + +export const model = google("gemini-2.5-flash-preview-05-20"); + +export const systemPrompt = `You are the Livepeer Explorer AI assistant. You help users understand the Livepeer protocol by answering questions backed by real on-chain data. + +Your capabilities: +- Look up orchestrator information (stake, fees, performance) +- Look up delegator information (bonded amount, delegate) +- Query protocol-level statistics (participation rate, inflation, total stake) +- Get current round information +- Get performance/leaderboard scores for orchestrators +- Get AI pipeline usage metrics +- Get recent protocol events (bonds, unbonds, rewards, etc.) +- Get treasury proposal information + +Guidelines: +- Always use the available tools to fetch real data before answering. Never make up numbers. +- Present data clearly using structured formats when appropriate. +- When showing addresses, use the short format (0x1234...abcd) unless the user asks for the full address. +- Explain protocol concepts in simple terms when users seem unfamiliar. +- If a tool returns no data or an error, tell the user honestly rather than guessing. +- Keep responses concise but informative. +- You can only read data — you cannot execute any transactions or modify protocol state. +- Do not answer questions unrelated to Livepeer or the protocol.`; diff --git a/lib/ai/ratelimit.ts b/lib/ai/ratelimit.ts new file mode 100644 index 00000000..7cf3c2aa --- /dev/null +++ b/lib/ai/ratelimit.ts @@ -0,0 +1,31 @@ +import { Ratelimit } from "@upstash/ratelimit"; +import { Redis } from "@upstash/redis"; + +let ratelimit: Ratelimit | null = null; + +function getRatelimit(): Ratelimit | null { + if (ratelimit) return ratelimit; + + const url = process.env.UPSTASH_REDIS_REST_URL; + const token = process.env.UPSTASH_REDIS_REST_TOKEN; + + if (!url || !token) return null; + + ratelimit = new Ratelimit({ + redis: new Redis({ url, token }), + limiter: Ratelimit.slidingWindow(20, "1 m"), + analytics: false, + }); + + return ratelimit; +} + +export async function checkRateLimit( + ip: string +): Promise<{ allowed: boolean; remaining: number }> { + const limiter = getRatelimit(); + if (!limiter) return { allowed: true, remaining: 20 }; + + const { success, remaining } = await limiter.limit(ip); + return { allowed: success, remaining }; +} diff --git a/lib/ai/tools/get-ai-usage.ts b/lib/ai/tools/get-ai-usage.ts new file mode 100644 index 00000000..16b741ea --- /dev/null +++ b/lib/ai/tools/get-ai-usage.ts @@ -0,0 +1,85 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { fetchWithRetry } from "../../fetchWithRetry"; + +export const getAIUsageTool = tool({ + description: + "Get AI pipeline usage metrics and available AI models/pipelines on the Livepeer network. Use this when users ask about AI capabilities, which orchestrators support AI, or AI pipeline stats.", + inputSchema: z.object({ + orchestrator: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/) + .optional() + .describe( + "Optional orchestrator address to filter AI metrics for a specific orchestrator" + ), + }), + execute: async ({ orchestrator }) => { + const baseUrl = + process.env.NEXT_PUBLIC_AI_METRICS_SERVER_URL ?? + "https://leaderboard-api.livepeer.cloud"; + + // Fetch available pipelines + const pipelinesResponse = await fetchWithRetry( + `${baseUrl}/api/pipelines` + ) + .then((res) => res.json()) + .catch(() => ({ pipelines: [] })); + + // Fetch aggregated stats for AI + const statsResponse = await fetchWithRetry( + `${baseUrl}/api/aggregated_stats` + ) + .then((res) => res.json()) + .catch(() => ({})); + + const stats = statsResponse as Record< + string, + Record> + >; + const allOrchestrators = Object.keys(stats); + + if (orchestrator) { + const orchStats = stats[orchestrator.toLowerCase()]; + if (!orchStats) { + return { + type: "error" as const, + message: `No AI metrics found for orchestrator ${orchestrator}`, + }; + } + + const regions = Object.keys(orchStats); + return { + type: "stats" as const, + title: `AI Metrics for ${orchestrator}`, + stats: { + "Regions Active": regions.join(", "), + ...Object.fromEntries( + regions.map((r) => [ + `Score (${r})`, + `${((orchStats[r]?.score ?? 0) * 100).toFixed(1)}%`, + ]) + ), + }, + }; + } + + const pipelines = pipelinesResponse?.pipelines ?? []; + + return { + type: "stats" as const, + title: "AI Network Overview", + stats: { + "Orchestrators with AI": allOrchestrators.length, + "Available Pipelines": Array.isArray(pipelines) + ? pipelines.length + : 0, + "Pipeline Names": Array.isArray(pipelines) + ? pipelines.map((p: { pipeline?: string }) => p.pipeline ?? "unknown").join(", ") || + "None reported" + : "Unknown", + }, + }; + }, +}); diff --git a/lib/ai/tools/get-current-round.ts b/lib/ai/tools/get-current-round.ts new file mode 100644 index 00000000..b6dc47e5 --- /dev/null +++ b/lib/ai/tools/get-current-round.ts @@ -0,0 +1,46 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + CurrentRoundDocument, + CurrentRoundQuery, + CurrentRoundQueryVariables, +} from "../../../apollo"; + +export const getCurrentRoundTool = tool({ + description: + "Get information about the current Livepeer round, including round number, start block, and initialization status. Use this when users ask about the current round or round timing.", + inputSchema: z.object({}), + execute: async () => { + const client = getApollo(); + + const result = await client.query< + CurrentRoundQuery, + CurrentRoundQueryVariables + >({ + query: CurrentRoundDocument, + }); + + const round = result.data?.protocol?.currentRound; + const blockNumber = result.data?._meta?.block?.number; + + if (!round) { + return { + type: "error" as const, + message: "Could not fetch current round data", + }; + } + + return { + type: "stats" as const, + title: "Current Round", + stats: { + "Round Number": round.id ?? "Unknown", + Initialized: round.initialized ? "Yes" : "No", + "Start Block": round.startBlock ?? "Unknown", + "Current L2 Block": blockNumber ?? "Unknown", + }, + }; + }, +}); diff --git a/lib/ai/tools/get-delegator.ts b/lib/ai/tools/get-delegator.ts new file mode 100644 index 00000000..bc9275df --- /dev/null +++ b/lib/ai/tools/get-delegator.ts @@ -0,0 +1,61 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + AccountDocument, + AccountQuery, + AccountQueryVariables, +} from "../../../apollo"; + +export const getDelegatorTool = tool({ + description: + "Get information about a specific delegator including their bonded amount, delegate (orchestrator), and unbonding locks. Use this when users ask about a delegator's staking position.", + inputSchema: z.object({ + address: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, "Must be a valid Ethereum address") + .transform((v) => v.toLowerCase()) + .describe("The Ethereum address of the delegator"), + }), + execute: async ({ address }) => { + const client = getApollo(); + + const result = await client.query({ + query: AccountDocument, + variables: { account: address }, + }); + + const delegator = result.data?.delegator; + if (!delegator) { + return { + type: "error" as const, + message: `No delegator found at address ${address}`, + }; + } + + const pendingUnbonds = + delegator.unbondingLocks?.filter( + (lock) => lock && Number(lock.amount) > 0 + ) ?? []; + + return { + type: "stats" as const, + title: `Delegator ${address}`, + stats: { + "Bonded Amount (LPT)": ( + Number(delegator.bondedAmount) / 1e18 + ).toFixed(2), + "Principal (LPT)": (Number(delegator.principal) / 1e18).toFixed(2), + "Delegate (Orchestrator)": delegator.delegate?.id ?? "None", + "Delegate Active": delegator.delegate?.active ? "Yes" : "No", + "Start Round": delegator.startRound ?? "N/A", + "Last Claim Round": delegator.lastClaimRound?.id ?? "N/A", + "Pending Unbonds": pendingUnbonds.length, + "Total Unbonding (LPT)": pendingUnbonds + .reduce((sum, lock) => sum + Number(lock?.amount ?? 0), 0) + .toFixed(2), + }, + }; + }, +}); diff --git a/lib/ai/tools/get-events.ts b/lib/ai/tools/get-events.ts new file mode 100644 index 00000000..49de9031 --- /dev/null +++ b/lib/ai/tools/get-events.ts @@ -0,0 +1,94 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + EventsDocument, + EventsQuery, + EventsQueryVariables, +} from "../../../apollo"; + +export const getEventsTool = tool({ + description: + "Get recent protocol events including bonds, unbonds, rewards, ticket redemptions, and other on-chain activities. Use this when users ask about recent activity, what's happening on the network, or specific event types.", + inputSchema: z.object({ + limit: z + .number() + .min(1) + .max(50) + .optional() + .default(20) + .describe("Number of recent transactions to fetch (default 20, max 50)"), + }), + execute: async ({ limit }) => { + const client = getApollo(); + + const result = await client.query({ + query: EventsDocument, + variables: { first: limit }, + }); + + const transactions = result.data?.transactions ?? []; + const events: Array<{ + type: string; + round: string; + time: string; + details: string; + }> = []; + + for (const tx of transactions) { + for (const event of tx?.events ?? []) { + if (!event) continue; + + const typeName = event.__typename ?? "Unknown"; + const round = event.round?.id ?? "?"; + const timestamp = event.transaction?.timestamp + ? new Date(Number(event.transaction.timestamp) * 1000).toISOString() + : "Unknown"; + + let details = ""; + switch (typeName) { + case "BondEvent": { + const e = event as { delegator?: { id: string }; newDelegate?: { id: string }; additionalAmount?: string }; + details = `${e.delegator?.id ?? "?"} bonded ${(Number(e.additionalAmount ?? 0) / 1e18).toFixed(2)} LPT to ${e.newDelegate?.id ?? "?"}`; + break; + } + case "UnbondEvent": { + const e = event as { delegator?: { id: string }; amount?: string }; + details = `${e.delegator?.id ?? "?"} unbonded ${(Number(e.amount ?? 0) / 1e18).toFixed(2)} LPT`; + break; + } + case "RewardEvent": { + const e = event as { delegate?: { id: string }; rewardTokens?: string }; + details = `${e.delegate?.id ?? "?"} claimed ${(Number(e.rewardTokens ?? 0) / 1e18).toFixed(2)} LPT reward`; + break; + } + case "WinningTicketRedeemedEvent": { + const e = event as { recipient?: { id: string }; faceValue?: string }; + details = `${e.recipient?.id ?? "?"} redeemed ticket worth ${(Number(e.faceValue ?? 0) / 1e18).toFixed(6)} ETH`; + break; + } + case "TranscoderUpdateEvent": { + const e = event as { delegate?: { id: string }; feeShare?: string; rewardCut?: string }; + details = `${e.delegate?.id ?? "?"} updated: fee share ${(Number(e.feeShare ?? 0) / 10000).toFixed(2)}%, reward cut ${(Number(e.rewardCut ?? 0) / 10000).toFixed(2)}%`; + break; + } + case "NewRoundEvent": + details = `New round initialized`; + break; + default: + details = typeName; + } + + events.push({ type: typeName, round, time: timestamp, details }); + } + } + + return { + type: "table" as const, + title: `Recent Protocol Events (${events.length})`, + columns: ["Type", "Round", "Time", "Details"], + rows: events.slice(0, 30).map((e) => [e.type, e.round, e.time, e.details]), + }; + }, +}); diff --git a/lib/ai/tools/get-orchestrator.ts b/lib/ai/tools/get-orchestrator.ts new file mode 100644 index 00000000..53f14f27 --- /dev/null +++ b/lib/ai/tools/get-orchestrator.ts @@ -0,0 +1,70 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + AccountDocument, + AccountQuery, + AccountQueryVariables, +} from "../../../apollo"; + +export const getOrchestratorTool = tool({ + description: + "Get detailed information about a specific orchestrator by their Ethereum address. Use this when users ask about a particular orchestrator's stats, fees, rewards, or configuration.", + inputSchema: z.object({ + address: z + .string() + .regex(/^0x[a-fA-F0-9]{40}$/, "Must be a valid Ethereum address") + .transform((v) => v.toLowerCase()) + .describe("The Ethereum address of the orchestrator"), + }), + execute: async ({ address }) => { + const client = getApollo(); + + const result = await client.query({ + query: AccountDocument, + variables: { account: address }, + }); + + const transcoder = result.data?.transcoder; + if (!transcoder) { + return { + type: "error" as const, + message: `No orchestrator found at address ${address}`, + }; + } + + const rewardHistory = + transcoder.pools?.map((p) => Number(p?.rewardTokens ?? 0) / 1e18) ?? []; + + return { + type: "stats" as const, + title: `Orchestrator ${address}`, + stats: { + Active: transcoder.active ? "Yes" : "No", + "Total Stake (LPT)": ( + Number(transcoder.totalStake) / 1e18 + ).toFixed(2), + "Fee Share": `${(Number(transcoder.feeShare) / 10000).toFixed(2)}%`, + "Reward Cut": `${(Number(transcoder.rewardCut) / 10000).toFixed(2)}%`, + "30d Volume (ETH)": Number( + transcoder.thirtyDayVolumeETH + ).toFixed(4), + "90d Volume (ETH)": Number( + transcoder.ninetyDayVolumeETH + ).toFixed(4), + "Total Volume (ETH)": Number( + transcoder.totalVolumeETH + ).toFixed(4), + Delegators: transcoder.delegators?.length ?? 0, + "Recent Avg Reward (LPT)": + rewardHistory.length > 0 + ? ( + rewardHistory.reduce((a, b) => a + b, 0) / + rewardHistory.length + ).toFixed(4) + : "N/A", + }, + }; + }, +}); diff --git a/lib/ai/tools/get-orchestrators.ts b/lib/ai/tools/get-orchestrators.ts new file mode 100644 index 00000000..50b295f2 --- /dev/null +++ b/lib/ai/tools/get-orchestrators.ts @@ -0,0 +1,87 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + CurrentRoundDocument, + CurrentRoundQuery, + CurrentRoundQueryVariables, + OrchestratorsDocument, + OrchestratorsQuery, + OrchestratorsQueryVariables, +} from "../../../apollo"; + +export const getOrchestratorsTool = tool({ + description: + "Get a list of active orchestrators on the Livepeer network, including their stake, fees, and delegation info. Use this when users ask about top orchestrators, who to delegate to, or orchestrator rankings.", + inputSchema: z.object({ + top: z + .number() + .min(1) + .max(100) + .optional() + .default(10) + .describe("Number of orchestrators to return (default 10, max 100)"), + sortBy: z + .enum(["stake", "fees"]) + .optional() + .default("fees") + .describe( + "Sort orchestrators by total stake or by 30-day fees volume (default: fees)" + ), + }), + execute: async ({ top, sortBy }) => { + const client = getApollo(); + + const roundResult = await client.query< + CurrentRoundQuery, + CurrentRoundQueryVariables + >({ + query: CurrentRoundDocument, + }); + + const currentRoundId = roundResult.data?.protocol?.currentRound?.id; + + const result = await client.query< + OrchestratorsQuery, + OrchestratorsQueryVariables + >({ + query: OrchestratorsDocument, + variables: { + currentRound: currentRoundId, + currentRoundString: currentRoundId, + first: top, + orderBy: + sortBy === "stake" + ? ("totalStake" as never) + : ("thirtyDayVolumeETH" as never), + orderDirection: "desc" as never, + }, + }); + + const orchestrators = result.data?.transcoders ?? []; + + return { + type: "table" as const, + title: `Top ${top} Orchestrators by ${sortBy === "stake" ? "Stake" : "30-Day Fees"}`, + columns: [ + "Rank", + "Address", + "Total Stake (LPT)", + "30d Volume (ETH)", + "Fee Share", + "Reward Cut", + "Delegators", + ], + rows: orchestrators.map((o, i) => [ + i + 1, + o.id, + (Number(o.totalStake) / 1e18).toFixed(2), + Number(o.thirtyDayVolumeETH).toFixed(4), + `${(Number(o.feeShare) / 10000).toFixed(2)}%`, + `${(Number(o.rewardCut) / 10000).toFixed(2)}%`, + o.delegators?.length ?? 0, + ]), + }; + }, +}); diff --git a/lib/ai/tools/get-performance.ts b/lib/ai/tools/get-performance.ts new file mode 100644 index 00000000..73f81c70 --- /dev/null +++ b/lib/ai/tools/get-performance.ts @@ -0,0 +1,92 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { fetchWithRetry } from "../../fetchWithRetry"; + +export const getPerformanceTool = tool({ + description: + "Get performance/leaderboard scores for orchestrators including success rates, round trip scores, and overall scores. Optionally filter by region. Use this when users ask about orchestrator performance, reliability, or the leaderboard.", + inputSchema: z.object({ + region: z + .string() + .optional() + .describe( + "Optional region filter (e.g., 'FRA', 'LAX', 'NYC', 'LON', 'PRG', 'SAO', 'SIN'). Omit for global scores." + ), + }), + execute: async ({ region }) => { + const baseUrl = + process.env.NEXT_PUBLIC_METRICS_SERVER_URL ?? + "https://livepeer-leaderboard-serverless.vercel.app"; + + const response = await fetchWithRetry( + `${baseUrl}/api/aggregated_stats` + ).then((res) => res.json()); + + const metrics = response as Record< + string, + Record> + >; + const orchestratorIds = Object.keys(metrics); + + const rows = orchestratorIds + .map((id) => { + const regions = metrics[id]; + if (!regions) return null; + + if (region) { + const r = regions[region]; + if (!r) return null; + return { + address: id, + successRate: (r.success_rate ?? 0) * 100, + roundTripScore: (r.round_trip_score ?? 0) * 100, + score: (r.score ?? 0) * 100, + }; + } + + // Global average + const regionKeys = Object.keys(regions); + if (regionKeys.length === 0) return null; + + const avgScore = + regionKeys.reduce( + (sum, rk) => sum + (regions[rk]?.score ?? 0), + 0 + ) / regionKeys.length; + const avgSuccess = + regionKeys.reduce( + (sum, rk) => sum + (regions[rk]?.success_rate ?? 0), + 0 + ) / regionKeys.length; + const avgRoundTrip = + regionKeys.reduce( + (sum, rk) => sum + (regions[rk]?.round_trip_score ?? 0), + 0 + ) / regionKeys.length; + + return { + address: id, + successRate: avgSuccess * 100, + roundTripScore: avgRoundTrip * 100, + score: avgScore * 100, + }; + }) + .filter(Boolean) + .sort((a, b) => (b?.score ?? 0) - (a?.score ?? 0)) + .slice(0, 20); + + return { + type: "table" as const, + title: `Orchestrator Performance${region ? ` (${region})` : " (Global)"}`, + columns: ["Rank", "Address", "Score", "Success Rate", "Round Trip Score"], + rows: rows.map((r, i) => [ + i + 1, + r!.address, + `${r!.score.toFixed(1)}%`, + `${r!.successRate.toFixed(1)}%`, + `${r!.roundTripScore.toFixed(1)}%`, + ]), + }; + }, +}); diff --git a/lib/ai/tools/get-protocol.ts b/lib/ai/tools/get-protocol.ts new file mode 100644 index 00000000..0fc19be2 --- /dev/null +++ b/lib/ai/tools/get-protocol.ts @@ -0,0 +1,55 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + ProtocolDocument, + ProtocolQuery, + ProtocolQueryVariables, +} from "../../../apollo"; + +export const getProtocolStatsTool = tool({ + description: + "Get overall Livepeer protocol statistics including participation rate, inflation, total stake, total supply, active orchestrator count, and delegator count. Use this when users ask about protocol health, network stats, or general Livepeer metrics.", + inputSchema: z.object({}), + execute: async () => { + const client = getApollo(); + + const result = await client.query({ + query: ProtocolDocument, + }); + + const protocol = result.data?.protocol; + if (!protocol) { + return { + type: "error" as const, + message: "Could not fetch protocol data", + }; + } + + return { + type: "stats" as const, + title: "Livepeer Protocol Stats", + stats: { + "Current Round": protocol.currentRound?.id ?? "Unknown", + "Participation Rate": `${(Number(protocol.participationRate) * 100).toFixed(2)}%`, + Inflation: `${(Number(protocol.inflation) / 1e7).toFixed(4)}%`, + "Inflation Change": `${(Number(protocol.inflationChange) / 1e7).toFixed(6)}%`, + "Total Active Stake (LPT)": ( + Number(protocol.totalActiveStake) / 1e18 + ).toFixed(0), + "Total Supply (LPT)": ( + Number(protocol.totalSupply) / 1e18 + ).toFixed(0), + "Active Orchestrators": protocol.activeTranscoderCount ?? 0, + "Total Delegators": protocol.delegatorsCount ?? 0, + "Total Volume (USD)": `$${Number(protocol.totalVolumeUSD).toFixed(2)}`, + "Total Volume (ETH)": `${Number(protocol.totalVolumeETH).toFixed(4)} ETH`, + "LPT Price (ETH)": `${Number(protocol.lptPriceEth).toFixed(6)} ETH`, + "Round Length (blocks)": protocol.roundLength ?? "Unknown", + "Lock Period (rounds)": protocol.lockPeriod ?? "Unknown", + Paused: protocol.paused ? "Yes" : "No", + }, + }; + }, +}); diff --git a/lib/ai/tools/get-treasury.ts b/lib/ai/tools/get-treasury.ts new file mode 100644 index 00000000..1c7dceee --- /dev/null +++ b/lib/ai/tools/get-treasury.ts @@ -0,0 +1,55 @@ +import { tool } from "ai"; +import { z } from "zod"; + +import { getApollo } from "../../../apollo"; +import { + TreasuryProposalsDocument, + TreasuryProposalsQuery, + TreasuryProposalsQueryVariables, +} from "../../../apollo"; + +export const getTreasuryTool = tool({ + description: + "Get treasury governance proposals including active and past proposals. Use this when users ask about governance, treasury proposals, or voting.", + inputSchema: z.object({}), + execute: async () => { + const client = getApollo(); + + const result = await client.query< + TreasuryProposalsQuery, + TreasuryProposalsQueryVariables + >({ + query: TreasuryProposalsDocument, + }); + + const proposals = result.data?.treasuryProposals ?? []; + + if (proposals.length === 0) { + return { + type: "stats" as const, + title: "Treasury Proposals", + stats: { Status: "No proposals found" }, + }; + } + + return { + type: "table" as const, + title: `Treasury Proposals (${proposals.length})`, + columns: [ + "ID", + "Description", + "Proposer", + "Vote Start", + "Vote End", + ], + rows: proposals.map((p) => [ + p.id.slice(0, 10) + "...", + (p.description ?? "No description").slice(0, 80) + + ((p.description ?? "").length > 80 ? "..." : ""), + p.proposer?.id ?? "Unknown", + p.voteStart ?? "?", + p.voteEnd ?? "?", + ]), + }; + }, +}); diff --git a/lib/ai/tools/index.ts b/lib/ai/tools/index.ts new file mode 100644 index 00000000..4281809d --- /dev/null +++ b/lib/ai/tools/index.ts @@ -0,0 +1,9 @@ +export { getAIUsageTool } from "./get-ai-usage"; +export { getCurrentRoundTool } from "./get-current-round"; +export { getDelegatorTool } from "./get-delegator"; +export { getEventsTool } from "./get-events"; +export { getOrchestratorTool } from "./get-orchestrator"; +export { getOrchestratorsTool } from "./get-orchestrators"; +export { getPerformanceTool } from "./get-performance"; +export { getProtocolStatsTool } from "./get-protocol"; +export { getTreasuryTool } from "./get-treasury"; diff --git a/package.json b/package.json index 8d5be139..6e2b7bbd 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,8 @@ "wait-on": "^9.0.3" }, "dependencies": { + "@ai-sdk/google": "^3.0.43", + "@ai-sdk/react": "^3.0.118", "@apollo/client": "3.13.1", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", @@ -68,7 +70,11 @@ "@reach/tabs": "^0.17.0", "@stitches/react": "1.2.5", "@tanstack/react-query": "^5.90.5", + "@upstash/ratelimit": "^2.0.8", + "@upstash/redis": "^1.36.4", + "@upstash/vector": "^1.2.3", "@wagmi/core": "^2.22.1", + "ai": "^6.0.116", "apollo-fetch": "^0.7.0", "apollo-link": "^1.2.11", "apollo-link-http": "^1.5.15", diff --git a/pages/api/ai/chat.ts b/pages/api/ai/chat.ts new file mode 100644 index 00000000..1065db9e --- /dev/null +++ b/pages/api/ai/chat.ts @@ -0,0 +1,101 @@ +import { stepCountIs, streamText } from "ai"; +import type { NextApiRequest, NextApiResponse } from "next"; + +import { getCachedResponse, setCachedResponse } from "../../../lib/ai/cache"; +import { model, systemPrompt } from "../../../lib/ai/config"; +import { checkRateLimit } from "../../../lib/ai/ratelimit"; +import { + getAIUsageTool, + getCurrentRoundTool, + getDelegatorTool, + getEventsTool, + getOrchestratorsTool, + getOrchestratorTool, + getPerformanceTool, + getProtocolStatsTool, + getTreasuryTool, +} from "../../../lib/ai/tools"; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== "POST") { + return res.status(405).json({ error: "Method not allowed" }); + } + + // Rate limiting + const ip = + (req.headers["x-forwarded-for"] as string)?.split(",")[0]?.trim() ?? + req.socket.remoteAddress ?? + "unknown"; + + const { allowed, remaining } = await checkRateLimit(ip); + if (!allowed) { + return res.status(429).json({ + error: + "You've sent too many messages. Please wait a moment before trying again.", + remaining, + }); + } + + const { messages } = req.body; + if (!messages || !Array.isArray(messages)) { + return res.status(400).json({ error: "messages array is required" }); + } + + // Extract latest user query for caching + const lastUserMessage = [...messages] + .reverse() + .find((m: { role: string }) => m.role === "user"); + + let userQuery = ""; + if (lastUserMessage) { + if (typeof lastUserMessage.content === "string") { + userQuery = lastUserMessage.content; + } else if (Array.isArray(lastUserMessage.parts)) { + userQuery = lastUserMessage.parts + .filter((p: { type: string }) => p.type === "text") + .map((p: { text: string }) => p.text) + .join(" "); + } + } + + // Check semantic cache + if (userQuery) { + const cached = await getCachedResponse(userQuery); + if (cached) { + res.setHeader("X-Cache", "HIT"); + res.setHeader("Content-Type", "text/plain; charset=utf-8"); + res.write(cached); + return res.end(); + } + } + + res.setHeader("X-Cache", "MISS"); + + const result = streamText({ + model, + system: systemPrompt, + messages, + tools: { + getOrchestrators: getOrchestratorsTool, + getOrchestrator: getOrchestratorTool, + getDelegator: getDelegatorTool, + getProtocolStats: getProtocolStatsTool, + getCurrentRound: getCurrentRoundTool, + getPerformance: getPerformanceTool, + getAIUsage: getAIUsageTool, + getEvents: getEventsTool, + getTreasury: getTreasuryTool, + }, + stopWhen: stepCountIs(5), + onFinish: async ({ text }) => { + if (userQuery && text) { + await setCachedResponse(userQuery, text); + } + }, + }); + + result.pipeUIMessageStreamToResponse(res); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67322cb2..ee19ef8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,12 @@ importers: .: dependencies: + '@ai-sdk/google': + specifier: ^3.0.43 + version: 3.0.43(zod@4.1.12) + '@ai-sdk/react': + specifier: ^3.0.118 + version: 3.0.118(react@19.2.1)(zod@4.1.12) '@apollo/client': specifier: 3.13.1 version: 3.13.1(@types/react@19.2.2)(graphql-ws@5.12.1(graphql@16.12.0))(graphql@16.12.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -38,7 +44,7 @@ importers: version: 8.5.0(graphql@16.12.0) '@livepeer/design-system': specifier: 1.1.0 - version: 1.1.0(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + version: 1.1.0(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) '@mdx-js/loader': specifier: ^2.1.2 version: 2.3.0(webpack@5.102.1) @@ -59,7 +65,7 @@ importers: version: 1.3.2(react@19.2.1) '@rainbow-me/rainbowkit': specifier: ^2.2.10 - version: 2.2.10(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)) + version: 2.2.10(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)) '@reach/dialog': specifier: ^0.17.0 version: 0.17.0(@types/react@19.2.2)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -72,9 +78,21 @@ importers: '@tanstack/react-query': specifier: ^5.90.5 version: 5.90.7(react@19.2.1) + '@upstash/ratelimit': + specifier: ^2.0.8 + version: 2.0.8(@upstash/redis@1.36.4) + '@upstash/redis': + specifier: ^1.36.4 + version: 1.36.4 + '@upstash/vector': + specifier: ^1.2.3 + version: 1.2.3 '@wagmi/core': specifier: ^2.22.1 version: 2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)) + ai: + specifier: ^6.0.116 + version: 6.0.116(zod@4.1.12) apollo-fetch: specifier: ^0.7.0 version: 0.7.0 @@ -146,10 +164,10 @@ importers: version: 0.1.1 next: specifier: 16.1.5 - version: 16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + version: 16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) next-themes: specifier: ^0.2.0 - version: 0.2.1(next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + version: 0.2.1(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) numbro: specifier: ^2.5.0 version: 2.5.0 @@ -242,7 +260,7 @@ importers: version: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) wagmi: specifier: ^2.19.1 - version: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) + version: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) zod: specifier: ^4.1.12 version: 4.1.12 @@ -352,6 +370,34 @@ packages: '@adraffy/ens-normalize@1.11.1': resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} + '@ai-sdk/gateway@3.0.66': + resolution: {integrity: sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@3.0.43': + resolution: {integrity: sha512-NGCgP5g8HBxrNdxvF8Dhww+UKfqAkZAmyYBvbu9YLoBkzAmGKDBGhVptN/oXPB5Vm0jggMdoLycZ8JReQM8Zqg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.19': + resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@3.0.8': + resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} + engines: {node: '>=18'} + + '@ai-sdk/react@3.0.118': + resolution: {integrity: sha512-fBAix8Jftxse6/2YJnOFkwW1/O6EQK4DK68M9DlFmZGAzBmsaHXEPVS77sVIlkaOWCy11bE7434NAVXRY+3OsQ==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ~19.0.1 || ~19.1.2 || ^19.2.1 + '@apollo/client@3.13.1': resolution: {integrity: sha512-HaAt62h3jNUXpJ1v5HNgUiCzPP1c5zc2Q/FeTb2cTk/v09YlhoqKKHQFJI7St50VCJ5q8JVIc03I5bRcBrQxsg==} peerDependencies: @@ -2304,6 +2350,10 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + '@paulirish/trace_engine@0.0.53': resolution: {integrity: sha512-PUl/vlfo08Oj804VI5nDPeSk9vyslnBlVzDDwFt8SUVxY8+KdGMkra/vrXjEEHe8gb7+RqVTfOIlGw0nyrEelA==} @@ -4629,6 +4679,21 @@ packages: cpu: [x64] os: [win32] + '@upstash/core-analytics@0.0.10': + resolution: {integrity: sha512-7qJHGxpQgQr9/vmeS1PktEwvNAF7TI4iJDi8Pu2CFZ9YUGHZH4fOP5TfYlZ4aVxfopnELiE4BS4FBjyK7V1/xQ==} + engines: {node: '>=16.0.0'} + + '@upstash/ratelimit@2.0.8': + resolution: {integrity: sha512-YSTMBJ1YIxsoPkUMX/P4DDks/xV5YYCswWMamU8ZIfK9ly6ppjRnVOyBhMDXBmzjODm4UQKcxsJPvaeFAijp5w==} + peerDependencies: + '@upstash/redis': ^1.34.3 + + '@upstash/redis@1.36.4': + resolution: {integrity: sha512-w4s/msmyMqxOxaVhC8TQ2whJ77+Zd8YaSFokXL4mULQopaYb4xNJcm/PedtFQyLJn65nneySw9IwYnlMBBmFHg==} + + '@upstash/vector@1.2.3': + resolution: {integrity: sha512-yXsWKeuHNYyH72BcSZd3bV5ZD5MybAoTvKxkMaeV2UzuGfNzbHBVh5eO+ysTWTFAf8I9XcOueF4tZfAGjCa4Iw==} + '@vanilla-extract/css@1.17.3': resolution: {integrity: sha512-jHivr1UPoJTX5Uel4AZSOwrCf4mO42LcdmnhJtUxZaRWhW4FviFbIfs0moAWWld7GOT+2XnuVZjjA/K32uUnMQ==} @@ -4643,6 +4708,10 @@ packages: peerDependencies: '@vanilla-extract/css': ^1.0.0 + '@vercel/oidc@3.1.0': + resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} + engines: {node: '>= 20'} + '@wagmi/connectors@6.1.4': resolution: {integrity: sha512-phfBOBBfkH1huSoyyTcHn1Brsm/YN9Vad4Z1ZYJ7iCE05CDUvipXI0TD9Idzgq+CkAJAxdAv3LBTIwTb3tysZw==} peerDependencies: @@ -4947,6 +5016,12 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ai@6.0.116: + resolution: {integrity: sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -6540,6 +6615,10 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + eventsource-parser@3.0.6: + resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + engines: {node: '>=18.0.0'} + evp_bytestokey@1.0.3: resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} @@ -7698,6 +7777,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -9961,6 +10043,10 @@ packages: resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} engines: {node: '>=10'} + throttleit@2.1.0: + resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} + engines: {node: '>=18'} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -10875,6 +10961,40 @@ snapshots: '@adraffy/ens-normalize@1.11.1': {} + '@ai-sdk/gateway@3.0.66(zod@4.1.12)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@4.1.12) + '@vercel/oidc': 3.1.0 + zod: 4.1.12 + + '@ai-sdk/google@3.0.43(zod@4.1.12)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@4.1.12) + zod: 4.1.12 + + '@ai-sdk/provider-utils@4.0.19(zod@4.1.12)': + dependencies: + '@ai-sdk/provider': 3.0.8 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 4.1.12 + + '@ai-sdk/provider@3.0.8': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/react@3.0.118(react@19.2.1)(zod@4.1.12)': + dependencies: + '@ai-sdk/provider-utils': 4.0.19(zod@4.1.12) + ai: 6.0.116(zod@4.1.12) + react: 19.2.1 + swr: 2.3.7(react@19.2.1) + throttleit: 2.1.0 + transitivePeerDependencies: + - zod + '@apollo/client@3.13.1(@types/react@19.2.2)(graphql-ws@5.12.1(graphql@16.12.0))(graphql@16.12.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) @@ -11932,7 +12052,7 @@ snapshots: '@coinbase/wallet-sdk@3.9.3': dependencies: - bn.js: 5.2.2 + bn.js: 5.2.3 buffer: 6.0.3 clsx: 1.2.1 eth-block-tracker: 7.1.0 @@ -13424,7 +13544,7 @@ snapshots: - encoding - immer - '@livepeer/design-system@1.1.0(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)': + '@livepeer/design-system@1.1.0(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)': dependencies: '@radix-ui/colors': 0.1.8 '@radix-ui/react-accessible-icon': 1.1.8(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -13459,7 +13579,7 @@ snapshots: '@stitches/react': 1.2.8(react@19.2.1) lodash.merge: 4.6.2 lodash.omit: 4.5.0 - next-themes: 0.2.1(next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + next-themes: 0.2.1(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) react-transition-group: 4.4.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -13671,7 +13791,7 @@ snapshots: '@types/debug': 4.1.12 debug: 4.4.3 pony-cause: 2.1.11 - semver: 7.7.3 + semver: 7.7.4 uuid: 9.0.1 transitivePeerDependencies: - supports-color @@ -13863,6 +13983,8 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@opentelemetry/api@1.9.0': {} + '@paulirish/trace_engine@0.0.53': dependencies: legacy-javascript: 0.0.1 @@ -13924,7 +14046,7 @@ snapshots: extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 - semver: 7.7.3 + semver: 7.7.4 tar-fs: 3.1.1 yargs: 17.7.2 transitivePeerDependencies: @@ -15336,7 +15458,7 @@ snapshots: '@radix-ui/rect@1.1.1': {} - '@rainbow-me/rainbowkit@2.2.10(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12))': + '@rainbow-me/rainbowkit@2.2.10(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12))': dependencies: '@tanstack/react-query': 5.90.7(react@19.2.1) '@vanilla-extract/css': 1.17.3(babel-plugin-macros@3.1.0) @@ -15349,7 +15471,7 @@ snapshots: react-remove-scroll: 2.6.2(@types/react@19.2.2)(react@19.2.1) ua-parser-js: 1.0.41 viem: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - wagmi: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) + wagmi: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) transitivePeerDependencies: - '@types/react' - babel-plugin-macros @@ -15429,11 +15551,11 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@reown/appkit-controllers@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) viem: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) transitivePeerDependencies: @@ -15464,12 +15586,12 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@reown/appkit-pay@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) lit: 3.3.0 valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) transitivePeerDependencies: @@ -15504,12 +15626,12 @@ snapshots: dependencies: buffer: 6.0.3 - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 transitivePeerDependencies: @@ -15541,10 +15663,10 @@ snapshots: - valtio - zod - '@reown/appkit-ui@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@reown/appkit-ui@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 qrcode: 1.5.3 @@ -15576,14 +15698,14 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12)': + '@reown/appkit-utils@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) viem: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) transitivePeerDependencies: @@ -15625,18 +15747,18 @@ snapshots: - typescript - utf-8-validate - '@reown/appkit@1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@reown/appkit@1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-pay': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-pay': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.2)(react@19.2.1))(zod@4.1.12) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/types': 2.21.0 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.0(@upstash/redis@1.36.4) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) viem: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) @@ -16670,7 +16792,7 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.3 + semver: 7.7.4 ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -16753,6 +16875,21 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@upstash/core-analytics@0.0.10': + dependencies: + '@upstash/redis': 1.36.4 + + '@upstash/ratelimit@2.0.8(@upstash/redis@1.36.4)': + dependencies: + '@upstash/core-analytics': 0.0.10 + '@upstash/redis': 1.36.4 + + '@upstash/redis@1.36.4': + dependencies: + uncrypto: 0.1.3 + + '@upstash/vector@1.2.3': {} + '@vanilla-extract/css@1.17.3(babel-plugin-macros@3.1.0)': dependencies: '@emotion/hash': 0.9.2 @@ -16780,7 +16917,9 @@ snapshots: dependencies: '@vanilla-extract/css': 1.17.3(babel-plugin-macros@3.1.0) - '@wagmi/connectors@6.1.4(dlw36dw4bsuntq3gfdcwuotaby)': + '@vercel/oidc@3.1.0': {} + + '@wagmi/connectors@6.1.4(aetltxkqmmnwo4uuiepedzvcla)': dependencies: '@base-org/account': 2.4.0(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.2)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@4.1.12) @@ -16789,9 +16928,9 @@ snapshots: '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)) + porto: 0.2.35(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)) viem: 2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) optionalDependencies: typescript: 5.9.2 @@ -16849,21 +16988,21 @@ snapshots: - react - use-sync-external-store - '@walletconnect/core@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/core@2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 '@walletconnect/relay-auth': 1.1.0 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.0(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@walletconnect/window-getters': 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 @@ -16893,21 +17032,21 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/core@2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 '@walletconnect/relay-auth': 1.1.0 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.1(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@walletconnect/window-getters': 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 @@ -16941,18 +17080,18 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@reown/appkit': 1.7.8(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@walletconnect/types': 2.21.1 - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) + '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.1(@upstash/redis@1.36.4) + '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -17029,11 +17168,11 @@ snapshots: - bufferutil - utf-8-validate - '@walletconnect/keyvaluestorage@1.1.1': + '@walletconnect/keyvaluestorage@1.1.1(@upstash/redis@1.36.4)': dependencies: '@walletconnect/safe-json': 1.0.2 idb-keyval: 6.2.2 - unstorage: 1.17.2(idb-keyval@6.2.2) + unstorage: 1.17.2(@upstash/redis@1.36.4)(idb-keyval@6.2.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -17075,16 +17214,16 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/sign-client@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/sign-client@2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: - '@walletconnect/core': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/core': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.0(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -17111,16 +17250,16 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/sign-client@2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: - '@walletconnect/core': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/core': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.1(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -17151,12 +17290,12 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/types@2.21.0': + '@walletconnect/types@2.21.0(@upstash/redis@1.36.4)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 events: 3.3.0 transitivePeerDependencies: @@ -17180,12 +17319,12 @@ snapshots: - ioredis - uploadthing - '@walletconnect/types@2.21.1': + '@walletconnect/types@2.21.1(@upstash/redis@1.36.4)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 events: 3.3.0 transitivePeerDependencies: @@ -17209,18 +17348,18 @@ snapshots: - ioredis - uploadthing - '@walletconnect/universal-provider@2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/universal-provider@2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@walletconnect/types': 2.21.0 - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/sign-client': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.0(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) es-toolkit: 1.33.0 events: 3.3.0 transitivePeerDependencies: @@ -17249,18 +17388,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/universal-provider@2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) - '@walletconnect/types': 2.21.1 - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) + '@walletconnect/types': 2.21.1(@upstash/redis@1.36.4) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12) es-toolkit: 1.33.0 events: 3.3.0 transitivePeerDependencies: @@ -17289,18 +17428,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/utils@2.21.0(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@noble/ciphers': 1.2.1 '@noble/curves': 1.8.1 '@noble/hashes': 1.7.1 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/relay-api': 1.0.11 '@walletconnect/relay-auth': 1.1.0 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0 + '@walletconnect/types': 2.21.0(@upstash/redis@1.36.4) '@walletconnect/window-getters': 1.0.1 '@walletconnect/window-metadata': 1.0.1 bs58: 6.0.0 @@ -17333,18 +17472,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': + '@walletconnect/utils@2.21.1(@upstash/redis@1.36.4)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)': dependencies: '@noble/ciphers': 1.2.1 '@noble/curves': 1.8.1 '@noble/hashes': 1.7.1 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.36.4) '@walletconnect/relay-api': 1.0.11 '@walletconnect/relay-auth': 1.1.0 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1 + '@walletconnect/types': 2.21.1(@upstash/redis@1.36.4) '@walletconnect/window-getters': 1.0.1 '@walletconnect/window-metadata': 1.0.1 bs58: 6.0.0 @@ -17599,6 +17738,14 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ai@6.0.116(zod@4.1.12): + dependencies: + '@ai-sdk/gateway': 3.0.66(zod@4.1.12) + '@ai-sdk/provider': 3.0.8 + '@ai-sdk/provider-utils': 4.0.19(zod@4.1.12) + '@opentelemetry/api': 1.9.0 + zod: 4.1.12 + ajv-formats@2.1.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 @@ -19520,6 +19667,8 @@ snapshots: events@3.3.0: {} + eventsource-parser@3.0.6: {} + evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 @@ -20404,7 +20553,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.4 is-callable@1.2.7: {} @@ -20603,7 +20752,7 @@ snapshots: '@babel/parser': 7.28.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.3 + semver: 7.7.4 transitivePeerDependencies: - supports-color @@ -21070,6 +21219,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stable-stringify@1.3.0: @@ -21360,7 +21511,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.4 make-error@1.3.6: {} @@ -22184,13 +22335,13 @@ snapshots: netmask@2.0.2: {} - next-themes@0.2.1(next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + next-themes@0.2.1(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1): dependencies: - next: 16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + next: 16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - next@16.1.5(@babel/core@7.28.5)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1): dependencies: '@next/env': 16.1.5 '@swc/helpers': 0.5.15 @@ -22209,6 +22360,7 @@ snapshots: '@next/swc-linux-x64-musl': 16.1.5 '@next/swc-win32-arm64-msvc': 16.1.5 '@next/swc-win32-x64-msvc': 16.1.5 + '@opentelemetry/api': 1.9.0 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -22411,7 +22563,7 @@ snapshots: dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 + '@noble/hashes': 1.8.0 '@scure/bip32': 1.6.2 '@scure/bip39': 1.5.4 abitype: 1.1.1(typescript@5.9.2)(zod@4.1.12) @@ -22666,7 +22818,7 @@ snapshots: pony-cause@2.1.11: {} - porto@0.2.35(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)): + porto@0.2.35(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)) hono: 4.10.4 @@ -22680,7 +22832,7 @@ snapshots: '@tanstack/react-query': 5.90.7(react@19.2.1) react: 19.2.1 typescript: 5.9.2 - wagmi: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) + wagmi: 2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12) transitivePeerDependencies: - '@types/react' - immer @@ -24054,6 +24206,8 @@ snapshots: throttle-debounce@3.0.1: {} + throttleit@2.1.0: {} + through@2.3.8: {} tiny-invariant@1.3.3: {} @@ -24430,7 +24584,7 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - unstorage@1.17.2(idb-keyval@6.2.2): + unstorage@1.17.2(@upstash/redis@1.36.4)(idb-keyval@6.2.2): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -24441,6 +24595,7 @@ snapshots: ofetch: 1.5.1 ufo: 1.6.1 optionalDependencies: + '@upstash/redis': 1.36.4 idb-keyval: 6.2.2 update-browserslist-db@1.1.4(browserslist@4.28.0): @@ -24667,10 +24822,10 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12): + wagmi@2.19.3(@tanstack/query-core@5.90.7)(@tanstack/react-query@5.90.7(react@19.2.1))(@types/react@19.2.2)(@upstash/redis@1.36.4)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12))(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.12): dependencies: '@tanstack/react-query': 5.90.7(react@19.2.1) - '@wagmi/connectors': 6.1.4(dlw36dw4bsuntq3gfdcwuotaby) + '@wagmi/connectors': 6.1.4(aetltxkqmmnwo4uuiepedzvcla) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.7)(@types/react@19.2.2)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.38.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.12)) react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1)