diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 3cf8dc9..67f91ef 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -35,5 +35,5 @@ jobs: run: bun install - name: Run tests - run: bun run test + run: bunx turbo run test --filter='!python-tools' diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml new file mode 100644 index 0000000..deebe3a --- /dev/null +++ b/.github/workflows/update-dependencies.yml @@ -0,0 +1,57 @@ +name: Update Dependencies + +on: + schedule: + # Runs every other Monday at 9am UTC (biweekly check) + - cron: '0 9 * * 1' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + update-deps: + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'schedule' && (github.run_number % 2 == 0)) + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + ref: staging + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Update dependencies with taze + run: bunx taze -r -w + + - name: Install updated dependencies + run: bun install + + - name: Check for changes + id: changes + run: | + if git diff --quiet; then + echo "has_changes=false" >> $GITHUB_OUTPUT + else + echo "has_changes=true" >> $GITHUB_OUTPUT + fi + + - name: Create Pull Request + if: steps.changes.outputs.has_changes == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: chore/update-dependencies + base: staging + commit-message: 'chore: update dependencies' + title: 'chore: update dependencies' + body: | + Automated dependency update via `bunx taze -r -w`. + + Please review the changes and ensure tests pass before merging. + labels: dependencies + delete-branch: true diff --git a/AGENTS.md b/AGENTS.md index 8c5d9a1..4cc84da 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -400,3 +400,56 @@ Environment Variables & Port Configuration - Add ngrok domains to `ALLOWED_ORIGINS` for external dev access Done. This guide covers the minimal, repeatable steps for adding new tools and flows with token‑efficient prompts and predictable UX. + +Conversation Logging (ML Training Data) + +The system captures all user transcripts and LLM responses to Convex for ML training and improvement. + +**Architecture:** +- **Schema**: `packages/convex/schema.ts` → `conversationLogs` table +- **Convex mutations**: `packages/convex/conversationLogs.ts` → `logConversation`, `updateResponse` +- **Application utility**: `apps/application/src/core/conversationLogger.ts` → fire-and-forget logging functions + +**Data Flow:** +1. `handleTranscription` receives utterance → routes via BAML `b.Route()` +2. Immediately after routing: `logConversation(userId, sessionId, transcript, route)` creates initial record +3. Handler processes request → displays response on glasses +4. Handler calls `updateConversationResponse(userId, sessionId, transcript, response)` to capture formatted output + +**LogContext Pattern:** +Handlers that capture responses receive an optional `logContext` parameter: +```ts +logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string } +``` + +After displaying lines, call: +```ts +if (logContext) { + const responseText = lines.map((l) => `W: ${l}`).join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); +} +``` + +**Coverage by Route:** +| Route | Initial Log | Response Captured | Notes | +|-------|-------------|-------------------|-------| +| WEATHER | ✓ | ✓ | Weather summary lines | +| MAPS | ✓ | ✓ | Place recommendations | +| WEB_SEARCH | ✓ | ✓ | Search answer lines | +| KNOWLEDGE | ✓ | ✓ | General knowledge answer | +| MEMORY_RECALL | ✓ | ✓ | Synthesized memory lines | +| MEMORY_CAPTURE | ✓ | ✗ | Silent operation (stores to Honcho) | +| PASSTHROUGH | ✓ | ✓ (when hint shown) | Null case for ambient speech | +| NOTE_THIS | ✓ | ✗ | Meta-action, not content response | +| FOLLOW_UP | ✓ | ✗ | Meta-action, not content response | + +**Key Points:** +- Use fire-and-forget pattern: `void convexClient.mutation(...)` with `.catch()` for error logging +- Response field captures the formatted text shown on glasses (e.g., `"W: 72°F and sunny"`) +- PASSTHROUGH with no hint = null response (valuable for training router to identify ambient speech) +- Initial log happens in `transcriptionFlow.ts`; response update happens in individual handlers diff --git a/apps/api/package.json b/apps/api/package.json index 6f3430a..64f68c1 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -19,9 +19,9 @@ "test": "echo 'No tests configured for @clairvoyant/api'" }, "dependencies": { - "@elysiajs/cors": "^1.4.0", + "@elysiajs/cors": "^1.4.1", "@t3-oss/env-core": "^0.13.10", - "convex": "^1.31.2", + "convex": "^1.32.0", "jose": "^6.1.3", "jsonwebtoken": "^9.0.3", "zod": "^3.25.76" diff --git a/apps/application/package.json b/apps/application/package.json index 581287c..d8d24e7 100644 --- a/apps/application/package.json +++ b/apps/application/package.json @@ -15,10 +15,10 @@ "@boundaryml/baml": "0.215.0", "@clairvoyant/baml-client": "workspace:*", "@honcho-ai/sdk": "^1.6.0", - "@mentra/sdk": "^2.1.28", + "@mentra/sdk": "^2.1.29", "@t3-oss/env-core": "^0.13.10", "@tavily/core": "^0.5.14", - "convex": "^1.31.2", + "convex": "^1.32.0", "exa-js": "^1.10.2", "openai": "^5.23.2", "zod": "^3.25.76" diff --git a/apps/application/src/core/conversationLogger.ts b/apps/application/src/core/conversationLogger.ts new file mode 100644 index 0000000..f427a54 --- /dev/null +++ b/apps/application/src/core/conversationLogger.ts @@ -0,0 +1,53 @@ +import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; +import { convexClient } from "./convex"; + +/** + * Logs a conversation to Convex for ML training data. + * Uses fire-and-forget pattern - errors are logged but don't block. + */ +export function logConversation( + userId: Id<"users">, + sessionId: string, + transcript: string, + route: string, + response?: string, +): void { + void convexClient + .mutation(api.conversationLogs.logConversation, { + userId, + sessionId, + transcript, + route, + response, + }) + .catch((error) => { + console.error("[ConversationLogger] Failed to log conversation:", error); + }); +} + +/** + * Updates the response field for a previously logged conversation. + * Used by handlers to capture the final formatted response shown on glasses. + * Uses fire-and-forget pattern - errors are logged but don't block. + */ +export function updateConversationResponse( + userId: Id<"users">, + sessionId: string, + transcript: string, + response: string, +): void { + void convexClient + .mutation(api.conversationLogs.updateResponse, { + userId, + sessionId, + transcript, + response, + }) + .catch((error) => { + console.error( + "[ConversationLogger] Failed to update conversation response:", + error, + ); + }); +} diff --git a/apps/application/src/handlers/hints.ts b/apps/application/src/handlers/hints.ts index 5c6cd76..98c2715 100644 --- a/apps/application/src/handlers/hints.ts +++ b/apps/application/src/handlers/hints.ts @@ -1,7 +1,9 @@ import { b, HintCategory } from "@clairvoyant/baml-client"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient } from "../core/convex"; import type { DisplayQueueManager } from "../core/displayQueue"; @@ -14,6 +16,7 @@ export async function tryPassthroughHint( peers: Peer[], mentraUserId: string, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ): Promise { const runId = Date.now(); hintRunIds.set(session, runId); @@ -163,6 +166,16 @@ export async function tryPassthroughHint( durationMs: 4000, priority: 3, }); + + // Log the hint response for ML training + if (logContext) { + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + `H: ${hintResult.hint}`, + ); + } } catch (error) { session.logger.error(`[tryPassthroughHint] Error: ${String(error)}`); } diff --git a/apps/application/src/handlers/knowledge.ts b/apps/application/src/handlers/knowledge.ts index 9edab24..edc3187 100644 --- a/apps/application/src/handlers/knowledge.ts +++ b/apps/application/src/handlers/knowledge.ts @@ -1,7 +1,9 @@ import { b } from "@clairvoyant/baml-client"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient } from "../core/convex"; import type { DisplayQueueManager } from "../core/displayQueue"; import { showTextDuringOperation } from "../core/textWall"; @@ -17,6 +19,7 @@ export async function startKnowledgeFlow( peers: Peer[], mentraUserId: string, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { const runId = Date.now(); knowledgeRunIds.set(session, runId); @@ -228,6 +231,21 @@ export async function startKnowledgeFlow( priority: 2, }); } + + if (logContext && answerLines.length > 0) { + const responseText = answerLines + .map((line, i) => { + const label = answerLines.length > 1 ? `A${i + 1}` : "A"; + return `Q: ${questionLine}\n${label}: ${line}`; + }) + .join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); + } } else { displayQueue.enqueue({ text: "// Clairvoyant\nK: No question detected.", diff --git a/apps/application/src/handlers/maps.ts b/apps/application/src/handlers/maps.ts index 8b03c4f..45a63cc 100644 --- a/apps/application/src/handlers/maps.ts +++ b/apps/application/src/handlers/maps.ts @@ -1,7 +1,9 @@ import { b } from "@clairvoyant/baml-client"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient, @@ -30,6 +32,7 @@ async function processPlacesData( places: PlaceSuggestion[], runId: number, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { if (!places?.length) { displayQueue.enqueue({ @@ -188,6 +191,16 @@ async function processPlacesData( priority: 2, }); } + + if (logContext && lines.length > 0) { + const responseText = lines.map((l) => `M: ${l}`).join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); + } } export async function startMapsFlow( @@ -197,6 +210,7 @@ export async function startMapsFlow( peers: Peer[], mentraUserId: string, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { const runId = Date.now(); mapsRunIds.set(session, runId); @@ -287,6 +301,7 @@ export async function startMapsFlow( places, runId, displayQueue, + logContext, ); } catch (error) { session.logger.error(`[startMapsFlow] Maps flow error: ${String(error)}`); @@ -376,6 +391,7 @@ export async function startMapsFlow( places, runId, displayQueue, + logContext, ); } catch (error) { session.logger.error( diff --git a/apps/application/src/handlers/memory.ts b/apps/application/src/handlers/memory.ts index 84e7bb5..11ee0a5 100644 --- a/apps/application/src/handlers/memory.ts +++ b/apps/application/src/handlers/memory.ts @@ -1,7 +1,9 @@ import { b } from "@clairvoyant/baml-client"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient } from "../core/convex"; import type { DisplayQueueManager } from "../core/displayQueue"; @@ -78,6 +80,7 @@ export async function MemoryRecall( peers: Peer[], mentraUserId: string, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { const runId = Date.now(); memoryRunCallIds.set(session, runId); @@ -251,6 +254,17 @@ export async function MemoryRecall( priority: 2, }); } + + // Log the response for ML training + if (logContext) { + const responseText = lines.map((l) => `R: ${l}`).join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); + } } else { session.logger.error( `[startMemoryRecallFlow] No lines in synthesis results`, diff --git a/apps/application/src/handlers/search.ts b/apps/application/src/handlers/search.ts index 1ba5cb7..8aaa436 100644 --- a/apps/application/src/handlers/search.ts +++ b/apps/application/src/handlers/search.ts @@ -1,7 +1,9 @@ import { b } from "@clairvoyant/baml-client"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient } from "../core/convex"; import type { DisplayQueueManager } from "../core/displayQueue"; import { showTextDuringOperation } from "../core/textWall"; @@ -18,6 +20,7 @@ export async function startWebSearchFlow( peers: Peer[], mentraUserId: string, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { const runId = Date.now(); webSearchRunIds.set(session, runId); @@ -231,6 +234,16 @@ export async function startWebSearchFlow( priority: 2, }); } + + if (logContext) { + const responseText = lines.map((l) => `S: ${l}`).join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); + } } else { session.logger.error(`[startWebSearchFlow] No lines in answerLines`); } diff --git a/apps/application/src/handlers/weather.ts b/apps/application/src/handlers/weather.ts index 29d6bf6..0119ac5 100644 --- a/apps/application/src/handlers/weather.ts +++ b/apps/application/src/handlers/weather.ts @@ -1,8 +1,10 @@ import { b } from "@clairvoyant/baml-client"; import type { FormattedWeather } from "@clairvoyant/baml-client/types"; import { api } from "@convex/_generated/api"; +import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession } from "@mentra/sdk"; +import { updateConversationResponse } from "../core/conversationLogger"; import { checkUserIsPro, convexClient, @@ -30,6 +32,7 @@ async function processWeatherData( displayQueue: DisplayQueueManager, memorySession?: Session, peers?: Peer[], + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { // Fetch memory context if available let memoryContext: { @@ -161,6 +164,16 @@ async function processWeatherData( priority: 2, }); } + + if (logContext && weatherLines.lines.length > 0) { + const responseText = weatherLines.lines.map((l) => `W: ${l}`).join("\n"); + updateConversationResponse( + logContext.convexUserId, + logContext.sessionId, + logContext.transcript, + responseText, + ); + } } export async function startWeatherFlow( @@ -168,6 +181,7 @@ export async function startWeatherFlow( memorySession: Session | undefined, peers: Peer[] | undefined, displayQueue: DisplayQueueManager, + logContext?: { convexUserId: Id<"users">; sessionId: string; transcript: string }, ) { const mentraUserId = session.userId; let preferredUnit: "C" | "F" = "C"; @@ -250,6 +264,7 @@ export async function startWeatherFlow( displayQueue, memorySession, peers, + logContext, ); // TODO: Add a BAML to check if the weather is inclement and if so and if so, ask the user if they're appropriately dressed for the weather. @@ -337,6 +352,7 @@ export async function startWeatherFlow( displayQueue, memorySession, peers, + logContext, ); } catch (err) { session.logger.error( diff --git a/apps/application/src/transcriptionFlow.ts b/apps/application/src/transcriptionFlow.ts index 16ba2de..d3736a1 100644 --- a/apps/application/src/transcriptionFlow.ts +++ b/apps/application/src/transcriptionFlow.ts @@ -3,6 +3,7 @@ import type { Id } from "@convex/_generated/dataModel"; import type { Peer, Session } from "@honcho-ai/sdk"; import type { AppSession, TranscriptionData } from "@mentra/sdk"; import { recordToolInvocation } from "./core/convex"; +import { logConversation } from "./core/conversationLogger"; import type { DisplayQueueManager } from "./core/displayQueue"; import { tryPassthroughHint } from "./handlers/hints"; import { startKnowledgeFlow } from "./handlers/knowledge"; @@ -31,11 +32,17 @@ export async function handleTranscription( session.logger.warn(`[Clairvoyant] No routing decision made. Resetting...`); return; } + + // Log conversation for ML training (fire-and-forget) + logConversation(convexUserId, sessionId, data.text, routing.routing); + + const logContext = { convexUserId, sessionId, transcript: data.text }; + switch (routing.routing) { case Router.WEATHER: session.logger.info(`[Clairvoyant] Weather route: starting async flow`); void recordToolInvocation(mentraUserId, Router.WEATHER); - void startWeatherFlow(session, memorySession, peers, displayQueue); + void startWeatherFlow(session, memorySession, peers, displayQueue, logContext); return; case Router.MAPS: @@ -48,6 +55,7 @@ export async function handleTranscription( peers, mentraUserId, displayQueue, + logContext, ); return; @@ -63,6 +71,7 @@ export async function handleTranscription( peers, mentraUserId, displayQueue, + logContext, ); return; @@ -76,6 +85,7 @@ export async function handleTranscription( peers, mentraUserId, displayQueue, + logContext, ); return; @@ -99,7 +109,7 @@ export async function handleTranscription( `[Clairvoyant] Memory Recall route: starting async flow`, ); void recordToolInvocation(mentraUserId, Router.MEMORY_RECALL); - void MemoryRecall(data.text, session, memorySession, peers, mentraUserId, displayQueue); + void MemoryRecall(data.text, session, memorySession, peers, mentraUserId, displayQueue, logContext); return; case Router.PASSTHROUGH: @@ -113,6 +123,7 @@ export async function handleTranscription( peers, mentraUserId, displayQueue, + logContext, ); return; diff --git a/apps/web/package.json b/apps/web/package.json index e301df1..801957f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,8 +14,8 @@ "dependencies": { "@clairvoyant/api": "workspace:*", "@convex-dev/polar": "^0.6.4", - "@elysiajs/eden": "^1.4.5", - "@mentra/react": "^2.0.2", + "@elysiajs/eden": "^1.4.8", + "@mentra/react": "^2.1.2", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-scroll-area": "^1.2.10", @@ -24,32 +24,33 @@ "@radix-ui/react-switch": "^1.2.6", "@t3-oss/env-core": "^0.13.10", "@types/mapbox-gl": "^3.4.1", + "@vercel/analytics": "^1.6.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "convex": "^1.31.2", + "convex": "^1.32.0", "date-fns": "^4.1.0", - "framer-motion": "^12.23.26", + "framer-motion": "^12.34.3", "lucide-react": "^0.553.0", - "mapbox-gl": "^3.17.0", - "motion": "^12.23.26", - "react": "^19.2.3", - "react-day-picker": "^9.13.0", - "react-dom": "^19.2.3", + "mapbox-gl": "^3.19.0", + "motion": "^12.34.3", + "react": "^19.2.4", + "react-day-picker": "^9.14.0", + "react-dom": "^19.2.4", "react-map-gl": "^8.1.0", - "react-router-dom": "^7.11.0", - "recharts": "^3.6.0", - "tailwind-merge": "^3.4.0", + "react-router-dom": "^7.13.1", + "recharts": "^3.7.0", + "tailwind-merge": "^3.5.0", "zod": "^3.25.76" }, "devDependencies": { - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24.10.4", - "@types/react": "^19.2.3", + "@tailwindcss/vite": "^4.2.1", + "@types/node": "^24.10.15", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.7.0", - "autoprefixer": "^10.4.23", + "autoprefixer": "^10.4.27", "postcss": "^8.5.6", - "tailwindcss": "^4.1.18", + "tailwindcss": "^4.2.1", "tailwindcss-animate": "^1.0.7", "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", diff --git a/apps/web/src/components/ChatPage.tsx b/apps/web/src/components/ChatPage.tsx index a7c26b3..0c35831 100644 --- a/apps/web/src/components/ChatPage.tsx +++ b/apps/web/src/components/ChatPage.tsx @@ -76,7 +76,7 @@ export function ChatPage({ mentraUserId }: ChatPageProps) { useEffect(() => { if (existingMessages && pendingMessages.length > 0) { const existingContents = new Set( - existingMessages.map((m) => `${m.role}:${m.content}`), + existingMessages.map((m: Message) => `${m.role}:${m.content}`), ); const remaining = pendingMessages.filter( (m) => !existingContents.has(`${m.role}:${m.content}`), diff --git a/apps/web/src/components/FollowupChatPage.tsx b/apps/web/src/components/FollowupChatPage.tsx index 1e94f6b..907f07a 100644 --- a/apps/web/src/components/FollowupChatPage.tsx +++ b/apps/web/src/components/FollowupChatPage.tsx @@ -46,7 +46,7 @@ export function FollowupChatPage({ mentraUserId }: FollowupChatPageProps) { useEffect(() => { if (existingMessages && pendingMessages.length > 0) { const existingContents = new Set( - existingMessages.map((m) => `${m.role}:${m.content}`), + existingMessages.map((m: Message) => `${m.role}:${m.content}`), ); const remaining = pendingMessages.filter( (m) => !existingContents.has(`${m.role}:${m.content}`), diff --git a/apps/web/src/components/FollowupsPage.tsx b/apps/web/src/components/FollowupsPage.tsx index b7d5ca1..de0d410 100644 --- a/apps/web/src/components/FollowupsPage.tsx +++ b/apps/web/src/components/FollowupsPage.tsx @@ -125,52 +125,60 @@ export function FollowupsPage({ userId }: FollowupsPageProps) {

Follow-ups

- {followups.map((followup) => ( - { - if (followup.status === "pending") { - navigate(`/followups/chat/${followup._id}`); - } - }} - > - -
- {followup.topic} - -
-
- -

{followup.summary}

+ {followups.map( + (followup: { + _id: Id<"followups">; + topic: string; + summary: string; + status: "pending" | "completed" | "dismissed"; + createdAt: string; + }) => ( + { + if (followup.status === "pending") { + navigate(`/followups/chat/${followup._id}`); + } + }} + > + +
+ {followup.topic} + +
+
+ +

{followup.summary}

-
-

- {formatRelativeTime(followup.createdAt)} -

+
+

+ {formatRelativeTime(followup.createdAt)} +

- {followup.status === "pending" && ( -
- - -
- )} -
- - - ))} + {followup.status === "pending" && ( +
+ + +
+ )} +
+
+
+ ), + )}
); diff --git a/apps/web/src/components/MemoryPage.tsx b/apps/web/src/components/MemoryPage.tsx index ee46e84..55b0203 100644 --- a/apps/web/src/components/MemoryPage.tsx +++ b/apps/web/src/components/MemoryPage.tsx @@ -82,40 +82,47 @@ export function MemoryPage({ mentraUserId }: MemoryPageProps) {

Memory

- {result.summaries.map((day) => ( - navigate(`/memory/chat/${day.date}`)} - > - - - 📅 - {formatDate(day.date)} - - - -

{day.summary}

+ {result.summaries.map( + (day: { + date: string; + summary: string; + topics: string[]; + sessionCount: number; + }) => ( + navigate(`/memory/chat/${day.date}`)} + > + + + 📅 + {formatDate(day.date)} + + + +

{day.summary}

- {day.topics.length > 0 && ( -
- {day.topics.map((topic) => ( - - {topic} - - ))} -
- )} + {day.topics.length > 0 && ( +
+ {day.topics.map((topic: string) => ( + + {topic} + + ))} +
+ )} -

- {day.sessionCount} session{day.sessionCount > 1 ? "s" : ""} -

-
-
- ))} +

+ {day.sessionCount} session{day.sessionCount > 1 ? "s" : ""} +

+
+
+ ), + )}
); diff --git a/apps/web/src/components/QueuePage.tsx b/apps/web/src/components/QueuePage.tsx index 756b356..93e67f4 100644 --- a/apps/web/src/components/QueuePage.tsx +++ b/apps/web/src/components/QueuePage.tsx @@ -9,7 +9,10 @@ interface QueuePageProps { userId: Id<"users">; } -const PREFIX_COLORS: Record = { +const PREFIX_COLORS: Record< + string, + { bg: string; text: string; label: string } +> = { W: { bg: "bg-blue-100", text: "text-blue-700", label: "Weather" }, M: { bg: "bg-purple-100", text: "text-purple-700", label: "Memory" }, S: { bg: "bg-green-100", text: "text-green-700", label: "Search" }, @@ -51,9 +54,19 @@ interface MessageCardProps { displayedAt?: string; } -function MessageCard({ message, prefix, status, createdAt, displayedAt }: MessageCardProps) { - const prefixStyle = PREFIX_COLORS[prefix] || { bg: "bg-gray-100", text: "text-gray-700", label: prefix }; - +function MessageCard({ + message, + prefix, + status, + createdAt, + displayedAt, +}: MessageCardProps) { + const prefixStyle = PREFIX_COLORS[prefix] || { + bg: "bg-gray-100", + text: "text-gray-700", + label: prefix, + }; + const statusStyles = { queued: "border-yellow-300 bg-yellow-50", displayed: "border-border", @@ -63,11 +76,15 @@ function MessageCard({ message, prefix, status, createdAt, displayedAt }: Messag const cleanMessage = message.replace(/^\/\/ Clairvoyant\n[A-Z]: /, ""); return ( -
+
- + {prefixStyle.label} {status === "queued" && ( @@ -84,7 +101,9 @@ function MessageCard({ message, prefix, status, createdAt, displayedAt }: Messag

{cleanMessage}

- {displayedAt ? formatRelativeTime(displayedAt) : formatRelativeTime(createdAt)} + {displayedAt + ? formatRelativeTime(displayedAt) + : formatRelativeTime(createdAt)}
@@ -115,8 +134,12 @@ export function QueuePage({ userId }: QueuePageProps) { ); } - const queuedMessages = messages.filter((m) => m.status === "queued").slice(0, MAX_VISIBLE); - const recentMessages = messages.filter((m) => m.status !== "queued").slice(0, MAX_VISIBLE); + const queuedMessages = messages + .filter((m: { status: string }) => m.status === "queued") + .slice(0, MAX_VISIBLE); + const recentMessages = messages + .filter((m: { status: string }) => m.status !== "queued") + .slice(0, MAX_VISIBLE); return (
@@ -144,16 +167,25 @@ export function QueuePage({ userId }: QueuePageProps) {

No messages in queue

) : (
- {queuedMessages.map((msg) => ( - - ))} + {queuedMessages.map( + (msg: { + _id: string; + message: string; + prefix: string; + status: string; + createdAt: string; + displayedAt?: string; + }) => ( + + ), + )}
)} @@ -168,16 +200,25 @@ export function QueuePage({ userId }: QueuePageProps) {

No recent messages

) : (
- {recentMessages.map((msg) => ( - - ))} + {recentMessages.map( + (msg: { + _id: string; + message: string; + prefix: string; + status: string; + createdAt: string; + displayedAt?: string; + }) => ( + + ), + )}
)} diff --git a/apps/web/src/components/SettingsPage.tsx b/apps/web/src/components/SettingsPage.tsx index 7bbf33b..c76a5be 100644 --- a/apps/web/src/components/SettingsPage.tsx +++ b/apps/web/src/components/SettingsPage.tsx @@ -1,6 +1,6 @@ import { api } from "@convex/_generated/api"; import type { Id } from "@convex/_generated/dataModel"; -import { useMutation, useQuery } from "convex/react"; +import { useAction, useMutation, useQuery } from "convex/react"; import { useEffect, useMemo, useState } from "react"; import { LocationSelector } from "./LocationSelector"; import { MessageSpeedSelector } from "./MessageSpeedSelector"; @@ -33,18 +33,27 @@ export function SettingsPage({ userId, mentraUserId }: SettingsPageProps) { const updatePreferences = useMutation(api.users.updatePreferences); const updatePrefixPriorities = useMutation(api.users.updatePrefixPriorities); const updateMessageGapSpeed = useMutation(api.users.updateMessageGapSpeed); - + const requestOptOutCheckoutEmail = useAction( + api.optOut.requestOptOutCheckoutEmail, + ); const storedEmail = useQuery( api.users.getEmail, mentraUserId ? { mentraUserId } : "skip", ); + const optOutStatus = useQuery( + api.users.getOptOutStatus, + mentraUserId ? { mentraUserId } : "skip", + ); const updateEmail = useMutation(api.users.updateEmail); const [emailInput, setEmailInput] = useState(""); const [emailStatus, setEmailStatus] = useState< "idle" | "saving" | "saved" | "error" >("idle"); const [emailError, setEmailError] = useState(null); - + const [optOutRequestStatus, setOptOutRequestStatus] = useState< + "idle" | "sending" | "sent" | "error" + >("idle"); + const [optOutError, setOptOutError] = useState(null); useEffect(() => { if (storedEmail !== undefined && storedEmail !== null) { setEmailInput(storedEmail); @@ -97,6 +106,26 @@ export function SettingsPage({ userId, mentraUserId }: SettingsPageProps) { console.log(`Preference saved: messageGapSpeed=${speed}`); }; + const handleRequestOptOut = async () => { + if (!mentraUserId) return; + + setOptOutRequestStatus("sending"); + setOptOutError(null); + try { + const result = await requestOptOutCheckoutEmail({ mentraUserId }); + if (!result.success) { + setOptOutError("Unable to send opt-out email."); + setOptOutRequestStatus("error"); + return; + } + setOptOutRequestStatus("sent"); + setTimeout(() => setOptOutRequestStatus("idle"), 2500); + } catch { + setOptOutError("Unable to send opt-out email."); + setOptOutRequestStatus("error"); + } + }; + const hasPreferencesLoaded = preferences !== undefined; const weatherUnit = useMemo(() => { if (!preferences) { @@ -200,6 +229,39 @@ export function SettingsPage({ userId, mentraUserId }: SettingsPageProps) { + + + Training Data + + Control whether your data is used for model training. + + + +

+ Status:{" "} + {optOutStatus?.optedOut ? "Opted out" : "Included in training"} +

+ {!optOutStatus?.optedOut && ( + + )} + {optOutRequestStatus === "sent" && ( +

+ Email sent with instructions. +

+ )} + {optOutError && ( +

{optOutError}

+ )} +
+
+ Weather Unit diff --git a/apps/web/src/components/charts/ToolUsageChart.tsx b/apps/web/src/components/charts/ToolUsageChart.tsx index 15c3b53..3471afc 100644 --- a/apps/web/src/components/charts/ToolUsageChart.tsx +++ b/apps/web/src/components/charts/ToolUsageChart.tsx @@ -79,6 +79,8 @@ export function ToolUsageChart({ days: timeframe, }); + type ToolInvocation = { date: string; router: string; count: number }; + const chartMemo = useMemo(() => { if (!toolInvocations || !toolInvocations.length) { return { @@ -90,7 +92,7 @@ export function ToolUsageChart({ } // Filter out KNOWLEDGE entries - const filteredInvocations = toolInvocations.filter( + const filteredInvocations = (toolInvocations as ToolInvocation[]).filter( ({ router }) => router !== "KNOWLEDGE", ); @@ -226,12 +228,15 @@ export function ToolUsageChart({ /> - new Date(`${value}T00:00:00Z`).toLocaleDateString(undefined, { - weekday: "short", - month: "short", - day: "numeric", - }) + labelFormatter={(value) => + new Date(`${String(value)}T00:00:00Z`).toLocaleDateString( + undefined, + { + weekday: "short", + month: "short", + day: "numeric", + }, + ) } formatter={(value, name) => [ Number(value).toLocaleString(), diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx index 696f4cd..d576784 100644 --- a/apps/web/src/main.tsx +++ b/apps/web/src/main.tsx @@ -1,7 +1,9 @@ import "./index.css"; import { MentraAuthProvider } from "@mentra/react"; +import { Analytics } from "@vercel/analytics/react"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; + import { App } from "./App"; const rootElement = document.getElementById("root"); @@ -13,6 +15,7 @@ createRoot(rootElement).render( + , ); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 1c055cc..c7200d7 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -19,6 +19,7 @@ "noEmit": true, "strict": true, "skipLibCheck": true, + "types": ["node"], "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, "noImplicitOverride": true, diff --git a/bun.lock b/bun.lock index 6a2bda0..fe23769 100644 --- a/bun.lock +++ b/bun.lock @@ -4,16 +4,18 @@ "": { "name": "clairvoyant", "dependencies": { - "convex": "^1.31.2", - "elysia": "^1.4.19", + "convex": "^1.32.0", + "elysia": "^1.4.26", }, "devDependencies": { "@biomejs/biome": "2.1.2", "@boundaryml/baml": "0.215.0", "@types/bun": "latest", - "@types/node": "^24.10.4", + "@types/node": "^24.10.15", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "tsx": "^4.21.0", - "turbo": "^2.7.0", + "turbo": "^2.8.11", "typescript": "^5.9.3", }, }, @@ -21,9 +23,9 @@ "name": "@clairvoyant/api", "version": "0.1.0", "dependencies": { - "@elysiajs/cors": "^1.4.0", + "@elysiajs/cors": "^1.4.1", "@t3-oss/env-core": "^0.13.10", - "convex": "^1.31.2", + "convex": "^1.32.0", "jose": "^6.1.3", "jsonwebtoken": "^9.0.3", "zod": "^3.25.76", @@ -41,10 +43,10 @@ "@boundaryml/baml": "0.215.0", "@clairvoyant/baml-client": "workspace:*", "@honcho-ai/sdk": "^1.6.0", - "@mentra/sdk": "^2.1.28", + "@mentra/sdk": "^2.1.29", "@t3-oss/env-core": "^0.13.10", "@tavily/core": "^0.5.14", - "convex": "^1.31.2", + "convex": "^1.32.0", "exa-js": "^1.10.2", "openai": "^5.23.2", "zod": "^3.25.76", @@ -61,8 +63,8 @@ "dependencies": { "@clairvoyant/api": "workspace:*", "@convex-dev/polar": "^0.6.4", - "@elysiajs/eden": "^1.4.5", - "@mentra/react": "^2.0.2", + "@elysiajs/eden": "^1.4.8", + "@mentra/react": "^2.1.2", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-scroll-area": "^1.2.10", @@ -71,32 +73,33 @@ "@radix-ui/react-switch": "^1.2.6", "@t3-oss/env-core": "^0.13.10", "@types/mapbox-gl": "^3.4.1", + "@vercel/analytics": "^1.6.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "convex": "^1.31.2", + "convex": "^1.32.0", "date-fns": "^4.1.0", - "framer-motion": "^12.23.26", + "framer-motion": "^12.34.3", "lucide-react": "^0.553.0", - "mapbox-gl": "^3.17.0", - "motion": "^12.23.26", - "react": "^19.2.3", - "react-day-picker": "^9.13.0", - "react-dom": "^19.2.3", + "mapbox-gl": "^3.19.0", + "motion": "^12.34.3", + "react": "^19.2.4", + "react-day-picker": "^9.14.0", + "react-dom": "^19.2.4", "react-map-gl": "^8.1.0", - "react-router-dom": "^7.11.0", - "recharts": "^3.6.0", - "tailwind-merge": "^3.4.0", + "react-router-dom": "^7.13.1", + "recharts": "^3.7.0", + "tailwind-merge": "^3.5.0", "zod": "^3.25.76", }, "devDependencies": { - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24.10.4", - "@types/react": "^19.2.3", + "@tailwindcss/vite": "^4.2.1", + "@types/node": "^24.10.15", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.7.0", - "autoprefixer": "^10.4.23", + "autoprefixer": "^10.4.27", "postcss": "^8.5.6", - "tailwindcss": "^4.1.18", + "tailwindcss": "^4.2.1", "tailwindcss-animate": "^1.0.7", "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", @@ -121,18 +124,18 @@ "@convex-dev/resend": "^0.2.3", "@honcho-ai/sdk": "^1.6.0", "@polar-sh/sdk": "^0.41.5", - "@react-email/components": "^1.0.2", - "@react-email/render": "^2.0.0", - "convex": "^1.31.2", + "@react-email/components": "^1.0.8", + "@react-email/render": "^2.0.4", + "convex": "^1.32.0", "groq-sdk": "^0.18.0", - "react": "^19.2.3", - "react-dom": "^19.2.3", - "react-email": "^5.1.0", - "svix": "^1.82.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-email": "^5.2.8", + "svix": "^1.86.0", "zod": "^3.25.76", }, "devDependencies": { - "@types/react": "^19.2.3", + "@types/react": "^19.2.14", }, }, "packages/ngrok": { @@ -145,7 +148,8 @@ }, }, "overrides": { - "elysia": "^1.4.19", + "elysia": "^1.4.26", + "esbuild": "0.25.12", }, "packages": { "@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="], @@ -248,59 +252,59 @@ "@elysiajs/cors": ["@elysiajs/cors@1.4.1", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-lQfad+F3r4mNwsxRKbXyJB8Jg43oAOXjRwn7sKUL6bcOW3KjUqUimTS+woNpO97efpzjtDE0tEjGk9DTw8lqTQ=="], - "@elysiajs/eden": ["@elysiajs/eden@1.4.6", "", { "peerDependencies": { "elysia": ">=1.4.19" } }, "sha512-Tsa4NwXEWg/u73vWiYZQ3L5/ecgZSxqiEjYwpS+4qBKXeTZqZKl2hcgHJSVBL+InEDMi35Xugct7qyAXE5oM4Q=="], + "@elysiajs/eden": ["@elysiajs/eden@1.4.8", "", { "peerDependencies": { "elysia": ">=1.4.19" } }, "sha512-a7oct2kFa49tH+GawZtSUCZR2rQgucNYgGLz8alXUqb4IrU3PASA0T4zXJw4MhdV1Xb6vyiR7p7kkqJcVjgbkA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], @@ -408,8 +412,6 @@ "@mapbox/vector-tile": ["@mapbox/vector-tile@2.0.4", "", { "dependencies": { "@mapbox/point-geometry": "~1.1.0", "@types/geojson": "^7946.0.16", "pbf": "^4.0.1" } }, "sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg=="], - "@mapbox/whoots-js": ["@mapbox/whoots-js@3.1.0", "", {}, "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q=="], - "@maplibre/maplibre-gl-style-spec": ["@maplibre/maplibre-gl-style-spec@19.3.3", "", { "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", "@mapbox/unitbezier": "^0.0.1", "json-stringify-pretty-compact": "^3.0.0", "minimist": "^1.2.8", "rw": "^1.3.3", "sort-object": "^3.0.3" }, "bin": { "gl-style-format": "dist/gl-style-format.mjs", "gl-style-migrate": "dist/gl-style-migrate.mjs", "gl-style-validate": "dist/gl-style-validate.mjs" } }, "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw=="], "@mentra/react": ["@mentra/react@2.1.2", "", { "peerDependencies": { "react": ">=19.0.0", "react-dom": ">=19.0.0" } }, "sha512-HnZ8bIE4I4L26BnuJ4AZdB48c14X+0PGV/sJJz6VYBXwc9kkoRFh2A2SsOW3PPcj9GMv5O6A/iydPNKF+Wanfg=="], @@ -530,7 +532,7 @@ "@react-email/column": ["@react-email/column@0.0.14", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-f+W+Bk2AjNO77zynE33rHuQhyqVICx4RYtGX9NKsGUg0wWjdGP0qAuIkhx9Rnmk4/hFMo1fUrtYNqca9fwJdHg=="], - "@react-email/components": ["@react-email/components@1.0.4", "", { "dependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/column": "0.0.14", "@react-email/container": "0.0.16", "@react-email/font": "0.0.10", "@react-email/head": "0.0.13", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/html": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/markdown": "0.0.18", "@react-email/preview": "0.0.14", "@react-email/render": "2.0.2", "@react-email/row": "0.0.13", "@react-email/section": "0.0.17", "@react-email/tailwind": "2.0.3", "@react-email/text": "0.1.6" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-XpSs/mN0APMD9E3TYZnj8N6kRXqb6WBl9WrE+IHyB4PdgLNqXe7uZ5+5oZkKSE8Tskzw/K2vDJUqSZ2v+sRjUA=="], + "@react-email/components": ["@react-email/components@1.0.8", "", { "dependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/column": "0.0.14", "@react-email/container": "0.0.16", "@react-email/font": "0.0.10", "@react-email/head": "0.0.13", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/html": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/markdown": "0.0.18", "@react-email/preview": "0.0.14", "@react-email/render": "2.0.4", "@react-email/row": "0.0.13", "@react-email/section": "0.0.17", "@react-email/tailwind": "2.0.5", "@react-email/text": "0.1.6" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-zY81ED6o5MWMzBkr9uZFuT24lWarT+xIbOZxI6C9dsFmCWBczM8IE1BgOI8rhpUK4JcYVDy1uKxYAFqsx2Bc4w=="], "@react-email/container": ["@react-email/container@0.0.16", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-QWBB56RkkU0AJ9h+qy33gfT5iuZknPC7Un/IjZv9B0QmMIK+WWacc0cH6y2SV5Cv/b99hU94fjEMOOO4enpkbQ=="], @@ -552,13 +554,13 @@ "@react-email/preview": ["@react-email/preview@0.0.14", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aYK8q0IPkBXyMsbpMXgxazwHxYJxTrXrV95GFuu2HbEiIToMwSyUgb8HDFYwPqqfV03/jbwqlsXmFxsOd+VNaw=="], - "@react-email/render": ["@react-email/render@2.0.2", "", { "dependencies": { "html-to-text": "^9.0.5", "prettier": "^3.5.3" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-AGuNo86TP9Y2JBUwFcT+z0frPDML4WLIFlnCi7laCPYJA+43kdim0y+qRNPxRxZkJiUz1JMPnE2M5HaNYhWwIg=="], + "@react-email/render": ["@react-email/render@2.0.4", "", { "dependencies": { "html-to-text": "^9.0.5", "prettier": "^3.5.3" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-kht2oTFQ1SwrLpd882ahTvUtNa9s53CERHstiTbzhm6aR2Hbykp/mQ4tpPvsBGkKAEvKRlDEoooh60Uk6nHK1g=="], "@react-email/row": ["@react-email/row@0.0.13", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-bYnOac40vIKCId7IkwuLAAsa3fKfSfqCvv6epJKmPE0JBuu5qI4FHFCl9o9dVpIIS08s/ub+Y/txoMt0dYziGw=="], "@react-email/section": ["@react-email/section@0.0.17", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-qNl65ye3W0Rd5udhdORzTV9ezjb+GFqQQSae03NDzXtmJq6sqVXNWNiVolAjvJNypim+zGXmv6J9TcV5aNtE/w=="], - "@react-email/tailwind": ["@react-email/tailwind@2.0.3", "", { "dependencies": { "tailwindcss": "^4.1.18" }, "peerDependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/container": "0.0.16", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/preview": "0.0.14", "@react-email/text": "0.1.6", "react": "^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@react-email/body", "@react-email/button", "@react-email/code-block", "@react-email/code-inline", "@react-email/container", "@react-email/heading", "@react-email/hr", "@react-email/img", "@react-email/link", "@react-email/preview"] }, "sha512-URXb/T2WS4RlNGM5QwekYnivuiVUcU87H0y5sqLl6/Oi3bMmgL0Bmw/W9GeJylC+876Vw+E6NkE0uRiUFIQwGg=="], + "@react-email/tailwind": ["@react-email/tailwind@2.0.5", "", { "dependencies": { "tailwindcss": "^4.1.18" }, "peerDependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/container": "0.0.16", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/preview": "0.0.14", "@react-email/text": "0.1.6", "react": "^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@react-email/body", "@react-email/button", "@react-email/code-block", "@react-email/code-inline", "@react-email/container", "@react-email/heading", "@react-email/hr", "@react-email/img", "@react-email/link", "@react-email/preview"] }, "sha512-7Ey+kiWliJdxPMCLYsdDts8ffp4idlP//w4Ui3q/A5kokVaLSNKG8DOg/8qAuzWmRiGwNQVOKBk7PXNlK5W+sg=="], "@react-email/text": ["@react-email/text@0.1.6", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-TYqkioRS45wTR5il3dYk/SbUjjEdhSwh9BtRNB99qNH1pXAwA45H7rAuxehiu8iJQJH0IyIr+6n62gBz9ezmsw=="], @@ -636,35 +638,37 @@ "@t3-oss/env-core": ["@t3-oss/env-core@0.13.10", "", { "peerDependencies": { "arktype": "^2.1.0", "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["arktype", "typescript", "valibot", "zod"] }, "sha512-NNFfdlJ+HmPHkLi2HKy7nwuat9SIYOxei9K10lO2YlcSObDILY7mHZNSHsieIM3A0/5OOzw/P/b+yLvPdaG52g=="], - "@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="], + "@tabby_ai/hijri-converter": ["@tabby_ai/hijri-converter@1.0.5", "", {}, "sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], - "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="], + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], - "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="], + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], - "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="], + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], - "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="], + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], - "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="], + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], - "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="], + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], - "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="], + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], - "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="], + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], - "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="], + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], - "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="], + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], - "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="], + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], - "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="], + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], - "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="], + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], - "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="], + "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="], "@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="], @@ -716,17 +720,17 @@ "@types/mapbox-gl": ["@types/mapbox-gl@3.4.1", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-NsGKKtgW93B+UaLPti6B7NwlxYlES5DpV5Gzj9F75rK5ALKsqSk15CiEHbOnTr09RGbr6ZYiCdI+59NNNcAImg=="], - "@types/mapbox__point-geometry": ["@types/mapbox__point-geometry@0.1.4", "", {}, "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA=="], + "@types/mapbox__point-geometry": ["@types/mapbox__point-geometry@1.0.87", "", { "dependencies": { "@mapbox/point-geometry": "*" } }, "sha512-32whuSWD/aDBHpRrZmEMlRjxR0L3sSYUaRnVmw0XwyVMvuU5LsRqrFwYud7gXjqmUE0MSoJB91+IJMqCyYyxag=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + "@types/node": ["@types/node@24.10.15", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-BgjLoRuSr0MTI5wA6gMw9Xy0sFudAaUuvrnjgGx9wZ522fYYLA5SYJ+1Y30vTcJEG+DRCyDHx/gzQVfofYzSdg=="], "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], "@types/pbf": ["@types/pbf@3.0.5", "", {}, "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA=="], - "@types/react": ["@types/react@19.2.8", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg=="], + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], @@ -736,6 +740,8 @@ "@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="], + "@vercel/analytics": ["@vercel/analytics@1.6.1", "", { "peerDependencies": { "@remix-run/react": "^2", "@sveltejs/kit": "^1 || ^2", "next": ">= 13", "react": "^18 || ^19 || ^19.0.0-rc", "svelte": ">= 4", "vue": "^3", "vue-router": "^4" }, "optionalPeers": ["@remix-run/react", "@sveltejs/kit", "next", "react", "svelte", "vue", "vue-router"] }, "sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg=="], + "@vis.gl/react-mapbox": ["@vis.gl/react-mapbox@8.1.0", "", { "peerDependencies": { "mapbox-gl": ">=3.5.0", "react": ">=16.3.0", "react-dom": ">=16.3.0" }, "optionalPeers": ["mapbox-gl"] }, "sha512-FwvH822oxEjWYOr+pP2L8hpv+7cZB2UsQbHHHT0ryrkvvqzmTgt7qHDhamv0EobKw86e1I+B4ojENdJ5G5BkyQ=="], "@vis.gl/react-maplibre": ["@vis.gl/react-maplibre@8.1.0", "", { "dependencies": { "@maplibre/maplibre-gl-style-spec": "^19.2.1" }, "peerDependencies": { "maplibre-gl": ">=4.0.0", "react": ">=16.3.0", "react-dom": ">=16.3.0" }, "optionalPeers": ["maplibre-gl"] }, "sha512-PkAK/gp3mUfhCLhUuc+4gc3PN9zCtVGxTF2hB6R5R5yYUw+hdg84OZ770U5MU4tPMTCG6fbduExuIW6RRKN6qQ=="], @@ -756,6 +762,8 @@ "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], + "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -778,7 +786,7 @@ "atomically": ["atomically@2.1.0", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-+gDffFXRW6sl/HCwbta7zK4uNqbPjv4YJEAdz7Vu+FLQHe77eZ4bvbJGi4hE0QPeJlMYMA3piXEr1UL3dAwx7Q=="], - "autoprefixer": ["autoprefixer@10.4.23", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA=="], + "autoprefixer": ["autoprefixer@10.4.27", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA=="], "await-to-js": ["await-to-js@3.0.0", "", {}, "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g=="], @@ -800,6 +808,8 @@ "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], @@ -824,7 +834,7 @@ "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001765", "", {}, "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001774", "", {}, "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -842,6 +852,8 @@ "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="], @@ -854,7 +866,7 @@ "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], - "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], + "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], "concat-stream": ["concat-stream@2.0.0", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A=="], @@ -870,7 +882,7 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - "convex": ["convex@1.31.5", "", { "dependencies": { "esbuild": "0.27.0", "prettier": "^3.0.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-E1IuJKFwMCHDToNGukBPs6c7RFaarR3t8chLF9n98TM5/Tgmj8lM6l7sKM1aJ3VwqGaB4wbeUAPY8osbCOXBhQ=="], + "convex": ["convex@1.32.0", "", { "dependencies": { "esbuild": "0.27.0", "prettier": "^3.0.0", "ws": "8.18.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-5FlajdLpW75pdLS+/CgGH5H6yeRuA+ru50AKJEYbJpmyILUS+7fdTvsdTaQ7ZFXMv0gE8mX4S+S3AtJ94k0mfw=="], "convex-helpers": ["convex-helpers@0.1.111", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "convex": "^1.25.4", "hono": "^4.0.5", "react": "^17.0.2 || ^18.0.0 || ^19.0.0", "typescript": "^5.5", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@standard-schema/spec", "hono", "react", "typescript", "zod"], "bin": { "convex-helpers": "bin.cjs" } }, "sha512-0O59Ohi8HVc3+KULxSC6JHsw8cQJyc8gZ7OAfNRVX7T5Wy6LhPx3l8veYN9avKg7UiPlO7m1eBiQMHKclIyXyQ=="], @@ -968,7 +980,7 @@ "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="], - "elysia": ["elysia@1.4.22", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.6", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-Q90VCb1RVFxnFaRV0FDoSylESQQLWgLHFmWciQJdX9h3b2cSasji9KWEUvaJuy/L9ciAGg4RAhUVfsXHg5K2RQ=="], + "elysia": ["elysia@1.4.26", "", { "dependencies": { "cookie": "^1.1.1", "exact-mirror": "^0.2.7", "fast-decode-uri-component": "^1.0.1", "memoirist": "^0.4.0" }, "peerDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "@types/bun": ">= 1.2.0", "file-type": ">= 20.0.0", "openapi-types": ">= 12.0.0", "typescript": ">= 5.0.0" }, "optionalPeers": ["@types/bun", "typescript"] }, "sha512-oGhEFYwt+4M/U9w34XTdBen2KOQIa/PXne40zUkTWRgJlVJNBhepxOdjWeY1U0CbYoEOyZaj1tc79wOsuCxMYw=="], "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], @@ -980,12 +992,14 @@ "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], - "enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="], + "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="], "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], @@ -996,7 +1010,7 @@ "es-toolkit": ["es-toolkit@1.44.0", "", {}, "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg=="], - "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -1014,7 +1028,7 @@ "exa-js": ["exa-js@1.10.2", "", { "dependencies": { "cross-fetch": "~4.1.0", "dotenv": "~16.4.7", "openai": "^5.0.1", "zod": "^3.22.0", "zod-to-json-schema": "^3.20.0" } }, "sha512-nObBipoXKL5uL6Dc8Q3c9GA4xEfunQMdGGqtcCkQSNilzR6AExyVkBxTdpWqC20jKa3/dvXu6otXQLaRyZNqGw=="], - "exact-mirror": ["exact-mirror@0.2.6", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA=="], + "exact-mirror": ["exact-mirror@0.2.7", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-+MeEmDcLA4o/vjK2zujgk+1VTxPR4hdp23qLqkWfStbECtAq9gmsvQa3LW6z/0GXZyHJobrCnmy1cdeE7BjsYg=="], "exif-parser": ["exif-parser@0.1.12", "", {}, "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="], @@ -1040,6 +1054,8 @@ "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], @@ -1056,7 +1072,7 @@ "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], - "framer-motion": ["framer-motion@12.27.0", "", { "dependencies": { "motion-dom": "^12.27.0", "motion-utils": "^12.24.10", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-gJtqOKEDJH/jrn0PpsWp64gdOjBvGX8hY6TWstxjDot/85daIEtJHl1UsiwHSXiYmJF2QXUoXP6/3gGw5xY2YA=="], + "framer-motion": ["framer-motion@12.34.3", "", { "dependencies": { "motion-dom": "^12.34.3", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-v81ecyZKYO/DfpTwHivqkxSUBzvceOpoI+wLfgCgoUIKxlFKEXdg0oR9imxwXumT4SFy8vRk9xzJ5l3/Du/55Q=="], "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], @@ -1112,6 +1128,8 @@ "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -1130,10 +1148,12 @@ "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="], "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], @@ -1206,6 +1226,10 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + "lint-staged": ["lint-staged@16.2.7", "", { "dependencies": { "commander": "^14.0.2", "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow=="], + + "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="], + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], @@ -1222,6 +1246,8 @@ "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], + "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], @@ -1232,7 +1258,7 @@ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - "mapbox-gl": ["mapbox-gl@3.18.0", "", { "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^3.0.0", "@mapbox/point-geometry": "^1.1.0", "@mapbox/tiny-sdf": "^2.0.6", "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^2.0.4", "@mapbox/whoots-js": "^3.1.0", "@types/geojson": "^7946.0.16", "@types/geojson-vt": "^3.2.5", "@types/mapbox__point-geometry": "^0.1.4", "@types/pbf": "^3.0.5", "@types/supercluster": "^7.1.3", "cheap-ruler": "^4.0.0", "csscolorparser": "~1.0.3", "earcut": "^3.0.1", "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.4", "grid-index": "^1.1.0", "kdbush": "^4.0.2", "martinez-polygon-clipping": "^0.8.1", "murmurhash-js": "^1.0.0", "pbf": "^4.0.1", "potpack": "^2.0.0", "quickselect": "^3.0.0", "supercluster": "^8.0.1", "tinyqueue": "^3.0.0" } }, "sha512-xMr9HUoof0qPqWrVNK+kLiPtU1ogyfR6cihGSTB4eQAzdfFuMTC7CPrbpbZK0oUKQxXI/1qvB35FXZIK7kfR9w=="], + "mapbox-gl": ["mapbox-gl@3.19.0", "", { "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^3.0.0", "@mapbox/point-geometry": "^1.1.0", "@mapbox/tiny-sdf": "^2.0.6", "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^2.0.4", "@types/geojson": "^7946.0.16", "@types/geojson-vt": "^3.2.5", "@types/mapbox__point-geometry": "^1.0.87", "@types/pbf": "^3.0.5", "@types/supercluster": "^7.1.3", "cheap-ruler": "^4.0.0", "csscolorparser": "~1.0.3", "earcut": "^3.0.1", "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.4", "grid-index": "^1.1.0", "kdbush": "^4.0.2", "martinez-polygon-clipping": "^0.8.1", "murmurhash-js": "^1.0.0", "pbf": "^4.0.1", "potpack": "^2.0.0", "quickselect": "^3.0.0", "supercluster": "^8.0.1", "tinyqueue": "^3.0.0" } }, "sha512-SFObIgdxN0b6hZNsRxSUmQWdVW9q9GM2gw4McgFbycyhekew7BZIh8V57pEERDWlI9x/5SxxraTit5Cf0hm9OA=="], "markdown-to-jsx": ["markdown-to-jsx@7.7.17", "", { "peerDependencies": { "react": ">= 0.14.0" }, "optionalPeers": ["react"] }, "sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ=="], @@ -1250,6 +1276,8 @@ "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], @@ -1266,11 +1294,11 @@ "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], - "motion": ["motion@12.27.0", "", { "dependencies": { "framer-motion": "^12.27.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-5/WbUMUV0QPOlgimOKJRhKwE+/pIHBI38SVgEpsfadOa5lYDgkgJAEav7KqNahdX3i3xkvogD5JR4K41w+9Hzw=="], + "motion": ["motion@12.34.3", "", { "dependencies": { "framer-motion": "^12.34.3", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-xZIkBGO7v/Uvm+EyaqYd+9IpXu0sZqLywVlGdCFrrMiaO9JI4Kx51mO9KlHSWwll+gZUVY5OJsWgYI5FywJ/tw=="], - "motion-dom": ["motion-dom@12.27.0", "", { "dependencies": { "motion-utils": "^12.24.10" } }, "sha512-oDjl0WoAsWIWKl3GCDxmh7GITrNjmLX+w5+jwk4+pzLu3VnFvsOv2E6+xCXeH72O65xlXsr84/otiOYQKW/nQA=="], + "motion-dom": ["motion-dom@12.34.3", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ=="], - "motion-utils": ["motion-utils@12.24.10", "", {}, "sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww=="], + "motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -1278,6 +1306,8 @@ "murmurhash-js": ["murmurhash-js@1.0.0", "", {}, "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="], + "nano-spawn": ["nano-spawn@2.0.0", "", {}, "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], @@ -1348,6 +1378,8 @@ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + "pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], + "pino": ["pino@9.14.0", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w=="], "pino-abstract-transport": ["pino-abstract-transport@1.2.0", "", { "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q=="], @@ -1400,13 +1432,13 @@ "raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], - "react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="], + "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], - "react-day-picker": ["react-day-picker@9.13.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0", "date-fns-jalali": "^4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ=="], + "react-day-picker": ["react-day-picker@9.14.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "@tabby_ai/hijri-converter": "1.0.5", "date-fns": "^4.1.0", "date-fns-jalali": "4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA=="], - "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], + "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], - "react-email": ["react-email@5.2.5", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "conf": "^15.0.2", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.2", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-YaCp5n/0czviN4lFndsYongiI0IJOMFtFoRVIPJc9+WPJejJEvzJO94r31p3Cz9swDuV0RhEhH1W0lJFAXntHA=="], + "react-email": ["react-email@5.2.8", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "conf": "^15.0.2", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.2", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-noPcnpl78vsyBnhiKCzxK9Mdsv7ncAYI80osS5kbMgaKH2IgPtPab5BzLJX6INXuiNk5ju+9YRnCjPoPTOHZjA=="], "react-hook-form": ["react-hook-form@7.71.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w=="], @@ -1422,9 +1454,9 @@ "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], - "react-router": ["react-router@7.12.0", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw=="], + "react-router": ["react-router@7.13.1", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA=="], - "react-router-dom": ["react-router-dom@7.12.0", "", { "dependencies": { "react-router": "7.12.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-pfO9fiBcpEfX4Tx+iTYKDtPbrSLLCbwJ5EqP+SPYQu1VYCXdy79GSj0wttR0U4cikVdlImZuEZ/9ZNCgoaxwBA=="], + "react-router-dom": ["react-router-dom@7.13.1", "", { "dependencies": { "react-router": "7.13.1" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw=="], "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], @@ -1438,7 +1470,7 @@ "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], - "recharts": ["recharts@3.6.0", "", { "dependencies": { "@reduxjs/toolkit": "1.x.x || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-L5bjxvQRAe26RlToBAziKUB7whaGKEwD3znoM6fz3DrTowCIC/FnJYnuq1GEzB8Zv2kdTfaxQfi5GoH0tBinyg=="], + "recharts": ["recharts@3.7.0", "", { "dependencies": { "@reduxjs/toolkit": "1.x.x || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew=="], "redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="], @@ -1458,6 +1490,8 @@ "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + "robust-predicates": ["robust-predicates@2.0.4", "", {}, "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg=="], "rollup": ["rollup@4.55.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.55.1", "@rollup/rollup-android-arm64": "4.55.1", "@rollup/rollup-darwin-arm64": "4.55.1", "@rollup/rollup-darwin-x64": "4.55.1", "@rollup/rollup-freebsd-arm64": "4.55.1", "@rollup/rollup-freebsd-x64": "4.55.1", "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", "@rollup/rollup-linux-arm-musleabihf": "4.55.1", "@rollup/rollup-linux-arm64-gnu": "4.55.1", "@rollup/rollup-linux-arm64-musl": "4.55.1", "@rollup/rollup-linux-loong64-gnu": "4.55.1", "@rollup/rollup-linux-loong64-musl": "4.55.1", "@rollup/rollup-linux-ppc64-gnu": "4.55.1", "@rollup/rollup-linux-ppc64-musl": "4.55.1", "@rollup/rollup-linux-riscv64-gnu": "4.55.1", "@rollup/rollup-linux-riscv64-musl": "4.55.1", "@rollup/rollup-linux-s390x-gnu": "4.55.1", "@rollup/rollup-linux-x64-gnu": "4.55.1", "@rollup/rollup-linux-x64-musl": "4.55.1", "@rollup/rollup-openbsd-x64": "4.55.1", "@rollup/rollup-openharmony-arm64": "4.55.1", "@rollup/rollup-win32-arm64-msvc": "4.55.1", "@rollup/rollup-win32-ia32-msvc": "4.55.1", "@rollup/rollup-win32-x64-gnu": "4.55.1", "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A=="], @@ -1510,6 +1544,8 @@ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], + "socket.io": ["socket.io@4.8.3", "", { "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } }, "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A=="], "socket.io-adapter": ["socket.io-adapter@2.5.6", "", { "dependencies": { "debug": "~4.4.1", "ws": "~8.18.3" } }, "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ=="], @@ -1542,6 +1578,8 @@ "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="], + "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1564,13 +1602,13 @@ "supercluster": ["supercluster@8.0.1", "", { "dependencies": { "kdbush": "^4.0.2" } }, "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ=="], - "svix": ["svix@1.84.1", "", { "dependencies": { "standardwebhooks": "1.0.0", "uuid": "^10.0.0" } }, "sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ=="], + "svix": ["svix@1.86.0", "", { "dependencies": { "standardwebhooks": "1.0.0", "uuid": "^10.0.0" } }, "sha512-/HTvXwjLJe1l/MsLXAO1ddCYxElJk4eNR4DzOjDOEmGrPN/3BtBE8perGwMAaJ2sT5T172VkBYzmHcjUfM1JRQ=="], "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], - "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], + "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], - "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="], + "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], @@ -1588,6 +1626,8 @@ "tinyqueue": ["tinyqueue@3.0.0", "", {}, "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], "token-types": ["token-types@4.2.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ=="], @@ -1600,19 +1640,19 @@ "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], - "turbo": ["turbo@2.7.5", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.5", "turbo-darwin-arm64": "2.7.5", "turbo-linux-64": "2.7.5", "turbo-linux-arm64": "2.7.5", "turbo-windows-64": "2.7.5", "turbo-windows-arm64": "2.7.5" }, "bin": { "turbo": "bin/turbo" } }, "sha512-7Imdmg37joOloTnj+DPrab9hIaQcDdJ5RwSzcauo/wMOSAgO+A/I/8b3hsGGs6PWQz70m/jkPgdqWsfNKtwwDQ=="], + "turbo": ["turbo@2.8.11", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.11", "turbo-darwin-arm64": "2.8.11", "turbo-linux-64": "2.8.11", "turbo-linux-arm64": "2.8.11", "turbo-windows-64": "2.8.11", "turbo-windows-arm64": "2.8.11" }, "bin": { "turbo": "bin/turbo" } }, "sha512-H+rwSHHPLoyPOSoHdmI1zY0zy0GGj1Dmr7SeJW+nZiWLz2nex8EJ+fkdVabxXFMNEux+aywI4Sae8EqhmnOv4A=="], - "turbo-darwin-64": ["turbo-darwin-64@2.7.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-nN3wfLLj4OES/7awYyyM7fkU8U8sAFxsXau2bYJwAWi6T09jd87DgHD8N31zXaJ7LcpyppHWPRI2Ov9MuZEwnQ=="], + "turbo-darwin-64": ["turbo-darwin-64@2.8.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-XKaCWaz4OCt77oYYvGCIRpvYD4c/aNaKjRkUpv+e8rN3RZb+5Xsyew4yRO+gaHdMIUhQznXNXfHlhs+/p7lIhA=="], - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.7.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wCoDHMiTf3FgLAbZHDDx/unNNonSGhsF5AbbYODbxnpYyoKDpEYacUEPjZD895vDhNvYCH0Nnk24YsP4n/cD6g=="], + "turbo-darwin-arm64": ["turbo-darwin-arm64@2.8.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VvynLHGUNvQ9k7GZjRPSsRcK4VkioTfFb7O7liAk4nHKjEcMdls7GqxzjVWgJiKz3hWmQGaP9hRa9UUnhVWCxA=="], - "turbo-linux-64": ["turbo-linux-64@2.7.5", "", { "os": "linux", "cpu": "x64" }, "sha512-KKPvhOmJMmzWj/yjeO4LywkQ85vOJyhru7AZk/+c4B6OUh/odQ++SiIJBSbTG2lm1CuV5gV5vXZnf/2AMlu3Zg=="], + "turbo-linux-64": ["turbo-linux-64@2.8.11", "", { "os": "linux", "cpu": "x64" }, "sha512-cbSn37dcm+EmkQ7DD0euy7xV7o2el4GAOr1XujvkAyKjjNvQ+6QIUeDgQcwAx3D17zPpDvfDMJY2dLQadWnkmQ=="], - "turbo-linux-arm64": ["turbo-linux-arm64@2.7.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-8PIva4L6BQhiPikUTds9lSFSHXVDAsEvV6QUlgwPsXrtXVQMVi6Sv9p+IxtlWQFvGkdYJUgX9GnK2rC030Xcmw=="], + "turbo-linux-arm64": ["turbo-linux-arm64@2.8.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-+trymp2s2aBrhS04l6qFxcExzZ8ffndevuUB9c5RCeqsVpZeiWuGQlWNm5XjOmzoMayxRARZ5ma7yiWbGMiLqQ=="], - "turbo-windows-64": ["turbo-windows-64@2.7.5", "", { "os": "win32", "cpu": "x64" }, "sha512-rupskv/mkIUgQXzX/wUiK00mKMorQcK8yzhGFha/D5lm05FEnLx8dsip6rWzMcVpvh+4GUMA56PgtnOgpel2AA=="], + "turbo-windows-64": ["turbo-windows-64@2.8.11", "", { "os": "win32", "cpu": "x64" }, "sha512-3kJjFSM4yw1n9Uzmi+XkAUgCae19l/bH6RJ442xo7mnZm0tpOjo33F+FYHoSVpIWVMd0HG0LDccyafPSdylQbA=="], - "turbo-windows-arm64": ["turbo-windows-arm64@2.7.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-G377Gxn6P42RnCzfMyDvsqQV7j69kVHKlhz9J4RhtJOB5+DyY4yYh/w0oTIxZQ4JRMmhjwLu3w9zncMoQ6nNDw=="], + "turbo-windows-arm64": ["turbo-windows-arm64@2.8.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-JOM4uF2vuLsJUvibdR6X9QqdZr6BhC6Nhlrw4LKFPsXZZI/9HHLoqAiYRpE4MuzIwldCH/jVySnWXrI1SKto0g=="], "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], @@ -1678,7 +1718,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], "xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="], @@ -1690,6 +1730,8 @@ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], + "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -1706,10 +1748,18 @@ "@babel/traverse/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "@clairvoyant/api/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], + + "@clairvoyant/application/@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], + "@clairvoyant/web/@convex-dev/polar": ["@convex-dev/polar@0.6.4", "", { "dependencies": { "buffer": "^6.0.3", "convex-helpers": "^0.1.63", "remeda": "^2.20.2", "standardwebhooks": "^1.0.0" }, "peerDependencies": { "@polar-sh/checkout": ">=0.1.10", "@polar-sh/sdk": ">=0.32.11", "convex": "^1.25.4", "react": "^18 || ^19", "react-dom": "^18 || ^19" } }, "sha512-QXWe+URjSMIkJI9vB8u4ghNA3IPa1fCnlhP3lXg0kDV5CvW7imZx7TzXx2Yce9ZQA7EhMfSJH6GNBV7zYa7vhQ=="], + "@convex-dev/resend/svix": ["svix@1.84.1", "", { "dependencies": { "standardwebhooks": "1.0.0", "uuid": "^10.0.0" } }, "sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ=="], + "@honcho-ai/core/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], + "@honcho-ai/sdk/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + "@honcho-ai/sdk/zod": ["zod@4.0.0", "", {}, "sha512-9diLdTPc/L7w/5jI4C3gHYNiGHDV9IZYxo1e5LSD8cabi65WVTWWb+g2BGPEpUUCOxR4D+6O5B0AzyMdUAXwrw=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -1724,12 +1774,20 @@ "@mentra/sdk/jsonwebtoken": ["jsonwebtoken@8.5.1", "", { "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^5.6.0" } }, "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w=="], + "@mentra/sdk/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "@polar-sh/checkout/@polar-sh/sdk": ["@polar-sh/sdk@0.39.1", "", { "dependencies": { "standardwebhooks": "^1.0.0", "zod": "^3.25.76" } }, "sha512-PSWnp2EX+guVxtLyUwk2hCgsV/FTOXf+nI33xXwAGHyakACEmJOIeHMxlja++t4YVHf+5GZouT9iYE1yxnmIjQ=="], "@polar-sh/sdk/zod": ["zod@4.0.0", "", {}, "sha512-9diLdTPc/L7w/5jI4C3gHYNiGHDV9IZYxo1e5LSD8cabi65WVTWWb+g2BGPEpUUCOxR4D+6O5B0AzyMdUAXwrw=="], "@polar-sh/ui/lucide-react": ["lucide-react@0.547.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-YLChGBWKq8ynr1UWP8WWRPhHhyuBAXfSBnHSgfoj51L//9TU3d0zvxpigf5C1IJ4vnEoTzthl5awPK55PiZhdA=="], + "@polar-sh/ui/react-day-picker": ["react-day-picker@9.13.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0", "date-fns-jalali": "^4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ=="], + + "@polar-sh/ui/recharts": ["recharts@3.6.0", "", { "dependencies": { "@reduxjs/toolkit": "1.x.x || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-L5bjxvQRAe26RlToBAziKUB7whaGKEwD3znoM6fz3DrTowCIC/FnJYnuq1GEzB8Zv2kdTfaxQfi5GoH0tBinyg=="], + + "@polar-sh/ui/tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], + "@radix-ui/react-alert-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], @@ -1754,6 +1812,8 @@ "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + "@tailwindcss/node/lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], @@ -1766,22 +1826,34 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@types/cors/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + + "@types/jsonwebtoken/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + + "@types/node-fetch/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "browserslist/caniuse-lite": ["caniuse-lite@1.0.30001765", "", {}, "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ=="], + + "bun-types/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + + "cli-truncate/string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="], + "cmdk/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="], "concat-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "convex/esbuild": ["esbuild@0.27.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.0", "@esbuild/android-arm": "0.27.0", "@esbuild/android-arm64": "0.27.0", "@esbuild/android-x64": "0.27.0", "@esbuild/darwin-arm64": "0.27.0", "@esbuild/darwin-x64": "0.27.0", "@esbuild/freebsd-arm64": "0.27.0", "@esbuild/freebsd-x64": "0.27.0", "@esbuild/linux-arm": "0.27.0", "@esbuild/linux-arm64": "0.27.0", "@esbuild/linux-ia32": "0.27.0", "@esbuild/linux-loong64": "0.27.0", "@esbuild/linux-mips64el": "0.27.0", "@esbuild/linux-ppc64": "0.27.0", "@esbuild/linux-riscv64": "0.27.0", "@esbuild/linux-s390x": "0.27.0", "@esbuild/linux-x64": "0.27.0", "@esbuild/netbsd-arm64": "0.27.0", "@esbuild/netbsd-x64": "0.27.0", "@esbuild/openbsd-arm64": "0.27.0", "@esbuild/openbsd-x64": "0.27.0", "@esbuild/openharmony-arm64": "0.27.0", "@esbuild/sunos-x64": "0.27.0", "@esbuild/win32-arm64": "0.27.0", "@esbuild/win32-ia32": "0.27.0", "@esbuild/win32-x64": "0.27.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA=="], - "cookie-parser/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "dot-prop/type-fest": ["type-fest@5.4.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ=="], + "engine.io/@types/node": ["@types/node@24.10.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw=="], + "engine.io/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "engine.io/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], @@ -1802,6 +1874,10 @@ "image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="], + "is-fullwidth-code-point/get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], "pino/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="], @@ -1812,7 +1888,9 @@ "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - "react-email/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "react-email/commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], + + "resend/svix": ["svix@1.84.1", "", { "dependencies": { "standardwebhooks": "1.0.0", "uuid": "^10.0.0" } }, "sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ=="], "serialize-error/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], @@ -1828,20 +1906,24 @@ "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "string-width-cjs/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], - "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@clairvoyant/api/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], + + "@clairvoyant/application/@types/bun/bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], + "@honcho-ai/core/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -1850,63 +1932,37 @@ "@mentra/sdk/jsonwebtoken/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "convex/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A=="], - - "convex/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.0", "", { "os": "android", "cpu": "arm" }, "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ=="], - - "convex/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.0", "", { "os": "android", "cpu": "arm64" }, "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ=="], - - "convex/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.0", "", { "os": "android", "cpu": "x64" }, "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q=="], - - "convex/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg=="], - - "convex/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g=="], - - "convex/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw=="], - - "convex/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g=="], - - "convex/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.0", "", { "os": "linux", "cpu": "arm" }, "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ=="], + "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], - "convex/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ=="], + "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], - "convex/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw=="], + "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], - "convex/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.0", "", { "os": "linux", "cpu": "none" }, "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg=="], + "@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], - "convex/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.0", "", { "os": "linux", "cpu": "none" }, "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg=="], + "@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], - "convex/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA=="], + "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], - "convex/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.0", "", { "os": "linux", "cpu": "none" }, "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ=="], + "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], - "convex/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w=="], + "@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], - "convex/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.0", "", { "os": "linux", "cpu": "x64" }, "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw=="], + "@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], - "convex/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.0", "", { "os": "none", "cpu": "arm64" }, "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w=="], + "@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], - "convex/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.0", "", { "os": "none", "cpu": "x64" }, "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA=="], + "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], - "convex/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ=="], - - "convex/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A=="], - - "convex/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.0", "", { "os": "none", "cpu": "arm64" }, "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA=="], + "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "convex/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA=="], + "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "convex/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg=="], + "ansi-align/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "convex/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ=="], + "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "convex/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.0", "", { "os": "win32", "cpu": "x64" }, "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg=="], + "cli-truncate/string-width/get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -1914,119 +1970,21 @@ "ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], - "react-email/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "react-email/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "react-email/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "react-email/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "react-email/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "react-email/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "react-email/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "react-email/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "react-email/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "react-email/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "react-email/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "react-email/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "react-email/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "react-email/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "react-email/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "react-email/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "react-email/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "react-email/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "react-email/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "react-email/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "react-email/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "react-email/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - - "react-email/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "react-email/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - - "react-email/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - - "react-email/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "split-string/extend-shallow/is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - - "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + "wrap-ansi-cjs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@clairvoyant/api/@types/bun/bun-types/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="], - "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@clairvoyant/application/@types/bun/bun-types/@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="], "@mentra/sdk/jsonwebtoken/jws/jwa": ["jwa@1.4.2", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw=="], diff --git a/docs/autonomous/prd.json b/docs/autonomous/prd.json deleted file mode 100644 index a7e3d57..0000000 --- a/docs/autonomous/prd.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "project": "remove-payment-gating", - "branchName": "autonomous/remove-payment-gating", - "description": "Remove payment gating from the application layer. All features previously behind Pro subscription are now free. Backend Convex schema and Polar webhooks remain intact for potential future use.", - "userStories": [ - { - "id": "US-001", - "title": "Bypass isPro check in application", - "description": "As a user, I can access all features without a Pro subscription because the isPro check always returns true.", - "acceptanceCriteria": [ - "checkUserIsPro() in apps/application/src/core/convex.ts always returns true", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 1, - "passes": true, - "notes": "Function now returns true immediately, parameter renamed to _mentraUserId to indicate unused" - }, - { - "id": "US-002", - "title": "Remove isPro gate from daily summaries", - "description": "As a user, I can view my daily summaries without a Pro subscription.", - "acceptanceCriteria": [ - "packages/convex/dailySummaries.ts getForUser removes subscription check", - "Always returns isPro: true with summaries data", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 2, - "passes": true, - "notes": "Removed polar subscription check and early return. Always returns isPro: true. Removed unused polar import." - }, - { - "id": "US-003", - "title": "Remove subscription gate from session summaries", - "description": "As a user, my session summaries are stored regardless of subscription status.", - "acceptanceCriteria": [ - "packages/convex/sessionSummaries.ts upsert removes subscription check (lines 24-31)", - "Always stores session summaries for all users", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 3, - "passes": true, - "notes": "Removed polar subscription check and early return. Now stores session summaries for all users. Removed unused polar import." - }, - { - "id": "US-004", - "title": "Comment out Billing section in Settings", - "description": "As a user, I no longer see the Billing section in Settings since payments are disabled.", - "acceptanceCriteria": [ - "apps/web/src/components/SettingsPage.tsx Billing button (lines 140-154) is commented out", - "Billing card section (lines 291-310) is commented out", - "SubscriptionCard import can be commented out", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 4, - "passes": true, - "notes": "Commented out SubscriptionCard import, Billing button, and Billing card section with JSX comments" - }, - { - "id": "US-005", - "title": "Remove Pro upgrade prompt from Memory page", - "description": "As a user, I see my memory log directly without an upgrade prompt.", - "acceptanceCriteria": [ - "apps/web/src/components/MemoryPage.tsx removes the !result.isPro conditional block (lines 63-88)", - "Users go straight to viewing summaries or 'no memories yet' state", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 5, - "passes": true, - "notes": "Removed !result.isPro conditional block. Users now go straight to summaries or 'no memories yet' state. Removed unused CardDescription import." - }, - { - "id": "US-006", - "title": "Unify features list on Home page", - "description": "As a user, I see all features in a single unified list without Free/Pro distinction.", - "acceptanceCriteria": [ - "apps/web/src/components/HomePage.tsx FEATURES array: all items have isPro: false", - "UI collapses Free/Pro sections into single 'Features' list", - "Remove 'Upgrade' badge from Pro heading", - "Typecheck passes: bun run build", - "Lint passes: bun run check" - ], - "priority": 6, - "passes": true, - "notes": "Set all isPro: false in FEATURES array. Collapsed Free/Pro sections into single unified list. Removed Pro badge from accordion triggers." - } - ] -} diff --git a/docs/autonomous/progress.txt b/docs/autonomous/progress.txt deleted file mode 100644 index 502054b..0000000 --- a/docs/autonomous/progress.txt +++ /dev/null @@ -1,62 +0,0 @@ -# Progress Log - -## Iteration Counter -current_iteration: 7 -max_iterations: 15 - -## Codebase Patterns - -- Build check: `bun run build` -- Lint check: `bun run check` -- Package manager: bun -- Monorepo structure: apps/application, apps/web, packages/convex -- isPro gating pattern: `checkUserIsPro()` in apps/application/src/core/convex.ts -- Convex subscription check: `polar.getCurrentSubscription(ctx, { userId })` - ---- - -## Execution Log - -(Entries appended below as iterations complete) - ---- - -## 2026-01-17 | US-001 | T-019bcf05-d7a5-725a-920d-5893c5e42879 -**Changes:** Modified checkUserIsPro() to always return true, bypassing all Pro checks in application handlers -**Files:** apps/application/src/core/convex.ts -**Learnings:** Pre-existing lint errors in codebase (36 errors), unrelated to payment gating changes - ---- - -## 2026-01-17 | US-002 | T-019bcf14-b957-7596-a765-6977690c16b4 -**Changes:** Removed polar subscription check from getForUser query. Always returns isPro: true with summaries. Removed unused polar import. -**Files:** packages/convex/dailySummaries.ts -**Learnings:** None - straightforward pattern matching US-001 - ---- - -## 2026-01-17 | US-003 | T-019bcf15-c3db-76bd-9131-479e7e8a8787 -**Changes:** Removed polar subscription check from upsert mutation. Session summaries now stored for all users. Removed unused polar import. -**Files:** packages/convex/sessionSummaries.ts -**Learnings:** None - same pattern as US-001 and US-002 - ---- - -## 2026-01-17 | US-004 | T-019bcf16-a824-75dc-9360-9b2c5fa777bf -**Changes:** Commented out Billing section in Settings - SubscriptionCard import, Billing button, and Billing card section -**Files:** apps/web/src/components/SettingsPage.tsx -**Learnings:** None - straightforward JSX comment pattern - ---- - -## 2026-01-17 | US-005 | T-019bcf17-9b44-7058-b0d4-079f92ef715c -**Changes:** Removed !result.isPro conditional block from MemoryPage.tsx. Users now see summaries or "no memories yet" directly. Removed unused CardDescription import. -**Files:** apps/web/src/components/MemoryPage.tsx -**Learnings:** None - straightforward removal of conditional block - ---- - -## 2026-01-17 | US-006 | T-019bcf18-7598-72cb-b2fb-ca7b86c9f04f -**Changes:** Set all isPro: false in FEATURES array. Collapsed Free/Pro sections into single unified "Features" list. Removed Pro badge from accordion triggers. -**Files:** apps/web/src/components/HomePage.tsx -**Learnings:** None - straightforward data change and UI simplification diff --git a/docs/autonomous/prompt.md b/docs/autonomous/prompt.md deleted file mode 100644 index 9854da4..0000000 --- a/docs/autonomous/prompt.md +++ /dev/null @@ -1,71 +0,0 @@ -# Ralph Mode: Remove Payment Gating - -You are executing Ralph Mode via Amp handoffs. Follow these rules strictly. - -## Context - -The Mantra platform CTO confirmed WebView-based payment processing is not possible. We are removing all payment gating from the application layer so all features are free. Backend Convex schema and Polar webhooks remain intact for potential future use. - -## Execution Steps (In Order) - -1. **Read progress.txt FIRST** — Check "Codebase Patterns" section at top -2. **Read prd.json** — Find current state -3. **Check iteration limit** — If `current_iteration >= max_iterations`, output `COMPLETE` and STOP -4. **Check branch** — Ensure on `autonomous/remove-payment-gating`, checkout if needed -5. **Pick next story** — First story where `passes: false` (lowest priority number) -6. **Implement ONE story** — Complete all acceptance criteria -7. **Run quality checks** — `bun run build` and `bun run check` -8. **Update AGENTS.md** — If patterns discovered, add to relevant AGENTS.md -9. **Commit** — `git add -A && git commit -m "feat: [US-XXX] - title"` -10. **Update prd.json** — Set `passes: true`, add notes -11. **Update progress.txt** — Increment counter, append log entry -12. **Check completion**: - - If ALL stories pass → output `COMPLETE` and STOP - - If `current_iteration >= max_iterations` → output `COMPLETE` and STOP - - Otherwise → handoff to fresh thread - -## Handoff Format - -When handing off, use this goal: -``` -Execute Ralph Mode for remove-payment-gating. Read docs/autonomous/prompt.md for instructions. -``` - -## Progress Report Format - -APPEND to progress.txt (never replace existing content): - -```markdown ---- - -## YYYY-MM-DD | US-XXX | T- -**Changes:** Brief description of what was implemented -**Files:** file1.ts, file2.ts -**Learnings:** Patterns discovered for future iterations -``` - -## Stop Conditions - -Output `COMPLETE` when: -- All stories have `passes: true` -- `current_iteration >= max_iterations` -- Unrecoverable error (document in progress.txt first) - -## Reference Files - -| File | Purpose | -|------|---------| -| apps/application/src/core/convex.ts | checkUserIsPro() function (US-001) | -| packages/convex/dailySummaries.ts | getForUser query with isPro gate (US-002) | -| packages/convex/sessionSummaries.ts | upsert mutation with subscription gate (US-003) | -| apps/web/src/components/SettingsPage.tsx | Billing section to comment out (US-004) | -| apps/web/src/components/MemoryPage.tsx | isPro upgrade prompt to remove (US-005) | -| apps/web/src/components/HomePage.tsx | FEATURES array and Free/Pro UI (US-006) | - -## Quality Requirements - -- ALL commits must pass typecheck (`bun run build`) -- ALL commits must pass lint (`bun run check`) -- Do NOT commit broken code -- Keep changes focused and minimal -- Follow existing patterns in codebase diff --git a/docs/screenshots/followups-mobile.png b/docs/screenshots/followups-mobile.png new file mode 100644 index 0000000..0fd522c Binary files /dev/null and b/docs/screenshots/followups-mobile.png differ diff --git a/docs/screenshots/home-mobile.png b/docs/screenshots/home-mobile.png new file mode 100644 index 0000000..5205525 Binary files /dev/null and b/docs/screenshots/home-mobile.png differ diff --git a/docs/screenshots/memory-mobile.png b/docs/screenshots/memory-mobile.png new file mode 100644 index 0000000..36266d0 Binary files /dev/null and b/docs/screenshots/memory-mobile.png differ diff --git a/docs/screenshots/queue-mobile.png b/docs/screenshots/queue-mobile.png new file mode 100644 index 0000000..03d89e8 Binary files /dev/null and b/docs/screenshots/queue-mobile.png differ diff --git a/docs/screenshots/settings-mobile.png b/docs/screenshots/settings-mobile.png new file mode 100644 index 0000000..c881f0e Binary files /dev/null and b/docs/screenshots/settings-mobile.png differ diff --git a/package.json b/package.json index cfdfa64..5e18432 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "type": "module", "private": true, - "packageManager": "bun@1.3.5", + "packageManager": "bun@1.3.10", "workspaces": [ "apps/*", "packages/*" @@ -23,22 +23,31 @@ "test": "turbo run test", "clean": "rm -rf node_modules apps/*/node_modules packages/*/node_modules .turbo apps/*/.turbo packages/*/.turbo apps/*/dist packages/*/dist apps/*/build packages/*/build packages/convex/_generated bun.lock", "clean:install": "bun run clean && bun install", - "ngrok": "turbo run dev --filter=@clairvoyant/ngrok" + "ngrok": "turbo run dev --filter=@clairvoyant/ngrok", + "prepare": "husky" }, "dependencies": { - "convex": "^1.31.2", - "elysia": "^1.4.19" + "convex": "^1.32.0", + "elysia": "^1.4.26" }, "overrides": { - "elysia": "$elysia" + "elysia": "$elysia", + "esbuild": "0.25.12" + }, + "lint-staged": { + "*.{ts,tsx,js,jsx,json,css}": [ + "bunx biome check --write --no-errors-on-unmatched" + ] }, "devDependencies": { "@biomejs/biome": "2.1.2", "@boundaryml/baml": "0.215.0", "@types/bun": "latest", - "@types/node": "^24.10.4", + "@types/node": "^24.10.15", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "tsx": "^4.21.0", - "turbo": "^2.7.0", + "turbo": "^2.8.11", "typescript": "^5.9.3" } } diff --git a/packages/convex/_generated/api.d.ts b/packages/convex/_generated/api.d.ts index 572c7da..3c5d346 100644 --- a/packages/convex/_generated/api.d.ts +++ b/packages/convex/_generated/api.d.ts @@ -12,14 +12,19 @@ import type * as analytics from "../analytics.js"; import type * as bamlActions from "../bamlActions.js"; import type * as chat from "../chat.js"; import type * as chatQueries from "../chatQueries.js"; +import type * as conversationLogs from "../conversationLogs.js"; import type * as cronManagement from "../cronManagement.js"; import type * as dailySummaries from "../dailySummaries.js"; import type * as dailySynthesis from "../dailySynthesis.js"; import type * as displayQueue from "../displayQueue.js"; +import type * as emailEntitlements from "../emailEntitlements.js"; +import type * as emailEntitlementsNode from "../emailEntitlementsNode.js"; import type * as emailEvents from "../emailEvents.js"; import type * as emailNotes from "../emailNotes.js"; import type * as emailReply from "../emailReply.js"; import type * as emailThreadMessages from "../emailThreadMessages.js"; +import type * as emails_EmailThreadPaywall from "../emails/EmailThreadPaywall.js"; +import type * as emails_OptOutCheckout from "../emails/OptOutCheckout.js"; import type * as emails_SessionNote from "../emails/SessionNote.js"; import type * as followups from "../followups.js"; import type * as followupsChat from "../followupsChat.js"; @@ -30,6 +35,7 @@ import type * as http from "../http.js"; import type * as inboundEmail from "../inboundEmail.js"; import type * as init from "../init.js"; import type * as notes from "../notes.js"; +import type * as optOut from "../optOut.js"; import type * as payments from "../payments.js"; import type * as resendClient from "../resendClient.js"; import type * as sessionSummaries from "../sessionSummaries.js"; @@ -37,39 +43,45 @@ import type * as tavilySearch from "../tavilySearch.js"; import type * as users from "../users.js"; import type { - ApiFromModules, - FilterApi, - FunctionReference, + ApiFromModules, + FilterApi, + FunctionReference, } from "convex/server"; declare const fullApi: ApiFromModules<{ - analytics: typeof analytics; - bamlActions: typeof bamlActions; - chat: typeof chat; - chatQueries: typeof chatQueries; - cronManagement: typeof cronManagement; - dailySummaries: typeof dailySummaries; - dailySynthesis: typeof dailySynthesis; - displayQueue: typeof displayQueue; - emailEvents: typeof emailEvents; - emailNotes: typeof emailNotes; - emailReply: typeof emailReply; - emailThreadMessages: typeof emailThreadMessages; - "emails/SessionNote": typeof emails_SessionNote; - followups: typeof followups; - followupsChat: typeof followupsChat; - followupsChatQueries: typeof followupsChatQueries; - honcho: typeof honcho; - honchoSessions: typeof honchoSessions; - http: typeof http; - inboundEmail: typeof inboundEmail; - init: typeof init; - notes: typeof notes; - payments: typeof payments; - resendClient: typeof resendClient; - sessionSummaries: typeof sessionSummaries; - tavilySearch: typeof tavilySearch; - users: typeof users; + analytics: typeof analytics; + bamlActions: typeof bamlActions; + chat: typeof chat; + chatQueries: typeof chatQueries; + conversationLogs: typeof conversationLogs; + cronManagement: typeof cronManagement; + dailySummaries: typeof dailySummaries; + dailySynthesis: typeof dailySynthesis; + displayQueue: typeof displayQueue; + emailEntitlements: typeof emailEntitlements; + emailEntitlementsNode: typeof emailEntitlementsNode; + emailEvents: typeof emailEvents; + emailNotes: typeof emailNotes; + emailReply: typeof emailReply; + emailThreadMessages: typeof emailThreadMessages; + "emails/EmailThreadPaywall": typeof emails_EmailThreadPaywall; + "emails/OptOutCheckout": typeof emails_OptOutCheckout; + "emails/SessionNote": typeof emails_SessionNote; + followups: typeof followups; + followupsChat: typeof followupsChat; + followupsChatQueries: typeof followupsChatQueries; + honcho: typeof honcho; + honchoSessions: typeof honchoSessions; + http: typeof http; + inboundEmail: typeof inboundEmail; + init: typeof init; + notes: typeof notes; + optOut: typeof optOut; + payments: typeof payments; + resendClient: typeof resendClient; + sessionSummaries: typeof sessionSummaries; + tavilySearch: typeof tavilySearch; + users: typeof users; }>; /** @@ -81,8 +93,8 @@ declare const fullApi: ApiFromModules<{ * ``` */ export declare const api: FilterApi< - typeof fullApi, - FunctionReference + typeof fullApi, + FunctionReference >; /** @@ -94,752 +106,752 @@ export declare const api: FilterApi< * ``` */ export declare const internal: FilterApi< - typeof fullApi, - FunctionReference + typeof fullApi, + FunctionReference >; export declare const components: { - polar: { - lib: { - createProduct: FunctionReference< - "mutation", - "internal", - { - product: { - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - }; - }, - any - >; - createSubscription: FunctionReference< - "mutation", - "internal", - { - subscription: { - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - }; - }, - any - >; - getCurrentSubscription: FunctionReference< - "query", - "internal", - { userId: string }, - { - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - product: { - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - }; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - } | null - >; - getCustomerByUserId: FunctionReference< - "query", - "internal", - { userId: string }, - { id: string; metadata?: Record; userId: string } | null - >; - getProduct: FunctionReference< - "query", - "internal", - { id: string }, - { - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - } | null - >; - getSubscription: FunctionReference< - "query", - "internal", - { id: string }, - { - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - } | null - >; - insertCustomer: FunctionReference< - "mutation", - "internal", - { id: string; metadata?: Record; userId: string }, - string - >; - listCustomerSubscriptions: FunctionReference< - "query", - "internal", - { customerId: string }, - Array<{ - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - }> - >; - listProducts: FunctionReference< - "query", - "internal", - { includeArchived?: boolean }, - Array<{ - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - priceAmount?: number; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - }> - >; - listUserSubscriptions: FunctionReference< - "query", - "internal", - { userId: string }, - Array<{ - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - product: { - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - } | null; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - }> - >; - syncProducts: FunctionReference< - "action", - "internal", - { polarAccessToken: string; server: "sandbox" | "production" }, - any - >; - updateProduct: FunctionReference< - "mutation", - "internal", - { - product: { - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - }; - }, - any - >; - updateProducts: FunctionReference< - "mutation", - "internal", - { - polarAccessToken: string; - products: Array<{ - createdAt: string; - description: string | null; - id: string; - isArchived: boolean; - isRecurring: boolean; - medias: Array<{ - checksumEtag: string | null; - checksumSha256Base64: string | null; - checksumSha256Hex: string | null; - createdAt: string; - id: string; - isUploaded: boolean; - lastModifiedAt: string | null; - mimeType: string; - name: string; - organizationId: string; - path: string; - publicUrl: string; - service?: string; - size: number; - sizeReadable: string; - storageVersion: string | null; - version: string | null; - }>; - metadata?: Record; - modifiedAt: string | null; - name: string; - organizationId: string; - prices: Array<{ - amountType?: string; - createdAt: string; - id: string; - isArchived: boolean; - maximumAmount?: number | null; - minimumAmount?: number | null; - modifiedAt: string | null; - presetAmount?: number | null; - priceAmount?: number; - priceCurrency?: string; - productId: string; - recurringInterval?: "day" | "week" | "month" | "year" | null; - type?: string; - }>; - recurringInterval?: "day" | "week" | "month" | "year" | null; - }>; - }, - any - >; - updateSubscription: FunctionReference< - "mutation", - "internal", - { - subscription: { - amount: number | null; - cancelAtPeriodEnd: boolean; - checkoutId: string | null; - createdAt: string; - currency: string | null; - currentPeriodEnd: string | null; - currentPeriodStart: string; - customerCancellationComment?: string | null; - customerCancellationReason?: string | null; - customerId: string; - endedAt: string | null; - id: string; - metadata: Record; - modifiedAt: string | null; - priceId?: string; - productId: string; - recurringInterval: "day" | "week" | "month" | "year" | null; - startedAt: string | null; - status: string; - }; - }, - any - >; - upsertCustomer: FunctionReference< - "mutation", - "internal", - { id: string; metadata?: Record; userId: string }, - string - >; - }; - }; - crons: { - public: { - del: FunctionReference< - "mutation", - "internal", - { identifier: { id: string } | { name: string } }, - null - >; - get: FunctionReference< - "query", - "internal", - { identifier: { id: string } | { name: string } }, - { - args: Record; - functionHandle: string; - id: string; - name?: string; - schedule: - | { kind: "interval"; ms: number } - | { cronspec: string; kind: "cron"; tz?: string }; - } | null - >; - list: FunctionReference< - "query", - "internal", - {}, - Array<{ - args: Record; - functionHandle: string; - id: string; - name?: string; - schedule: - | { kind: "interval"; ms: number } - | { cronspec: string; kind: "cron"; tz?: string }; - }> - >; - register: FunctionReference< - "mutation", - "internal", - { - args: Record; - functionHandle: string; - name?: string; - schedule: - | { kind: "interval"; ms: number } - | { cronspec: string; kind: "cron"; tz?: string }; - }, - string - >; - }; - }; - resend: { - lib: { - cancelEmail: FunctionReference< - "mutation", - "internal", - { emailId: string }, - null - >; - cleanupAbandonedEmails: FunctionReference< - "mutation", - "internal", - { olderThan?: number }, - null - >; - cleanupOldEmails: FunctionReference< - "mutation", - "internal", - { olderThan?: number }, - null - >; - createManualEmail: FunctionReference< - "mutation", - "internal", - { - from: string; - headers?: Array<{ name: string; value: string }>; - replyTo?: Array; - subject: string; - to: Array | string; - }, - string - >; - get: FunctionReference< - "query", - "internal", - { emailId: string }, - { - bcc?: Array; - bounced?: boolean; - cc?: Array; - clicked?: boolean; - complained: boolean; - createdAt: number; - deliveryDelayed?: boolean; - errorMessage?: string; - failed?: boolean; - finalizedAt: number; - from: string; - headers?: Array<{ name: string; value: string }>; - html?: string; - opened: boolean; - replyTo: Array; - resendId?: string; - segment: number; - status: - | "waiting" - | "queued" - | "cancelled" - | "sent" - | "delivered" - | "delivery_delayed" - | "bounced" - | "failed"; - subject?: string; - template?: { - id: string; - variables?: Record; - }; - text?: string; - to: Array; - } | null - >; - getStatus: FunctionReference< - "query", - "internal", - { emailId: string }, - { - bounced: boolean; - clicked: boolean; - complained: boolean; - deliveryDelayed: boolean; - errorMessage: string | null; - failed: boolean; - opened: boolean; - status: - | "waiting" - | "queued" - | "cancelled" - | "sent" - | "delivered" - | "delivery_delayed" - | "bounced" - | "failed"; - } | null - >; - handleEmailEvent: FunctionReference< - "mutation", - "internal", - { event: any }, - null - >; - sendEmail: FunctionReference< - "mutation", - "internal", - { - bcc?: Array; - cc?: Array; - from: string; - headers?: Array<{ name: string; value: string }>; - html?: string; - options: { - apiKey: string; - initialBackoffMs: number; - onEmailEvent?: { fnHandle: string }; - retryAttempts: number; - testMode: boolean; - }; - replyTo?: Array; - subject?: string; - template?: { - id: string; - variables?: Record; - }; - text?: string; - to: Array; - }, - string - >; - updateManualEmail: FunctionReference< - "mutation", - "internal", - { - emailId: string; - errorMessage?: string; - resendId?: string; - status: - | "waiting" - | "queued" - | "cancelled" - | "sent" - | "delivered" - | "delivery_delayed" - | "bounced" - | "failed"; - }, - null - >; - }; - }; + polar: { + lib: { + createProduct: FunctionReference< + "mutation", + "internal", + { + product: { + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + }; + }, + any + >; + createSubscription: FunctionReference< + "mutation", + "internal", + { + subscription: { + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + }; + }, + any + >; + getCurrentSubscription: FunctionReference< + "query", + "internal", + { userId: string }, + { + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + product: { + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + }; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + } | null + >; + getCustomerByUserId: FunctionReference< + "query", + "internal", + { userId: string }, + { id: string; metadata?: Record; userId: string } | null + >; + getProduct: FunctionReference< + "query", + "internal", + { id: string }, + { + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + } | null + >; + getSubscription: FunctionReference< + "query", + "internal", + { id: string }, + { + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + } | null + >; + insertCustomer: FunctionReference< + "mutation", + "internal", + { id: string; metadata?: Record; userId: string }, + string + >; + listCustomerSubscriptions: FunctionReference< + "query", + "internal", + { customerId: string }, + Array<{ + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + }> + >; + listProducts: FunctionReference< + "query", + "internal", + { includeArchived?: boolean }, + Array<{ + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + priceAmount?: number; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + }> + >; + listUserSubscriptions: FunctionReference< + "query", + "internal", + { userId: string }, + Array<{ + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + product: { + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + } | null; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + }> + >; + syncProducts: FunctionReference< + "action", + "internal", + { polarAccessToken: string; server: "sandbox" | "production" }, + any + >; + updateProduct: FunctionReference< + "mutation", + "internal", + { + product: { + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + }; + }, + any + >; + updateProducts: FunctionReference< + "mutation", + "internal", + { + polarAccessToken: string; + products: Array<{ + createdAt: string; + description: string | null; + id: string; + isArchived: boolean; + isRecurring: boolean; + medias: Array<{ + checksumEtag: string | null; + checksumSha256Base64: string | null; + checksumSha256Hex: string | null; + createdAt: string; + id: string; + isUploaded: boolean; + lastModifiedAt: string | null; + mimeType: string; + name: string; + organizationId: string; + path: string; + publicUrl: string; + service?: string; + size: number; + sizeReadable: string; + storageVersion: string | null; + version: string | null; + }>; + metadata?: Record; + modifiedAt: string | null; + name: string; + organizationId: string; + prices: Array<{ + amountType?: string; + createdAt: string; + id: string; + isArchived: boolean; + maximumAmount?: number | null; + minimumAmount?: number | null; + modifiedAt: string | null; + presetAmount?: number | null; + priceAmount?: number; + priceCurrency?: string; + productId: string; + recurringInterval?: "day" | "week" | "month" | "year" | null; + type?: string; + }>; + recurringInterval?: "day" | "week" | "month" | "year" | null; + }>; + }, + any + >; + updateSubscription: FunctionReference< + "mutation", + "internal", + { + subscription: { + amount: number | null; + cancelAtPeriodEnd: boolean; + checkoutId: string | null; + createdAt: string; + currency: string | null; + currentPeriodEnd: string | null; + currentPeriodStart: string; + customerCancellationComment?: string | null; + customerCancellationReason?: string | null; + customerId: string; + endedAt: string | null; + id: string; + metadata: Record; + modifiedAt: string | null; + priceId?: string; + productId: string; + recurringInterval: "day" | "week" | "month" | "year" | null; + startedAt: string | null; + status: string; + }; + }, + any + >; + upsertCustomer: FunctionReference< + "mutation", + "internal", + { id: string; metadata?: Record; userId: string }, + string + >; + }; + }; + crons: { + public: { + del: FunctionReference< + "mutation", + "internal", + { identifier: { id: string } | { name: string } }, + null + >; + get: FunctionReference< + "query", + "internal", + { identifier: { id: string } | { name: string } }, + { + args: Record; + functionHandle: string; + id: string; + name?: string; + schedule: + | { kind: "interval"; ms: number } + | { cronspec: string; kind: "cron"; tz?: string }; + } | null + >; + list: FunctionReference< + "query", + "internal", + {}, + Array<{ + args: Record; + functionHandle: string; + id: string; + name?: string; + schedule: + | { kind: "interval"; ms: number } + | { cronspec: string; kind: "cron"; tz?: string }; + }> + >; + register: FunctionReference< + "mutation", + "internal", + { + args: Record; + functionHandle: string; + name?: string; + schedule: + | { kind: "interval"; ms: number } + | { cronspec: string; kind: "cron"; tz?: string }; + }, + string + >; + }; + }; + resend: { + lib: { + cancelEmail: FunctionReference< + "mutation", + "internal", + { emailId: string }, + null + >; + cleanupAbandonedEmails: FunctionReference< + "mutation", + "internal", + { olderThan?: number }, + null + >; + cleanupOldEmails: FunctionReference< + "mutation", + "internal", + { olderThan?: number }, + null + >; + createManualEmail: FunctionReference< + "mutation", + "internal", + { + from: string; + headers?: Array<{ name: string; value: string }>; + replyTo?: Array; + subject: string; + to: Array | string; + }, + string + >; + get: FunctionReference< + "query", + "internal", + { emailId: string }, + { + bcc?: Array; + bounced?: boolean; + cc?: Array; + clicked?: boolean; + complained: boolean; + createdAt: number; + deliveryDelayed?: boolean; + errorMessage?: string; + failed?: boolean; + finalizedAt: number; + from: string; + headers?: Array<{ name: string; value: string }>; + html?: string; + opened: boolean; + replyTo: Array; + resendId?: string; + segment: number; + status: + | "waiting" + | "queued" + | "cancelled" + | "sent" + | "delivered" + | "delivery_delayed" + | "bounced" + | "failed"; + subject?: string; + template?: { + id: string; + variables?: Record; + }; + text?: string; + to: Array; + } | null + >; + getStatus: FunctionReference< + "query", + "internal", + { emailId: string }, + { + bounced: boolean; + clicked: boolean; + complained: boolean; + deliveryDelayed: boolean; + errorMessage: string | null; + failed: boolean; + opened: boolean; + status: + | "waiting" + | "queued" + | "cancelled" + | "sent" + | "delivered" + | "delivery_delayed" + | "bounced" + | "failed"; + } | null + >; + handleEmailEvent: FunctionReference< + "mutation", + "internal", + { event: any }, + null + >; + sendEmail: FunctionReference< + "mutation", + "internal", + { + bcc?: Array; + cc?: Array; + from: string; + headers?: Array<{ name: string; value: string }>; + html?: string; + options: { + apiKey: string; + initialBackoffMs: number; + onEmailEvent?: { fnHandle: string }; + retryAttempts: number; + testMode: boolean; + }; + replyTo?: Array; + subject?: string; + template?: { + id: string; + variables?: Record; + }; + text?: string; + to: Array; + }, + string + >; + updateManualEmail: FunctionReference< + "mutation", + "internal", + { + emailId: string; + errorMessage?: string; + resendId?: string; + status: + | "waiting" + | "queued" + | "cancelled" + | "sent" + | "delivered" + | "delivery_delayed" + | "bounced" + | "failed"; + }, + null + >; + }; + }; }; diff --git a/packages/convex/conversationLogs.ts b/packages/convex/conversationLogs.ts new file mode 100644 index 0000000..6a230bb --- /dev/null +++ b/packages/convex/conversationLogs.ts @@ -0,0 +1,80 @@ +import { v } from "convex/values"; +import { mutation, query } from "./_generated/server"; + +export const logConversation = mutation({ + args: { + userId: v.id("users"), + sessionId: v.string(), + transcript: v.string(), + route: v.string(), + response: v.optional(v.string()), + }, + handler: async (ctx, args) => { + const user = await ctx.db.get(args.userId); + if (user?.optedOutOfTraining) { + return null; + } + + return await ctx.db.insert("conversationLogs", { + userId: args.userId, + sessionId: args.sessionId, + transcript: args.transcript, + route: args.route, + response: args.response, + }); + }, +}); + +export const getBySession = query({ + args: { + sessionId: v.string(), + }, + handler: async (ctx, args) => { + return await ctx.db + .query("conversationLogs") + .withIndex("by_session", (q) => q.eq("sessionId", args.sessionId)) + .order("desc") + .collect(); + }, +}); + +export const getByUser = query({ + args: { + userId: v.id("users"), + }, + handler: async (ctx, args) => { + return await ctx.db + .query("conversationLogs") + .withIndex("by_user", (q) => q.eq("userId", args.userId)) + .order("desc") + .collect(); + }, +}); + +export const updateResponse = mutation({ + args: { + userId: v.id("users"), + sessionId: v.string(), + transcript: v.string(), + response: v.string(), + }, + handler: async (ctx, args) => { + const log = await ctx.db + .query("conversationLogs") + .withIndex("by_session", (q) => q.eq("sessionId", args.sessionId)) + .filter((q) => + q.and( + q.eq(q.field("userId"), args.userId), + q.eq(q.field("transcript"), args.transcript), + ), + ) + .order("desc") + .first(); + + if (log) { + await ctx.db.patch(log._id, { response: args.response }); + return log._id; + } + return null; + }, +}); diff --git a/packages/convex/emailEntitlements.ts b/packages/convex/emailEntitlements.ts new file mode 100644 index 0000000..ac5fc78 --- /dev/null +++ b/packages/convex/emailEntitlements.ts @@ -0,0 +1,117 @@ +import { v } from "convex/values"; +import { internalMutation, internalQuery, query } from "./_generated/server"; + +export const FREE_EMAIL_THREAD_LIMIT = 10; + +function currentPeriodKey(): string { + const now = new Date(); + const month = String(now.getUTCMonth() + 1).padStart(2, "0"); + return `${now.getUTCFullYear()}-${month}`; +} + +export const getEmailThreadStatus = query({ + args: { mentraUserId: v.string() }, + handler: async (ctx, args) => { + const user = await ctx.db + .query("users") + .withIndex("by_mentra_id", (q) => q.eq("mentraUserId", args.mentraUserId)) + .first(); + + if (!user) { + return null; + } + + const periodKey = currentPeriodKey(); + const usage = await ctx.db + .query("emailThreadUsage") + .withIndex("by_user_period", (q) => + q.eq("userId", user._id).eq("periodKey", periodKey), + ) + .first(); + + const used = usage?.outboundCount ?? 0; + const limit = FREE_EMAIL_THREAD_LIMIT; + + return { + periodKey, + paidEmailThreads: user.paidEmailThreads ?? false, + used, + limit, + remaining: Math.max(0, limit - used), + }; + }, +}); + +export const getUsageByUserPeriod = internalQuery({ + args: { + userId: v.id("users"), + periodKey: v.string(), + }, + handler: async (ctx, args) => { + return await ctx.db + .query("emailThreadUsage") + .withIndex("by_user_period", (q) => + q.eq("userId", args.userId).eq("periodKey", args.periodKey), + ) + .first(); + }, +}); + +export const incrementOutboundUsage = internalMutation({ + args: { + userId: v.id("users"), + periodKey: v.optional(v.string()), + }, + handler: async (ctx, args) => { + const periodKey = args.periodKey ?? currentPeriodKey(); + const existing = await ctx.db + .query("emailThreadUsage") + .withIndex("by_user_period", (q) => + q.eq("userId", args.userId).eq("periodKey", periodKey), + ) + .first(); + + if (existing) { + await ctx.db.patch(existing._id, { + outboundCount: existing.outboundCount + 1, + }); + return existing._id; + } + + return await ctx.db.insert("emailThreadUsage", { + userId: args.userId, + periodKey, + outboundCount: 1, + }); + }, +}); + +export const markPaywallSent = internalMutation({ + args: { + userId: v.id("users"), + periodKey: v.string(), + }, + handler: async (ctx, args) => { + const existing = await ctx.db + .query("emailThreadUsage") + .withIndex("by_user_period", (q) => + q.eq("userId", args.userId).eq("periodKey", args.periodKey), + ) + .first(); + + const timestamp = new Date().toISOString(); + if (existing) { + await ctx.db.patch(existing._id, { + paywallEmailSentAt: timestamp, + }); + return existing._id; + } + + return await ctx.db.insert("emailThreadUsage", { + userId: args.userId, + periodKey: args.periodKey, + outboundCount: FREE_EMAIL_THREAD_LIMIT, + paywallEmailSentAt: timestamp, + }); + }, +}); diff --git a/packages/convex/emailEntitlementsNode.ts b/packages/convex/emailEntitlementsNode.ts new file mode 100644 index 0000000..40046a9 --- /dev/null +++ b/packages/convex/emailEntitlementsNode.ts @@ -0,0 +1,96 @@ +"use node"; + +import { render } from "@react-email/render"; +import { v } from "convex/values"; +import { internal } from "./_generated/api"; +import { internalAction } from "./_generated/server"; +import { FREE_EMAIL_THREAD_LIMIT } from "./emailEntitlements"; +import { EmailThreadPaywallEmail } from "./emails/EmailThreadPaywall"; +import { resend } from "./resendClient"; + +const EMAIL_DOMAIN = process.env.EMAIL_DOMAIN || "notes.example.com"; + +function currentPeriodKey(): string { + const now = new Date(); + const month = String(now.getUTCMonth() + 1).padStart(2, "0"); + return `${now.getUTCFullYear()}-${month}`; +} + +export const preflightOutboundEmail = internalAction({ + args: { userId: v.id("users") }, + handler: async ( + ctx, + args, + ): Promise<{ allowed: boolean; trackUsage: boolean; reason?: string }> => { + const user = await ctx.runQuery(internal.users.getByIdInternal, { + userId: args.userId, + }); + if (!user) { + return { + allowed: false as const, + trackUsage: false, + reason: "user_not_found", + }; + } + + if (user.paidEmailThreads) { + return { allowed: true as const, trackUsage: false }; + } + + const periodKey = currentPeriodKey(); + const usage = await ctx.runQuery( + internal.emailEntitlements.getUsageByUserPeriod, + { + userId: args.userId, + periodKey, + }, + ); + + const used = usage?.outboundCount ?? 0; + if (used < FREE_EMAIL_THREAD_LIMIT) { + return { allowed: true as const, trackUsage: true }; + } + + if (!usage?.paywallEmailSentAt && user.email) { + try { + const checkout = await ctx.runAction( + internal.payments.createFeatureCheckoutLinkInternal, + { + userId: args.userId, + feature: "emailThreads", + }, + ); + + const html = await render( + EmailThreadPaywallEmail({ + checkoutUrl: checkout.url, + limit: FREE_EMAIL_THREAD_LIMIT, + }), + ); + + await resend.sendEmail(ctx, { + from: `Clairvoyant `, + to: user.email, + subject: "Continue your Clairvoyant email thread", + html, + }); + + await ctx.runMutation(internal.emailEntitlements.markPaywallSent, { + userId: args.userId, + periodKey, + }); + } catch (error) { + console.error( + "[EmailEntitlements] Failed to send paywall email:", + error, + ); + } + } + + return { + allowed: false as const, + trackUsage: false, + reason: "limit_reached", + }; + }, +}); diff --git a/packages/convex/emailReply.ts b/packages/convex/emailReply.ts index f98c46e..dbd73ef 100644 --- a/packages/convex/emailReply.ts +++ b/packages/convex/emailReply.ts @@ -261,22 +261,25 @@ export const processEmailReply = internalAction({ const diatribePeer = await honchoClient.peer(`${user._id}-diatribe`, { metadata: { name: "Diatribe", - description: "A peer that listens to the raw translations of the users' speech.", + description: + "A peer that listens to the raw translations of the users' speech.", }, }); const synthesisPeer = await honchoClient.peer(`${user._id}-synthesis`, { metadata: { name: "Synthesis Peer", - description: "A peer that captures synthesized knowledge from the user's speech.", + description: + "A peer that captures synthesized knowledge from the user's speech.", }, }); await session.addPeers([diatribePeer, synthesisPeer]); // Add user email message + extracted facts to diatribe peer - const userContent = interpretation.extractedFacts.length > 0 - ? `${textContent}\n\nExtracted facts:\n${interpretation.extractedFacts.map((f) => `• ${f}`).join("\n")}` - : textContent; + const userContent = + interpretation.extractedFacts.length > 0 + ? `${textContent}\n\nExtracted facts:\n${interpretation.extractedFacts.map((f) => `• ${f}`).join("\n")}` + : textContent; await session.addMessages([ { @@ -290,7 +293,9 @@ export const processEmailReply = internalAction({ }, }, ]); - console.log(`[EmailReply] ✓ Added user message to diatribe peer${interpretation.extractedFacts.length > 0 ? ` with ${interpretation.extractedFacts.length} facts` : ""}`); + console.log( + `[EmailReply] ✓ Added user message to diatribe peer${interpretation.extractedFacts.length > 0 ? ` with ${interpretation.extractedFacts.length} facts` : ""}`, + ); // Add assistant response to synthesis peer await session.addMessages([ @@ -305,7 +310,9 @@ export const processEmailReply = internalAction({ }, }, ]); - console.log(`[EmailReply] ✓ Added assistant response to synthesis peer`); + console.log( + `[EmailReply] ✓ Added assistant response to synthesis peer`, + ); } catch (error) { console.warn( `[EmailReply] ✗ Failed to update Honcho memory: ${error instanceof Error ? error.message : String(error)}`, @@ -356,6 +363,16 @@ export const processEmailReply = internalAction({ // Step 9: Build and send reply email with proper threading headers console.log("[EmailReply] Step 9: Building and sending reply email..."); + const access = await ctx.runAction( + internal.emailEntitlementsNode.preflightOutboundEmail, + { + userId: user._id, + }, + ); + if (!access.allowed) { + return { success: false, error: access.reason ?? "email_limit_reached" }; + } + const newMessageId = generateMessageId(); const inReplyTo = inboundMessageId; @@ -415,6 +432,15 @@ Sent by Clairvoyant`; resendEmailId, textContent: replyContent, }); + + if (access.trackUsage) { + await ctx.runMutation( + internal.emailEntitlements.incrementOutboundUsage, + { + userId: user._id, + }, + ); + } console.log(`[EmailReply] ✓ Stored outbound message in thread`); const totalTime = Date.now() - startTime; diff --git a/packages/convex/emails/EmailThreadPaywall.tsx b/packages/convex/emails/EmailThreadPaywall.tsx new file mode 100644 index 0000000..e2dd22b --- /dev/null +++ b/packages/convex/emails/EmailThreadPaywall.tsx @@ -0,0 +1,117 @@ +import { + Body, + Button, + Container, + Head, + Heading, + Hr, + Html, + Preview, + Section, + Text, +} from "@react-email/components"; + +interface EmailThreadPaywallEmailProps { + checkoutUrl: string; + limit: number; +} + +export function EmailThreadPaywallEmail({ + checkoutUrl, + limit, +}: EmailThreadPaywallEmailProps) { + return ( + + + Your Clairvoyant email thread limit was reached + + + Email Thread Limit Reached + +
+ + You have reached your free monthly limit of {limit} email thread + messages. + + + Subscribe to continue receiving threaded email responses. + +
+ +
+ +
+ +
+ +
+ + Sent by Clairvoyant +
+ + + ); +} + +const main = { + backgroundColor: "#f6f9fc", + fontFamily: + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif', +}; + +const container = { + backgroundColor: "#ffffff", + margin: "0 auto", + padding: "40px 20px", + maxWidth: "560px", + borderRadius: "8px", +}; + +const heading = { + fontSize: "24px", + fontWeight: "600", + color: "#1a1a1a", + margin: "0 0 24px", + padding: "0", +}; + +const paragraph = { + fontSize: "14px", + lineHeight: "24px", + color: "#333333", + margin: "0 0 16px", + padding: "0", +}; + +const hr = { + borderColor: "#e6e6e6", + margin: "24px 0", +}; + +const buttonContainer = { + textAlign: "center" as const, +}; + +const button = { + backgroundColor: "#1a1a1a", + borderRadius: "6px", + color: "#ffffff", + fontSize: "16px", + fontWeight: "600", + textDecoration: "none", + textAlign: "center" as const, + display: "inline-block", + padding: "12px 24px", +}; + +const footer = { + fontSize: "12px", + color: "#999999", + textAlign: "center" as const, + margin: "0", + padding: "0", +}; + +export default EmailThreadPaywallEmail; diff --git a/packages/convex/emails/OptOutCheckout.tsx b/packages/convex/emails/OptOutCheckout.tsx new file mode 100644 index 0000000..fb5abd5 --- /dev/null +++ b/packages/convex/emails/OptOutCheckout.tsx @@ -0,0 +1,114 @@ +import { + Body, + Button, + Container, + Head, + Heading, + Hr, + Html, + Preview, + Section, + Text, +} from "@react-email/components"; + +interface OptOutCheckoutEmailProps { + checkoutUrl: string; +} + +export function OptOutCheckoutEmail({ checkoutUrl }: OptOutCheckoutEmailProps) { + return ( + + + Enable paid opt-out for Clairvoyant training + + + Opt Out Of Training + +
+ + You requested to opt out of Clairvoyant model training. This is a + paid privacy feature. + + + Activate this subscription and your new conversations will no + longer be logged for training. + +
+ +
+ +
+ +
+ +
+ + Sent by Clairvoyant +
+ + + ); +} + +const main = { + backgroundColor: "#f6f9fc", + fontFamily: + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif', +}; + +const container = { + backgroundColor: "#ffffff", + margin: "0 auto", + padding: "40px 20px", + maxWidth: "560px", + borderRadius: "8px", +}; + +const heading = { + fontSize: "24px", + fontWeight: "600", + color: "#1a1a1a", + margin: "0 0 24px", + padding: "0", +}; + +const paragraph = { + fontSize: "14px", + lineHeight: "24px", + color: "#333333", + margin: "0 0 16px", + padding: "0", +}; + +const hr = { + borderColor: "#e6e6e6", + margin: "24px 0", +}; + +const buttonContainer = { + textAlign: "center" as const, +}; + +const button = { + backgroundColor: "#1a1a1a", + borderRadius: "6px", + color: "#ffffff", + fontSize: "16px", + fontWeight: "600", + textDecoration: "none", + textAlign: "center" as const, + display: "inline-block", + padding: "12px 24px", +}; + +const footer = { + fontSize: "12px", + color: "#999999", + textAlign: "center" as const, + margin: "0", + padding: "0", +}; + +export default OptOutCheckoutEmail; diff --git a/packages/convex/http.ts b/packages/convex/http.ts index cbfddc2..13d7f1d 100644 --- a/packages/convex/http.ts +++ b/packages/convex/http.ts @@ -14,6 +14,7 @@ polar.registerRoutes(http, { event.data.customer?.externalId ?? (metadataUserId ? String(metadataUserId) : undefined); const customerId = event.data.customer?.id; + const productId = event.data.productId; if (!userId) { console.warn( @@ -23,9 +24,23 @@ polar.registerRoutes(http, { } console.log( - `[Polar Webhook] Subscription created for user ${userId}, customer ${customerId}`, + `[Polar Webhook] Subscription created for user ${userId}, customer ${customerId}, product ${productId}`, ); + if (productId === polar.products.optOut) { + await ctx.runMutation(internal.users.setOptOutStatus, { + userId: userId as import("./_generated/dataModel").Id<"users">, + optedOut: true, + }); + } + + if (productId === polar.products.emailThreads) { + await ctx.runMutation(internal.users.setPaidEmailThreadsStatus, { + userId: userId as import("./_generated/dataModel").Id<"users">, + paidEmailThreads: true, + }); + } + await ctx.runMutation( internal.payments.scheduleSubscriptionCreatedHandler, { @@ -34,6 +49,38 @@ polar.registerRoutes(http, { }, ); }, + onSubscriptionUpdated: async (ctx, event) => { + const metadataUserId = event.data.customer?.metadata?.userId; + const userId = + event.data.customer?.externalId ?? + (metadataUserId ? String(metadataUserId) : undefined); + if (!userId) { + return; + } + + const productId = event.data.productId; + const endedStatuses = new Set([ + "canceled", + "past_due", + "unpaid", + "revoked", + ]); + const isActive = !endedStatuses.has(event.data.status); + + if (productId === polar.products.optOut) { + await ctx.runMutation(internal.users.setOptOutStatus, { + userId: userId as import("./_generated/dataModel").Id<"users">, + optedOut: isActive, + }); + } + + if (productId === polar.products.emailThreads) { + await ctx.runMutation(internal.users.setPaidEmailThreadsStatus, { + userId: userId as import("./_generated/dataModel").Id<"users">, + paidEmailThreads: isActive, + }); + } + }, }); http.route({ diff --git a/packages/convex/notes.ts b/packages/convex/notes.ts index 0fe6ada..f239fba 100644 --- a/packages/convex/notes.ts +++ b/packages/convex/notes.ts @@ -44,6 +44,16 @@ export const sendNoteEmail = action({ return { success: false, reason: "no_email_configured" }; } + const access = await ctx.runAction( + internal.emailEntitlementsNode.preflightOutboundEmail, + { + userId: user._id, + }, + ); + if (!access.allowed) { + return { success: false, reason: access.reason ?? "email_limit_reached" }; + } + const sessionDate = new Date().toLocaleDateString("en-US", { weekday: "long", year: "numeric", @@ -93,6 +103,15 @@ export const sendNoteEmail = action({ textContent, }); + if (access.trackUsage) { + await ctx.runMutation( + internal.emailEntitlements.incrementOutboundUsage, + { + userId: user._id, + }, + ); + } + console.log( `[Notes] Email queued successfully to ${user.email} (noteId: ${emailNoteId}, resendId: ${resendEmailId})`, ); diff --git a/packages/convex/optOut.ts b/packages/convex/optOut.ts new file mode 100644 index 0000000..38505de --- /dev/null +++ b/packages/convex/optOut.ts @@ -0,0 +1,52 @@ +"use node"; + +import { render } from "@react-email/render"; +import { v } from "convex/values"; +import { api, internal } from "./_generated/api"; +import { action } from "./_generated/server"; +import { OptOutCheckoutEmail } from "./emails/OptOutCheckout"; +import { resend } from "./resendClient"; + +const EMAIL_DOMAIN = process.env.EMAIL_DOMAIN || "notes.example.com"; + +export const requestOptOutCheckoutEmail = action({ + args: { mentraUserId: v.string() }, + handler: async (ctx, args) => { + const user = await ctx.runQuery(api.users.getByMentraId, { + mentraUserId: args.mentraUserId, + }); + + if (!user) { + return { success: false as const, reason: "user_not_found" }; + } + + if (!user.email) { + return { success: false as const, reason: "no_email_configured" }; + } + + if (user.optedOutOfTraining) { + return { success: true as const, alreadyOptedOut: true }; + } + + const checkout = await ctx.runAction( + internal.payments.createFeatureCheckoutLinkInternal, + { + userId: user._id, + feature: "optOut", + }, + ); + + const html = await render( + OptOutCheckoutEmail({ checkoutUrl: checkout.url }), + ); + + await resend.sendEmail(ctx, { + from: `Clairvoyant `, + to: user.email, + subject: "Complete your paid opt-out setup", + html, + }); + + return { success: true as const, alreadyOptedOut: false }; + }, +}); diff --git a/packages/convex/package.json b/packages/convex/package.json index e98d117..dcc8a44 100644 --- a/packages/convex/package.json +++ b/packages/convex/package.json @@ -17,17 +17,17 @@ "@convex-dev/resend": "^0.2.3", "@honcho-ai/sdk": "^1.6.0", "@polar-sh/sdk": "^0.41.5", - "@react-email/components": "^1.0.2", - "@react-email/render": "^2.0.0", - "convex": "^1.31.2", + "@react-email/components": "^1.0.8", + "@react-email/render": "^2.0.4", + "convex": "^1.32.0", "groq-sdk": "^0.18.0", - "react": "^19.2.3", - "react-dom": "^19.2.3", - "react-email": "^5.1.0", - "svix": "^1.82.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "react-email": "^5.2.8", + "svix": "^1.86.0", "zod": "^3.25.76" }, "devDependencies": { - "@types/react": "^19.2.3" + "@types/react": "^19.2.14" } } diff --git a/packages/convex/payments.ts b/packages/convex/payments.ts index bfb939a..7a2e454 100644 --- a/packages/convex/payments.ts +++ b/packages/convex/payments.ts @@ -10,6 +10,12 @@ import { query, } from "./_generated/server"; +const DEFAULT_SETTINGS_URL = process.env.WEB_APP_URL + ? `${process.env.WEB_APP_URL.replace(/\/$/, "")}/settings` + : "https://clairvoyant.app/settings"; + +type PaidFeatureProduct = "optOut" | "emailThreads"; + // ============================================================================= // Polar Types (inferred from polar.listProducts return type) // ============================================================================= @@ -69,6 +75,10 @@ export type PolarProduct = { // ============================================================================= export const polar = new Polar(components.polar, { + products: { + optOut: process.env.POLAR_OPT_OUT_PRODUCT_ID ?? "", + emailThreads: process.env.POLAR_EMAIL_THREADS_PRODUCT_ID ?? "", + }, getUserInfo: async (ctx): Promise<{ userId: Id<"users">; email: string }> => { const user = await ctx.runQuery(api.users.getCurrentUser); return { @@ -190,6 +200,32 @@ export const getCustomerInfo = action({ }, }); +export const createFeatureCheckoutLink = action({ + args: { + mentraUserId: v.string(), + feature: v.union(v.literal("optOut"), v.literal("emailThreads")), + successUrl: v.optional(v.string()), + }, + handler: async (ctx, args): Promise<{ url: string }> => { + const user = await ctx.runQuery(api.users.getByMentraId, { + mentraUserId: args.mentraUserId, + }); + + if (!user) { + throw new Error("User not found"); + } + + return await ctx.runAction( + internal.payments.createFeatureCheckoutLinkInternal, + { + userId: user._id, + feature: args.feature, + successUrl: args.successUrl, + }, + ); + }, +}); + // ============================================================================= // Internal Mutations // ============================================================================= @@ -312,3 +348,60 @@ export const handleSubscriptionCreated = internalAction({ } }, }); + +export const createFeatureCheckoutLinkInternal = internalAction({ + args: { + userId: v.id("users"), + feature: v.union(v.literal("optOut"), v.literal("emailThreads")), + successUrl: v.optional(v.string()), + }, + handler: async (ctx, args): Promise<{ url: string }> => { + const user = await ctx.runQuery(internal.users.getByIdInternal, { + userId: args.userId, + }); + if (!user) { + throw new Error("User not found"); + } + + const accessToken = + process.env.POLAR_ACCESS_TOKEN ?? process.env.POLAR_ORGANIZATION_TOKEN; + if (!accessToken) { + throw new Error( + "POLAR_ACCESS_TOKEN or POLAR_ORGANIZATION_TOKEN environment variable is not set", + ); + } + + const productId = getFeatureProductId(args.feature); + if (!productId) { + throw new Error( + `Polar product is not configured for feature: ${args.feature}`, + ); + } + + const polarSDK = new PolarSDK({ + accessToken, + server: process.env.POLAR_SERVER as "production" | "sandbox" | undefined, + }); + + const checkout = await polarSDK.checkouts.create({ + products: [productId], + externalCustomerId: user._id, + customerEmail: user.email, + successUrl: args.successUrl ?? DEFAULT_SETTINGS_URL, + metadata: { + userId: user._id, + feature: args.feature, + }, + }); + + return { url: checkout.url }; + }, +}); + +function getFeatureProductId(feature: PaidFeatureProduct): string { + if (feature === "optOut") { + return polar.products.optOut; + } + + return polar.products.emailThreads; +} diff --git a/packages/convex/schema.ts b/packages/convex/schema.ts index ecd86a0..f92f9db 100644 --- a/packages/convex/schema.ts +++ b/packages/convex/schema.ts @@ -6,6 +6,8 @@ export default defineSchema({ mentraUserId: v.string(), mentraToken: v.optional(v.string()), email: v.optional(v.string()), + optedOutOfTraining: v.optional(v.boolean()), + paidEmailThreads: v.optional(v.boolean()), billingName: v.optional(v.string()), billingAddress: v.optional( v.object({ @@ -91,6 +93,14 @@ export default defineSchema({ }) .index("by_email_note", ["emailNoteId"]) .index("by_resend_email_id", ["resendEmailId"]), + emailThreadUsage: defineTable({ + userId: v.id("users"), + periodKey: v.string(), + outboundCount: v.number(), + paywallEmailSentAt: v.optional(v.string()), + }) + .index("by_user", ["userId"]) + .index("by_user_period", ["userId", "periodKey"]), chatMessages: defineTable({ userId: v.id("users"), dailySummaryId: v.optional(v.id("dailySummaries")), @@ -140,4 +150,14 @@ export default defineSchema({ content: v.string(), createdAt: v.string(), }).index("by_followup", ["followupId"]), + conversationLogs: defineTable({ + userId: v.id("users"), + sessionId: v.string(), + transcript: v.string(), + route: v.string(), + response: v.optional(v.string()), + }) + .index("by_user", ["userId"]) + .index("by_session", ["sessionId"]) + .index("by_route", ["route"]), }); diff --git a/packages/convex/tsconfig.json b/packages/convex/tsconfig.json index a84f928..575c600 100644 --- a/packages/convex/tsconfig.json +++ b/packages/convex/tsconfig.json @@ -10,6 +10,7 @@ "moduleResolution": "Bundler", "jsx": "react-jsx", "skipLibCheck": true, + "types": [], "allowSyntheticDefaultImports": true, /* These compiler options are required by Convex */ diff --git a/packages/convex/users.ts b/packages/convex/users.ts index 6c0b25b..880ac6d 100644 --- a/packages/convex/users.ts +++ b/packages/convex/users.ts @@ -96,6 +96,26 @@ export const getEmail = query({ }, }); +export const getOptOutStatus = query({ + args: { mentraUserId: v.string() }, + handler: async (ctx, args) => { + const user = await getByMentraIdInternal(ctx, args.mentraUserId); + return { + optedOut: user?.optedOutOfTraining ?? false, + }; + }, +}); + +export const getEmailThreadsPaidStatus = query({ + args: { mentraUserId: v.string() }, + handler: async (ctx, args) => { + const user = await getByMentraIdInternal(ctx, args.mentraUserId); + return { + paidEmailThreads: user?.paidEmailThreads ?? false, + }; + }, +}); + // ============================================================================= // Public Queries - Preferences // ============================================================================= @@ -164,9 +184,11 @@ export const getOrCreate = mutation({ if (existing) { return existing._id; } + const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(args.mentraUserId); const userId = await ctx.db.insert("users", { mentraUserId: args.mentraUserId, mentraToken: args.mentraToken, + ...(isEmail ? { email: args.mentraUserId } : {}), }); await ctx.db.insert("preferences", { @@ -405,3 +427,44 @@ export const updateDefaultLocation = internalMutation({ }); }, }); + +export const setOptOutStatus = internalMutation({ + args: { + userId: v.id("users"), + optedOut: v.boolean(), + }, + handler: async (ctx, args) => { + await ctx.db.patch(args.userId, { + optedOutOfTraining: args.optedOut, + }); + return { success: true }; + }, +}); + +export const backfillEmailsFromMentraId = internalMutation({ + handler: async (ctx) => { + const users = await ctx.db.query("users").collect(); + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + let updated = 0; + for (const user of users) { + if (!user.email && emailRegex.test(user.mentraUserId)) { + await ctx.db.patch(user._id, { email: user.mentraUserId }); + updated++; + } + } + return { updated, total: users.length }; + }, +}); + +export const setPaidEmailThreadsStatus = internalMutation({ + args: { + userId: v.id("users"), + paidEmailThreads: v.boolean(), + }, + handler: async (ctx, args) => { + await ctx.db.patch(args.userId, { + paidEmailThreads: args.paidEmailThreads, + }); + return { success: true }; + }, +});