diff --git a/examples/cookbook/vercel-voice-agent/.env.example b/examples/cookbook/vercel-voice-agent/.env.example new file mode 100644 index 00000000..742620db --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/.env.example @@ -0,0 +1,12 @@ +MOSS_PROJECT_ID=your-project-id +MOSS_PROJECT_KEY=your-project-key +MOSS_INDEX_NAME=your-index-name + +# Vercel AI Gateway — generates WebSocket tokens + routes to gpt-realtime-2 +# Get key: https://vercel.com/dashboard/ai-gateway +AI_GATEWAY_API_KEY=your-vercel-ai-gateway-key + +# Demo auth — set both to the same value; omit to disable the check locally +DEMO_SECRET=change-me +NEXT_PUBLIC_DEMO_SECRET=change-me +ALLOW_UNAUTHENTICATED_DEMO=true \ No newline at end of file diff --git a/examples/cookbook/vercel-voice-agent/README.md b/examples/cookbook/vercel-voice-agent/README.md new file mode 100644 index 00000000..3556f1bf --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/README.md @@ -0,0 +1,49 @@ +# MOSS Voice Agent — Vercel AI Gateway + +Realtime voice agent using [Vercel AI Gateway](https://vercel.com/blog/realtime-voice-agents-on-ai-gateway) with MOSS as the knowledge base. Speak a question — the agent searches your MOSS index and answers out loud. + +## Architecture + +```text +Browser (useRealtime) ──WebSocket── Vercel AI Gateway ── gpt-realtime-2 + │ │ + │ tool call: search_knowledge_base │ + └─── POST /api/token ───────────────►│ + MOSS index (local) +``` + +- `POST /api/token` (empty body) — mints a short-lived WebSocket token via the gateway +- `POST /api/token` (`{ query }`) — executes MOSS search; uses local in-memory index loaded at startup + +> **Security note:** `/api/token` is unauthenticated for demo purposes. Before deploying publicly, add a session/cookie check so arbitrary callers cannot mint Gateway tokens or query your index. + +## Setup + +### 1. Install dependencies + +Requires **Node.js ≥ 22** (`ai@7` and `@ai-sdk/gateway@4` require it). + +```bash +npm install +``` + +### 2. Add credentials + +```bash +cp .env.example .env +``` + +| Variable | Where to get it | +| --- | --- | +| `MOSS_PROJECT_ID` | [moss.dev](https://moss.dev) dashboard | +| `MOSS_PROJECT_KEY` | [moss.dev](https://moss.dev) dashboard | +| `MOSS_INDEX_NAME` | Name of the index to search | +| `AI_GATEWAY_API_KEY` | [Vercel AI Gateway](https://vercel.com/dashboard/ai-gateway) → API Keys | + +### 3. Run + +```bash +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) and tap the orb to start talking. diff --git a/examples/cookbook/vercel-voice-agent/app/api/token/route.ts b/examples/cookbook/vercel-voice-agent/app/api/token/route.ts new file mode 100644 index 00000000..484cd42c --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/app/api/token/route.ts @@ -0,0 +1,73 @@ +import { createGateway } from '@ai-sdk/gateway'; +import { MossClient } from '@moss-dev/moss'; +import { mossSearchTool } from '@moss-tools/vercel-sdk'; + +export const runtime = 'nodejs'; + +const gateway = createGateway({ apiKey: process.env.AI_GATEWAY_API_KEY }); + +const client = new MossClient( + process.env.MOSS_PROJECT_ID!, + process.env.MOSS_PROJECT_KEY!, +); + +const searchTool = mossSearchTool({ + client, + indexName: process.env.MOSS_INDEX_NAME!, +}); + +// Load the index into local memory at startup. +// Cloud query returns 503 — local queries work fine after loadIndex. +// Storing the promise means search requests block until ready, or fail fast if it rejects. +const indexReady = client.loadIndex(process.env.MOSS_INDEX_NAME!) + .then(() => console.log('[MOSS] index loaded locally')) + .catch((err: unknown) => { console.error('[MOSS] loadIndex failed:', err); throw err; }); + +const MOSS_TOOL = { + type: 'function' as const, + name: 'search_knowledge_base', + description: searchTool.description, + parameters: { + type: 'object', + properties: { + query: { type: 'string', description: 'Concise search query' }, + topK: { type: 'integer', minimum: 1, maximum: 100, description: 'Number of results to return (1–100, default 5)' }, + }, + required: ['query'], + }, +}; + +// POST (empty body) → mint a short-lived WebSocket token via Vercel AI Gateway +// POST ({ query }) → execute MOSS search on behalf of the realtime model's tool call +// +// Auth: fails closed (401) unless ALLOW_UNAUTHENTICATED_DEMO=true is explicitly set. +// For production, replace this check with a real session/token verification. +export async function POST(req: Request) { + if (process.env.ALLOW_UNAUTHENTICATED_DEMO !== 'true') { + return new Response('Unauthorized', { status: 401 }); + } + + const body = await req.json().catch(() => ({})) as Record; + + if (typeof body.query === 'string') { + try { + await indexReady; + } catch { + return new Response('Search index unavailable', { status: 503 }); + } + const topK = Number.isInteger(body.topK) ? Math.min(100, Math.max(1, body.topK as number)) : 5; + const result = await searchTool.execute!( + { query: body.query, topK }, + { toolCallId: 'realtime', messages: [], abortSignal: req.signal }, + ); + const docs = (result as { docs: Array<{ text: string }> }).docs ?? []; + return new Response(docs.map((d) => d.text).join('\n\n---\n\n'), { + headers: { 'Content-Type': 'text/plain' }, + }); + } + + const { token, url } = await gateway.experimental_realtime.getToken({ + model: 'openai/gpt-realtime-2', + }); + return Response.json({ token, url, tools: [MOSS_TOOL] }); +} diff --git a/examples/cookbook/vercel-voice-agent/app/layout.tsx b/examples/cookbook/vercel-voice-agent/app/layout.tsx new file mode 100644 index 00000000..5015511e --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/app/layout.tsx @@ -0,0 +1,28 @@ +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'MOSS Voice Agent', + description: 'Realtime voice agent powered by Vercel AI Gateway and MOSS semantic search', +}; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + + + {children} + + + ); +} diff --git a/examples/cookbook/vercel-voice-agent/app/page.tsx b/examples/cookbook/vercel-voice-agent/app/page.tsx new file mode 100644 index 00000000..a2035906 --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/app/page.tsx @@ -0,0 +1,350 @@ +'use client'; + +import { experimental_useRealtime as useRealtime } from '@ai-sdk/react'; +import { gateway } from '@ai-sdk/gateway'; +import { useMemo, useState } from 'react'; + +type SearchEntry = { query: string; hits: number }; + +// MOSS design tokens (dark mode) — monochromatic white-based brand +const c = { + bg: '#0a0a0a', + bgAlt: '#111110', + bgElevated:'#181816', + border: '#222220', + borderSub: '#1a1a18', + text1: '#f0f0ee', + text2: '#888', + text3: '#555', + brand: '#e8e8e4', // MOSS brand — warm near-white + brandDim: '#ccccc6', + brandGlow: 'rgba(232,232,228,0.06)', + green: '#10b981', + greenGlow: 'rgba(16,185,129,0.12)', +}; + +export default function Page() { + const [connected, setConnected] = useState(false); + const [searches, setSearches] = useState([]); + const [isSpeaking, setIsSpeaking] = useState(false); + const [error, setError] = useState(null); + + + const model = useMemo( + () => gateway.experimental_realtime('openai/gpt-realtime-2'), + [], + ); + + const { connect, disconnect, startAudioCapture, stopAudioCapture, isCapturing } = + useRealtime({ + model, + api: { token: '/api/token' }, + sessionConfig: { + voice: 'alloy', + turnDetection: { type: 'server-vad' }, + instructions: + 'You are a helpful voice assistant with access to a knowledge base. ' + + 'Always call search_knowledge_base before answering factual questions. ' + + 'Keep answers brief — two or three sentences.', + }, + onError: (err) => setError(err instanceof Error ? err.message : String(err)), + onEvent: (event) => { + if (event.type === 'session-created') setConnected(true); + if (event.type === 'audio-delta') setIsSpeaking(true); + if (event.type === 'audio-done') setIsSpeaking(false); + }, + onToolCall: async ({ toolCall }) => { + if (toolCall.toolName !== 'search_knowledge_base') return; + const { query, topK } = toolCall.args as { query: string; topK?: number }; + const res = await fetch('/api/token', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query, topK: topK ?? 5 }), + }); + const text = await res.text(); + const hits = text.trim() ? text.split('\n\n---\n\n').length : 0; + setSearches((s) => [{ query, hits }, ...s.slice(0, 4)]); + return text; + }, + }); + + const handleToggle = async () => { + setError(null); + if (connected) { + stopAudioCapture(); + disconnect(); + setConnected(false); + setIsSpeaking(false); + } else { + let stream: MediaStream | undefined; + try { + stream = await navigator.mediaDevices.getUserMedia({ + audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true }, + }); + await connect(); + startAudioCapture(stream); + } catch (err) { + stream?.getTracks().forEach((t) => t.stop()); + disconnect(); + setError(err instanceof Error ? err.message : String(err)); + } + } + }; + + const phase = !connected ? 'idle' + : isSpeaking ? 'speaking' + : isCapturing ? 'listening' + : 'ready'; + + const orbGlow = phase === 'speaking' ? c.brandGlow + : phase === 'listening' ? 'rgba(255,255,255,0.04)' + : phase === 'ready' ? c.greenGlow + : 'transparent'; + + const orbBorder = phase === 'speaking' ? c.brand + : phase === 'listening' ? '#3a3a38' + : phase === 'ready' ? c.green + : c.border; + + const statusColor = phase === 'speaking' ? c.brand + : phase === 'listening' ? c.text1 + : phase === 'ready' ? c.green + : c.text3; + + const statusLabel = phase === 'speaking' ? 'Speaking' + : phase === 'listening' ? 'Listening' + : phase === 'ready' ? 'Ready' + : 'Tap to start'; + + return ( +
+ + {/* Subtle radial bg */} +
+ + {/* Logo */} +
+
+ MOSS + + MOSS + +
+
+ + Voice Agent +
+
+ + {/* Main content */} +
+ + {/* Orb */} +
+ {/* Glow ring */} +
+ + +
+ + {/* Status */} +
+

+ {statusLabel} +

+

+ {connected + ? 'gpt-realtime-2 · MOSS · server VAD' + : 'Click to connect · gpt-realtime-2'} +

+
+ + {/* Error */} + {error && ( +
+ {error} +
+ )} + + {/* MOSS search log */} + {searches.length > 0 && ( +
+

+ Knowledge lookups +

+
+ {searches.map((s, i) => ( +
+ + + {s.query} + + + {s.hits} result{s.hits !== 1 ? 's' : ''} + +
+ ))} +
+
+ )} +
+ + +
+ ); +} + +function MicIcon({ active, speaking }: { active: boolean; speaking: boolean }) { + const color = speaking ? '#7200E1' : active ? '#f0f0ee' : '#555'; + return ( + + + + + + + ); +} diff --git a/examples/cookbook/vercel-voice-agent/images/image.png b/examples/cookbook/vercel-voice-agent/images/image.png new file mode 100644 index 00000000..b64d8c1d Binary files /dev/null and b/examples/cookbook/vercel-voice-agent/images/image.png differ diff --git a/examples/cookbook/vercel-voice-agent/next-env.d.ts b/examples/cookbook/vercel-voice-agent/next-env.d.ts new file mode 100644 index 00000000..830fb594 --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/examples/cookbook/vercel-voice-agent/next.config.ts b/examples/cookbook/vercel-voice-agent/next.config.ts new file mode 100644 index 00000000..c76107dc --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + serverExternalPackages: ['@moss-dev/moss', '@moss-dev/moss-core'], +}; + +export default nextConfig; diff --git a/examples/cookbook/vercel-voice-agent/package-lock.json b/examples/cookbook/vercel-voice-agent/package-lock.json new file mode 100644 index 00000000..ab4538e1 --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/package-lock.json @@ -0,0 +1,1319 @@ +{ + "name": "moss-vercel-voice-agent", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "moss-vercel-voice-agent", + "version": "0.1.0", + "dependencies": { + "@ai-sdk/gateway": "^4.0.6", + "@ai-sdk/react": "^4.0.9", + "@moss-dev/moss": "latest", + "@moss-tools/vercel-sdk": "^0.1.1", + "ai": "^7.0.8", + "next": "^15.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "typescript": "^5.8.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@ai-sdk/gateway": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-4.0.7.tgz", + "integrity": "sha512-L0/CZwEL8AHO/Nxe5D0laNq9Q44mrKcth99tPgMNHqfsYbbNExwke4OYH18o/eLd3FLLBxs+03SuHP+Gcyp51Q==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "4.0.1", + "@ai-sdk/provider-utils": "5.0.2", + "@vercel/oidc": "3.2.0" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/mcp": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@ai-sdk/mcp/-/mcp-2.0.4.tgz", + "integrity": "sha512-o5edIxgQrssKl/DABaXOzTUG/DUOyn25ilnnczQeLpnlSEUNXqYc3TSOZ7u6aBB+vkersQ7MXkfNMzqulR6CKw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "4.0.1", + "@ai-sdk/provider-utils": "5.0.2", + "pkce-challenge": "^5.0.1" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-4.0.1.tgz", + "integrity": "sha512-6p3C/vGqVIjcptBu1DnVd/BZJ2wWmV9TUv9192vT6ZvT9KNED8EwRTqyqFpoQZKgSbMDSvBSq3dqR524Nt/Crw==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-5.0.2.tgz", + "integrity": "sha512-EcmdjJb7yggsZPCbS3MFBpvAUnKaPW+QvanU5GzF00XCq0bqqAmvJ3MN19ejlmOETbW8sJNiq6qam48wTcbUNw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "4.0.1", + "@standard-schema/spec": "^1.1.0", + "@workflow/serde": "4.1.0", + "eventsource-parser": "^3.0.8" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/react": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-4.0.10.tgz", + "integrity": "sha512-Qved3q/Wml+OB2tEhH2tNXeiP4+6jeytoZIJ2cODHL55QQyOkfJhScEZz33CRlzUSvvaJT0+VbqnTYknrD6GNg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/mcp": "2.0.4", + "@ai-sdk/provider": "4.0.1", + "@ai-sdk/provider-utils": "5.0.2", + "ai": "7.0.9", + "swr": "^2.4.1", + "throttleit": "2.1.0" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@moss-dev/moss": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss/-/moss-1.3.1.tgz", + "integrity": "sha512-DU6m+1kPBtWJ3iJEHZ5qQCunJBvL2xx/v1NsW6mQfh245QZhQGikS/Zsn8UKxl+M5rPaozKL5aQX4NmrdYvqZQ==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@moss-dev/moss-core": "0.19.1" + } + }, + "node_modules/@moss-dev/moss-core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core/-/moss-core-0.19.1.tgz", + "integrity": "sha512-YeH+kKuHVyEW0JRF2jP90VQbV8HeGfRtV9U5u5v9MVo0WQ4Lfa8kqM509TE4VMOpHDpO7HMDKn/izRR6Vvw3+w==", + "license": "Proprietary", + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "@moss-dev/moss-core-darwin-arm64": "0.19.1", + "@moss-dev/moss-core-darwin-x64": "0.19.1", + "@moss-dev/moss-core-linux-arm64-gnu": "0.19.1", + "@moss-dev/moss-core-linux-x64-gnu": "0.19.1", + "@moss-dev/moss-core-win32-x64-msvc": "0.19.1" + } + }, + "node_modules/@moss-dev/moss-core-darwin-arm64": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-darwin-arm64/-/moss-core-darwin-arm64-0.19.1.tgz", + "integrity": "sha512-Tu8moQH3hMRfEv/C9fB2HLY7wVoxlVQ2a6vJrBPYdqnEpQRdDNggos3bBevarxEnJhDgp27zvjw5UeWN+H+YRg==", + "cpu": [ + "arm64" + ], + "license": "Proprietary", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@moss-dev/moss-core-darwin-x64": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-darwin-x64/-/moss-core-darwin-x64-0.19.1.tgz", + "integrity": "sha512-DIv/mQrQMR8OYyT/bXXVx6s/XagGzuhbUESvEN9OWQu1eAYD2hqOyJXjAOMsVVYLCB8o0nlolQfbnFiYRUlvbQ==", + "cpu": [ + "x64" + ], + "license": "Proprietary", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@moss-dev/moss-core-linux-arm64-gnu": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-linux-arm64-gnu/-/moss-core-linux-arm64-gnu-0.19.1.tgz", + "integrity": "sha512-OrOM6n0z/T5ZryiOwGEBy14zqn/kJXMbTNykBlJIZmCIA0cCvPZqLUt2cMVh+Y51Ofy4HhMnXuyFmsLC8nER0g==", + "cpu": [ + "arm64" + ], + "license": "Proprietary", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@moss-dev/moss-core-linux-x64-gnu": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-linux-x64-gnu/-/moss-core-linux-x64-gnu-0.19.1.tgz", + "integrity": "sha512-18dZ8pFr0LZvfGCkxGXyCk9zqSmWPKcn5Cmt+JaSfA0vmZiZjQ4EgWAQdTJxGBs+cIa+vc3oMaVGuvJiotMhnw==", + "cpu": [ + "x64" + ], + "license": "Proprietary", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@moss-dev/moss-core-win32-x64-msvc": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@moss-dev/moss-core-win32-x64-msvc/-/moss-core-win32-x64-msvc-0.19.1.tgz", + "integrity": "sha512-VvOuq/U8IsRdHoGvcJH5jBM1QYuAQsJ7BUcr+OSXqFfht0TB4OpJMHcn9frSzVQ16ULf8x0ewSZYteNxLXKu9w==", + "cpu": [ + "x64" + ], + "license": "Proprietary", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@moss-tools/vercel-sdk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@moss-tools/vercel-sdk/-/vercel-sdk-0.1.1.tgz", + "integrity": "sha512-9X2MJTBGLD5DMfmxYKotAHRoM+VU8HwK+8LkbFb2/od8/cX6evZSGfvdpmSkMPrR9JhTTp4tlCDgNxdWjoW8/g==", + "license": "BSD-2-Clause", + "peerDependencies": { + "@moss-dev/moss": "^1.0.0", + "ai": "^6.0.0 || ^7.0.0", + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@next/env": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.19.tgz", + "integrity": "sha512-sWWluFvcv5v3Fxznmf2ZfjyoVQt/64oCnYqS90inQWGzMPK1VjvekPiz3OPHKmFT30EnHrjlbyaHLt3M0vWabw==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.19.tgz", + "integrity": "sha512-jx9wWlTKueHKPvVOndyr7WuaevWCkuYqsQ8gC0TMPKAVWG3MhcdMrjfo9tvIZNXd0QOUYXXvAcZ325y8Uq7uzg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.19.tgz", + "integrity": "sha512-291KFcsIQ3OenRdiUDFOR6W3wezzH4auENXm1gbm1Bjd4ANMMRgxPrWTUztQN43BnVoVuMnHCrLeECIMwgFKbA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.19.tgz", + "integrity": "sha512-WeH+nelQyyMeE2f8FxBRZNrGipya5zHZV2vjzfCOAYyiI6am+NbnWAAldOBFQBB2w0DjJcsvrKqoFT2b7+5YoA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.19.tgz", + "integrity": "sha512-5xTOE0lDlDCSSfp+BAif7j17VRRCjWp//ZPZy6NI0QpdrhxtQnsZguSx0xAAZ0c9XZLrLLwCe/XVe5YPrRilKw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.19.tgz", + "integrity": "sha512-LTxRmMgqqMv05Had879W00Fm53quiJd3Zuz8h1JSNJ3nGSlbZ/7Tjs1tKyScgN3Au3t3MyPsjPlq60fMmSHLsg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.19.tgz", + "integrity": "sha512-eoNQSpA5PQfB9wBO4RA47MTDXWz1fizy9Y3Z6e4DetYIF3dvjuu8sj7aIGn/bFCU6lnFzTK34NtCaffP4NsQ7Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.19.tgz", + "integrity": "sha512-6UNt2dFuCHOe446sm/Kp69nUe8/wIhnh9bm6Xcqw4qEWCOppLMOvhTBVgvM7invVUNr4SPpP6NOQsACtn2IN9Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.19.tgz", + "integrity": "sha512-PhmojAHyqMne56HBLGu9dhDnHPuFmEjrXSQMM/nW0J6j849lk3ESrVtqNJcCk8CKOV7brpTTbaYAjwKPzKM69w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/node": { + "version": "22.20.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", + "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@vercel/oidc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.2.0.tgz", + "integrity": "sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@workflow/serde": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@workflow/serde/-/serde-4.1.0.tgz", + "integrity": "sha512-pav4F2BoirECWR7Nf1TKt+2eETcBj7jj4cBefQ8VXQCA6NPkaKeLfj/zMgi+3zYV5ZIBT4GuUiphsj0/b9hPQQ==", + "license": "Apache-2.0" + }, + "node_modules/ai": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/ai/-/ai-7.0.9.tgz", + "integrity": "sha512-yoxg/ousRxSX5Ko4+/8SH4vsc8BzoQqG7ywtS04L0kLH/+Ww71c+zqdTDXNVRQteDtKFGmt8+Q82ra/NbzjYqA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "4.0.7", + "@ai-sdk/provider": "4.0.1", + "@ai-sdk/provider-utils": "5.0.2" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.0.tgz", + "integrity": "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "15.5.19", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.19.tgz", + "integrity": "sha512-xNOW6tYshGX1/Oi3F8uuk4gpDeWsSUE/1Z0G5uUMekIxaQ0xc03UXd9II0VQHYMWviMeA0OHpJFAKsHf8bTYVg==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.19", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.19", + "@next/swc-darwin-x64": "15.5.19", + "@next/swc-linux-arm64-gnu": "15.5.19", + "@next/swc-linux-arm64-musl": "15.5.19", + "@next/swc-linux-x64-gnu": "15.5.19", + "@next/swc-linux-x64-musl": "15.5.19", + "@next/swc-win32-arm64-msvc": "15.5.19", + "@next/swc-win32-x64-msvc": "15.5.19", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/swr": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.4.2.tgz", + "integrity": "sha512-ej644Y2bvkIajfR32KGeSSdBXQW+ScjGjkybZgSE7kFpk9eGnV44XY9FJylXi+W75pavSX1PVNB57W5EbhGIYw==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/throttleit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", + "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/examples/cookbook/vercel-voice-agent/package.json b/examples/cookbook/vercel-voice-agent/package.json new file mode 100644 index 00000000..48c5a17e --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/package.json @@ -0,0 +1,30 @@ +{ + "name": "moss-vercel-voice-agent", + "version": "0.1.0", + "private": true, + "engines": { + "node": ">=22" + }, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "@ai-sdk/gateway": "^4.0.6", + "@ai-sdk/react": "^4.0.9", + "@moss-dev/moss": "latest", + "@moss-tools/vercel-sdk": "^0.1.1", + "ai": "^7.0.8", + "next": "^15.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "typescript": "^5.8.0" + } +} diff --git a/examples/cookbook/vercel-voice-agent/public/moss-logo.png b/examples/cookbook/vercel-voice-agent/public/moss-logo.png new file mode 100644 index 00000000..b64d8c1d Binary files /dev/null and b/examples/cookbook/vercel-voice-agent/public/moss-logo.png differ diff --git a/examples/cookbook/vercel-voice-agent/tsconfig.json b/examples/cookbook/vercel-voice-agent/tsconfig.json new file mode 100644 index 00000000..afedc744 --- /dev/null +++ b/examples/cookbook/vercel-voice-agent/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [{ "name": "next" }], + "paths": { "@/*": ["./*"] } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}