From 521a87cda6fea33d740275f71d4a1c8f7285bb64 Mon Sep 17 00:00:00 2001 From: Ben Davis Date: Fri, 23 Jan 2026 17:44:48 -0800 Subject: [PATCH 1/4] plan put together --- RAYCAST-EXTENSION.md | 1058 ++++++++++++++++++++++++++++++++++++++++++ btca.config.jsonc | 7 + 2 files changed, 1065 insertions(+) create mode 100644 RAYCAST-EXTENSION.md diff --git a/RAYCAST-EXTENSION.md b/RAYCAST-EXTENSION.md new file mode 100644 index 00000000..0d1f0c94 --- /dev/null +++ b/RAYCAST-EXTENSION.md @@ -0,0 +1,1058 @@ +# RayCast Extension Implementation Plan + +This document provides a detailed implementation plan for creating a RayCast extension for Better Context (btca). The extension allows users to ask questions with `@resource` tagging directly from RayCast. + +## Table of Contents + +1. [Overview](#overview) +2. [Architecture](#architecture) +3. [Prerequisites](#prerequisites) +4. [Part 1: Convex HTTP Endpoints](#part-1-convex-http-endpoints) +5. [Part 2: RayCast Extension Setup](#part-2-raycast-extension-setup) +6. [Part 3: RayCast Extension Implementation](#part-3-raycast-extension-implementation) +7. [Testing](#testing) +8. [Error Handling Reference](#error-handling-reference) + +--- + +## Overview + +### What We're Building + +A RayCast extension with a single command that: + +1. Opens a text input where users type questions with `@resource` syntax +2. Streams the AI response in real-time +3. Displays the final answer as markdown + +### Key Design Decisions + +| Decision | Choice | Rationale | +| ------------------ | -------------------------- | --------------------------------------------------------- | +| Authentication | API Key | Simpler than OAuth, user manages key | +| Thread Management | None (ephemeral) | Keep it simple, one-off questions | +| Resource Caching | None | Fetch on open, fast enough | +| Data Fetching | HTTP endpoints | Convex stays in apps/web, no WebSocket support in RayCast | +| Resource Selection | `@resource` syntax in text | MVP approach, no dynamic dropdown | + +### Convex URL + +``` +https://greedy-partridge-784.convex.site +``` + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ RayCast Extension │ +│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ +│ │ Preferences │───►│ Form View │───►│ Detail View │ │ +│ │ (API Key) │ │ (Question) │ │ (Response) │ │ +│ └─────────────┘ └──────────────┘ └───────────────┘ │ +└─────────────────────────┬───────────────────────────────────┘ + │ HTTP + API Key Auth + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Convex HTTP Endpoints │ +│ ┌──────────────────────┐ ┌────────────────────────────┐ │ +│ │ GET /raycast/resources│ │ POST /raycast/ask (SSE) │ │ +│ └──────────────────────┘ └────────────────────────────┘ │ +└─────────────────────────┬───────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ btca Sandbox (Daytona) │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## Prerequisites + +- Node.js 18+ +- Bun (for package management) +- RayCast installed on macOS +- Access to the Better Context Convex deployment + +--- + +## Part 1: Convex HTTP Endpoints + +These endpoints live in `apps/web/src/convex/http.ts`. + +### 1.1 API Key Authentication Helper + +Create a helper to validate API keys and return the associated instance. + +**File: `apps/web/src/convex/raycastAuth.ts`** + +```typescript +import { ActionCtx } from './_generated/server'; +import { api } from './_generated/api'; +import type { Doc } from './_generated/dataModel'; + +export type RaycastAuthResult = { + instance: Doc<'instances'>; + apiKey: Doc<'apiKeys'>; +}; + +export type RaycastAuthError = { + status: number; + message: string; +}; + +export async function authenticateRaycastRequest( + ctx: ActionCtx, + request: Request +): Promise { + const authHeader = request.headers.get('Authorization'); + + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return { status: 401, message: 'Missing or invalid Authorization header' }; + } + + const apiKeyValue = authHeader.slice(7); // Remove 'Bearer ' + + if (!apiKeyValue) { + return { status: 401, message: 'API key is required' }; + } + + // Look up the API key + const apiKey = await ctx.runQuery(api.apiKeys.getByKey, { key: apiKeyValue }); + + if (!apiKey) { + return { status: 401, message: 'Invalid API key' }; + } + + // Check if key is active + if (apiKey.status !== 'active') { + return { status: 401, message: 'API key is inactive' }; + } + + // Get the associated instance + const instance = await ctx.runQuery(api.instances.queries.get, { + id: apiKey.instanceId + }); + + if (!instance) { + return { status: 404, message: 'Instance not found' }; + } + + return { instance, apiKey }; +} + +export function isAuthError( + result: RaycastAuthResult | RaycastAuthError +): result is RaycastAuthError { + return 'status' in result && 'message' in result; +} +``` + +### 1.2 GET /raycast/resources Endpoint + +Returns all available resources for the authenticated user. + +**Add to `apps/web/src/convex/http.ts`:** + +```typescript +import { authenticateRaycastRequest, isAuthError } from './raycastAuth'; + +const raycastResources = httpAction(async (ctx, request) => { + // Authenticate + const authResult = await authenticateRaycastRequest(ctx, request); + + if (isAuthError(authResult)) { + return new Response(JSON.stringify({ error: authResult.message }), { + status: authResult.status, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { instance } = authResult; + + // Fetch resources + const resources = await ctx.runQuery(api.resources.listAvailable, { + instanceId: instance._id + }); + + // Flatten and format for RayCast + const allResources = [ + ...resources.global.map((r) => ({ + name: r.name, + displayName: r.displayName, + isGlobal: true + })), + ...resources.custom.map((r) => ({ + name: r.name, + displayName: r.displayName, + isGlobal: false + })) + ]; + + return new Response(JSON.stringify({ resources: allResources }), { + status: 200, + headers: { 'Content-Type': 'application/json' } + }); +}); + +// Register the route +http.route({ + path: '/raycast/resources', + method: 'GET', + handler: raycastResources +}); +``` + +### 1.3 POST /raycast/ask Endpoint (SSE Streaming) + +Handles questions with `@resource` syntax, streams responses. + +**Add to `apps/web/src/convex/http.ts`:** + +```typescript +import { z } from 'zod'; + +const raycastAskRequestSchema = z.object({ + question: z.string().min(1) +}); + +// Helper to extract @resource mentions from question +function extractResources(question: string): { cleanQuestion: string; resources: string[] } { + const resourcePattern = /@(\w+)/g; + const resources: string[] = []; + let match; + + while ((match = resourcePattern.exec(question)) !== null) { + resources.push(match[1]); + } + + // Remove @mentions from question for cleaner display (optional) + const cleanQuestion = question; // Keep original, resources are contextual + + return { cleanQuestion, resources: [...new Set(resources)] }; +} + +const raycastAsk = httpAction(async (ctx, request) => { + // Authenticate + const authResult = await authenticateRaycastRequest(ctx, request); + + if (isAuthError(authResult)) { + return new Response(JSON.stringify({ error: authResult.message }), { + status: authResult.status, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { instance } = authResult; + + // Parse request body + let rawBody: unknown; + try { + rawBody = await request.json(); + } catch { + return new Response(JSON.stringify({ error: 'Invalid request body' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + const parseResult = raycastAskRequestSchema.safeParse(rawBody); + if (!parseResult.success) { + return new Response(JSON.stringify({ error: 'Invalid request: question is required' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { question } = parseResult.data; + const { resources } = extractResources(question); + + // Check usage/subscription + const usageCheck = await ctx.runAction(api.usage.ensureUsageAvailable, { + instanceId: instance._id, + question, + resources + }); + + if (!usageCheck?.ok) { + const reason = (usageCheck as { reason?: string }).reason; + if (reason === 'subscription_required') { + return new Response( + JSON.stringify({ + error: 'Subscription required', + upgradeUrl: 'https://btca.dev/pricing' + }), + { status: 402, headers: { 'Content-Type': 'application/json' } } + ); + } + if (reason === 'free_limit_reached') { + return new Response( + JSON.stringify({ + error: 'Free message limit reached. Upgrade to continue.', + upgradeUrl: 'https://btca.dev/pricing' + }), + { status: 402, headers: { 'Content-Type': 'application/json' } } + ); + } + return new Response(JSON.stringify({ error: 'Usage limit reached' }), { + status: 402, + headers: { 'Content-Type': 'application/json' } + }); + } + + // Ensure instance is running + if (instance.state !== 'running' || !instance.serverUrl) { + if (!instance.sandboxId) { + return new Response( + JSON.stringify({ error: 'Instance not provisioned. Please visit btca.dev to set up.' }), + { status: 503, headers: { 'Content-Type': 'application/json' } } + ); + } + + // Wake the instance + try { + const wakeResult = await ctx.runAction(api.instances.actions.wake, { + instanceId: instance._id + }); + if (!wakeResult.serverUrl) { + throw new Error('No server URL returned'); + } + // Update instance reference + instance.serverUrl = wakeResult.serverUrl; + instance.state = 'running'; + } catch (error) { + return new Response(JSON.stringify({ error: 'Failed to start instance. Try again.' }), { + status: 503, + headers: { 'Content-Type': 'application/json' } + }); + } + } + + // Create SSE stream + const encoder = new TextEncoder(); + + const stream = new ReadableStream({ + async start(controller) { + const sendEvent = (data: unknown) => { + controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)); + }; + + try { + // Call btca server + const response = await fetch(`${instance.serverUrl}/question/stream`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + question, + resources, + quiet: true + }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(errorText || `Server error: ${response.status}`); + } + + if (!response.body) { + throw new Error('No response body'); + } + + // Stream through the response + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() ?? ''; + + let eventData = ''; + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } else if (line === '' && eventData) { + try { + const event = JSON.parse(eventData); + + // Forward relevant events to RayCast + if (event.type === 'text.delta') { + sendEvent({ type: 'text', delta: event.delta }); + } else if (event.type === 'done') { + sendEvent({ type: 'done', text: event.text }); + } else if (event.type === 'error') { + sendEvent({ type: 'error', message: event.message }); + } + // Skip meta, reasoning, tool events for simplicity + } catch { + // Ignore parse errors + } + eventData = ''; + } + } + } + + reader.releaseLock(); + + // Finalize usage + await ctx.runAction(api.usage.finalizeUsage, { + instanceId: instance._id, + questionTokens: 0, // Simplified for RayCast + outputChars: 0, + reasoningChars: 0, + resources, + sandboxUsageHours: 0 + }); + + controller.close(); + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + sendEvent({ type: 'error', message }); + controller.close(); + } + } + }); + + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive' + } + }); +}); + +// Register routes +http.route({ + path: '/raycast/ask', + method: 'POST', + handler: raycastAsk +}); + +http.route({ + path: '/raycast/ask', + method: 'OPTIONS', + handler: corsPreflight +}); + +http.route({ + path: '/raycast/resources', + method: 'OPTIONS', + handler: corsPreflight +}); +``` + +--- + +## Part 2: RayCast Extension Setup + +### 2.1 Create the Extension + +Use the official RayCast CLI to scaffold the project: + +```bash +# Navigate to apps directory +cd apps + +# Create the extension using the official CLI +# Using 'submit-form' template as base since we need a form +npx create-raycast-extension -t submit-form -o raycast + +# Navigate into the new extension +cd raycast +``` + +### 2.2 Update package.json + +After scaffolding, update the `package.json` with the correct metadata: + +```json +{ + "$schema": "https://www.raycast.com/schemas/extension.json", + "name": "better-context", + "title": "Better Context", + "description": "Ask questions about documentation with AI-powered context", + "icon": "icon.png", + "author": "btca", + "license": "MIT", + "commands": [ + { + "name": "ask", + "title": "Ask Question", + "description": "Ask a question with @resource tagging", + "mode": "view" + } + ], + "preferences": [ + { + "name": "apiKey", + "type": "password", + "required": true, + "title": "API Key", + "description": "Your Better Context API key. Get one at btca.dev/app/settings", + "placeholder": "btca_..." + } + ], + "dependencies": { + "@raycast/api": "^1.94.0", + "@raycast/utils": "^1.19.1" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.4", + "@types/node": "22.13.10", + "@types/react": "19.0.12", + "eslint": "^9.22.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2" + }, + "scripts": { + "build": "ray build", + "dev": "ray develop", + "fix-lint": "ray lint --fix", + "lint": "ray lint", + "prepublishOnly": "echo \"\\n\\nIt seems like you are trying to publish the Raycast extension to npm.\\n\\nIf you did intend to publish it to npm, remove the \\`prepublishOnly\\` script and rerun \\`npm publish\\` again.\\nIf you wanted to publish it to the Raycast Store instead, use \\`npm run publish\\` instead.\\n\\n\" && exit 1", + "publish": "npx @raycast/api@latest publish" + } +} +``` + +### 2.3 Install Dependencies with Bun + +```bash +# Remove node_modules and lock file if they exist +rm -rf node_modules package-lock.json + +# Install dependencies with Bun +bun install + +# Add Zod 4 for response validation +bun add zod@^3.24.0 +``` + +> Note: As of January 2025, Zod 4 is in beta. Using latest Zod 3.x which is stable. Update to Zod 4 when it's released. + +### 2.4 Project Structure + +After setup, ensure this structure: + +``` +apps/raycast/ +├── assets/ +│ └── icon.png # Add your icon (512x512) +├── src/ +│ ├── ask.tsx # Main command (rename from index.tsx) +│ ├── api.ts # HTTP client +│ ├── stream.ts # SSE parser +│ └── types.ts # Type definitions +├── package.json +├── tsconfig.json +├── eslint.config.mjs +└── bun.lockb +``` + +--- + +## Part 3: RayCast Extension Implementation + +### 3.1 Types (`src/types.ts`) + +```typescript +import { z } from 'zod'; + +// API Response types +export const ResourceSchema = z.object({ + name: z.string(), + displayName: z.string(), + isGlobal: z.boolean() +}); + +export const ResourcesResponseSchema = z.object({ + resources: z.array(ResourceSchema) +}); + +export type Resource = z.infer; +export type ResourcesResponse = z.infer; + +// Stream event types +export const StreamEventSchema = z.discriminatedUnion('type', [ + z.object({ + type: z.literal('text'), + delta: z.string() + }), + z.object({ + type: z.literal('done'), + text: z.string() + }), + z.object({ + type: z.literal('error'), + message: z.string() + }) +]); + +export type StreamEvent = z.infer; + +// Error response +export const ErrorResponseSchema = z.object({ + error: z.string(), + upgradeUrl: z.string().optional() +}); + +export type ErrorResponse = z.infer; +``` + +### 3.2 API Client (`src/api.ts`) + +```typescript +import { getPreferenceValues } from '@raycast/api'; +import { ResourcesResponseSchema, type ResourcesResponse } from './types'; + +const CONVEX_URL = 'https://greedy-partridge-784.convex.site'; + +interface Preferences { + apiKey: string; +} + +function getApiKey(): string { + const preferences = getPreferenceValues(); + return preferences.apiKey; +} + +function getHeaders(): HeadersInit { + return { + Authorization: `Bearer ${getApiKey()}`, + 'Content-Type': 'application/json' + }; +} + +export async function fetchResources(): Promise { + const response = await fetch(`${CONVEX_URL}/raycast/resources`, { + method: 'GET', + headers: getHeaders() + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ error: 'Unknown error' })); + throw new ApiError( + response.status, + error.error || 'Failed to fetch resources', + error.upgradeUrl + ); + } + + const data = await response.json(); + return ResourcesResponseSchema.parse(data); +} + +export async function askQuestion(question: string): Promise { + const response = await fetch(`${CONVEX_URL}/raycast/ask`, { + method: 'POST', + headers: getHeaders(), + body: JSON.stringify({ question }) + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ error: 'Unknown error' })); + throw new ApiError(response.status, error.error || 'Request failed', error.upgradeUrl); + } + + return response; +} + +export class ApiError extends Error { + constructor( + public status: number, + message: string, + public upgradeUrl?: string + ) { + super(message); + this.name = 'ApiError'; + } +} +``` + +### 3.3 SSE Stream Parser (`src/stream.ts`) + +```typescript +import { StreamEventSchema, type StreamEvent } from './types'; + +export async function* parseSSEStream(response: Response): AsyncGenerator { + if (!response.body) { + throw new Error('Response body is null'); + } + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() ?? ''; + + let eventData = ''; + + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } else if (line === '' && eventData) { + try { + const parsed = JSON.parse(eventData); + const validated = StreamEventSchema.parse(parsed); + yield validated; + } catch (error) { + console.error('Failed to parse SSE event:', error); + } + eventData = ''; + } + } + } + + // Process remaining buffer + if (buffer.trim()) { + const lines = buffer.split('\n'); + let eventData = ''; + + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } + } + + if (eventData) { + try { + const parsed = JSON.parse(eventData); + const validated = StreamEventSchema.parse(parsed); + yield validated; + } catch { + // Ignore incomplete final event + } + } + } + } finally { + reader.releaseLock(); + } +} +``` + +### 3.4 Main Command (`src/ask.tsx`) + +```typescript +import { + Action, + ActionPanel, + Detail, + Form, + getPreferenceValues, + openExtensionPreferences, + showToast, + Toast, + useNavigation +} from '@raycast/api'; +import { usePromise } from '@raycast/utils'; +import { useState } from 'react'; +import { askQuestion, fetchResources, ApiError } from './api'; +import { parseSSEStream } from './stream'; +import type { Resource } from './types'; + +interface Preferences { + apiKey: string; +} + +export default function AskCommand() { + const [question, setQuestion] = useState(''); + const { push } = useNavigation(); + + // Fetch resources on mount (for future autocomplete hints) + const { data: resourcesData, isLoading: isLoadingResources } = usePromise( + async () => { + try { + return await fetchResources(); + } catch (error) { + if (error instanceof ApiError) { + handleApiError(error); + } + return null; + } + }, + [] + ); + + const handleSubmit = async (values: { question: string }) => { + if (!values.question.trim()) { + showToast({ + style: Toast.Style.Failure, + title: 'Question required', + message: 'Please enter a question' + }); + return; + } + + push(); + }; + + const resourceNames = resourcesData?.resources.map(r => r.name) ?? []; + const resourceHint = resourceNames.length > 0 + ? `Available: ${resourceNames.slice(0, 5).map(n => `@${n}`).join(', ')}${resourceNames.length > 5 ? '...' : ''}` + : ''; + + return ( +
+ + + + } + > + + + + ); +} + +function ResponseView({ question }: { question: string }) { + const [markdown, setMarkdown] = useState(''); + const [isComplete, setIsComplete] = useState(false); + + const { isLoading, error } = usePromise( + async () => { + try { + const response = await askQuestion(question); + + for await (const event of parseSSEStream(response)) { + if (event.type === 'text') { + setMarkdown(prev => prev + event.delta); + } else if (event.type === 'done') { + setMarkdown(event.text); + setIsComplete(true); + } else if (event.type === 'error') { + throw new Error(event.message); + } + } + } catch (error) { + if (error instanceof ApiError) { + handleApiError(error); + } + throw error; + } + }, + [] + ); + + const displayMarkdown = markdown || (isLoading ? '*Thinking...*' : ''); + + return ( + + + + ) : undefined + } + actions={ + + + + + } + /> + ); +} + +function handleApiError(error: ApiError) { + if (error.status === 401) { + showToast({ + style: Toast.Style.Failure, + title: 'Invalid API Key', + message: 'Check your API key in extension preferences', + primaryAction: { + title: 'Open Preferences', + onAction: () => openExtensionPreferences() + } + }); + } else if (error.status === 402) { + showToast({ + style: Toast.Style.Failure, + title: 'Subscription Required', + message: error.message, + primaryAction: error.upgradeUrl ? { + title: 'Upgrade', + onAction: () => { + // Open upgrade URL + import('@raycast/api').then(({ open }) => { + open(error.upgradeUrl!); + }); + } + } : undefined + }); + } else if (error.status === 503) { + showToast({ + style: Toast.Style.Failure, + title: 'Service Unavailable', + message: error.message + }); + } else { + showToast({ + style: Toast.Style.Failure, + title: 'Error', + message: error.message + }); + } +} +``` + +### 3.5 Update tsconfig.json + +Ensure the TypeScript config supports the project: + +```json +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node 20", + "include": ["src/**/*"], + "compilerOptions": { + "lib": ["ES2022"], + "module": "CommonJS", + "target": "ES2022", + "strict": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react-jsx", + "moduleResolution": "node", + "resolveJsonModule": true + } +} +``` + +--- + +## Testing + +### Local Development + +```bash +cd apps/raycast + +# Start development mode +bun run dev +``` + +This will: + +1. Build the extension +2. Register it with RayCast +3. Enable hot reloading + +### Test Scenarios + +1. **No API Key**: Should prompt to open preferences +2. **Invalid API Key**: Should show "Invalid API key" toast +3. **No Subscription**: Should show upgrade prompt with link +4. **Valid Request**: Should stream response +5. **Network Error**: Should show error toast + +### Manual Testing Checklist + +- [ ] Extension appears in RayCast search +- [ ] API key preference works +- [ ] Resources fetch on open +- [ ] Question submission works +- [ ] SSE streaming displays correctly +- [ ] Copy/paste actions work +- [ ] Error states handled gracefully + +--- + +## Error Handling Reference + +| HTTP Status | Error | User Message | Action | +| ----------- | ------------------------ | --------------------------------- | --------------------- | +| 401 | Invalid/missing API key | "Invalid API key" | Open preferences | +| 402 | Subscription required | "Subscription required" | Open btca.dev/pricing | +| 402 | Free limit reached | "Free limit reached" | Open btca.dev/pricing | +| 503 | Instance not provisioned | "Please visit btca.dev to set up" | Open btca.dev | +| 503 | Instance wake failed | "Failed to start. Try again." | Retry | +| 5xx | Server error | "Something went wrong" | Retry | + +--- + +## Future Enhancements (Out of Scope for MVP) + +1. **Resource Autocomplete**: Show dropdown as user types `@` +2. **Conversation History**: Optional thread persistence +3. **Multiple Commands**: Separate commands for different use cases +4. **Keyboard Shortcuts**: Quick actions for common tasks +5. **Caching**: Cache resources for faster startup + +--- + +## Quick Reference + +### Commands + +```bash +# Development +cd apps/raycast && bun run dev + +# Build +bun run build + +# Lint +bun run lint + +# Fix lint issues +bun run fix-lint +``` + +### API Endpoints + +| Endpoint | Method | Auth | Description | +| -------------------- | ------ | ------- | ------------------------ | +| `/raycast/resources` | GET | API Key | List available resources | +| `/raycast/ask` | POST | API Key | Stream AI response | + +### Environment + +- **Convex URL**: `https://greedy-partridge-784.convex.site` +- **Web App**: `https://btca.dev` +- **Pricing Page**: `https://btca.dev/pricing` diff --git a/btca.config.jsonc b/btca.config.jsonc index 75386696..1eb44b41 100644 --- a/btca.config.jsonc +++ b/btca.config.jsonc @@ -7,6 +7,13 @@ "url": "https://github.com/svecosystem/runed", "branch": "main" }, + { + "type": "git", + "name": "raycast", + "url": "https://github.com/raycast/extensions", + "branch": "main", + "searchPaths": ["docs", "examples"] + }, { "type": "git", "name": "autumn", From 5eca84254518c520a9337562136997b4a178bd8c Mon Sep 17 00:00:00 2001 From: Ben Davis Date: Fri, 23 Jan 2026 17:45:09 -0800 Subject: [PATCH 2/4] plan put together --- RAYCAST-EXTENSION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RAYCAST-EXTENSION.md b/RAYCAST-EXTENSION.md index 0d1f0c94..e105e05b 100644 --- a/RAYCAST-EXTENSION.md +++ b/RAYCAST-EXTENSION.md @@ -2,6 +2,8 @@ This document provides a detailed implementation plan for creating a RayCast extension for Better Context (btca). The extension allows users to ask questions with `@resource` tagging directly from RayCast. +Use btca as much as you need to, you can see what resources you have in btca.config.jsonc. + ## Table of Contents 1. [Overview](#overview) From 7ad6fc354fd639b5946a8519ac995e9122c6ed21 Mon Sep 17 00:00:00 2001 From: Ben Davis Date: Fri, 23 Jan 2026 18:02:07 -0800 Subject: [PATCH 3/4] raycast first exploration done, needs ui pass --- apps/raycast/assets/icon.png | Bin 0 -> 76790 bytes apps/raycast/eslint.config.js | 4 + apps/raycast/package.json | 48 +++ apps/raycast/raycast-env.d.ts | 27 ++ apps/raycast/src/api.ts | 71 ++++ apps/raycast/src/ask.tsx | 181 ++++++++++ apps/raycast/src/stream.ts | 63 ++++ apps/raycast/src/types.ts | 41 +++ apps/raycast/tsconfig.json | 18 + apps/web/src/convex/_generated/api.d.ts | 4 + apps/web/src/convex/apiKeys.ts | 23 ++ apps/web/src/convex/http.ts | 280 +++++++++++++++ apps/web/src/convex/raycastAuth.ts | 64 ++++ apps/web/src/convex/raycastUsage.ts | 447 ++++++++++++++++++++++++ bun.lock | 404 +++++++++++++++++++-- 15 files changed, 1640 insertions(+), 35 deletions(-) create mode 100644 apps/raycast/assets/icon.png create mode 100644 apps/raycast/eslint.config.js create mode 100644 apps/raycast/package.json create mode 100644 apps/raycast/raycast-env.d.ts create mode 100644 apps/raycast/src/api.ts create mode 100644 apps/raycast/src/ask.tsx create mode 100644 apps/raycast/src/stream.ts create mode 100644 apps/raycast/src/types.ts create mode 100644 apps/raycast/tsconfig.json create mode 100644 apps/web/src/convex/raycastAuth.ts create mode 100644 apps/web/src/convex/raycastUsage.ts diff --git a/apps/raycast/assets/icon.png b/apps/raycast/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..600b07c6e9494cc26b051c2ed73a83310d3ade95 GIT binary patch literal 76790 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 literal 0 HcmV?d00001 diff --git a/apps/raycast/eslint.config.js b/apps/raycast/eslint.config.js new file mode 100644 index 00000000..e5fc222f --- /dev/null +++ b/apps/raycast/eslint.config.js @@ -0,0 +1,4 @@ +const { defineConfig } = require('eslint/config'); +const raycastConfig = require('@raycast/eslint-config'); + +module.exports = defineConfig([...raycastConfig]); diff --git a/apps/raycast/package.json b/apps/raycast/package.json new file mode 100644 index 00000000..24be5dd4 --- /dev/null +++ b/apps/raycast/package.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://www.raycast.com/schemas/extension.json", + "name": "better-context", + "title": "Better Context", + "description": "Ask questions about documentation with AI-powered context", + "icon": "icon.png", + "author": "anomalyco", + "license": "MIT", + "commands": [ + { + "name": "ask", + "title": "Ask Question", + "description": "Ask a question with @resource tagging", + "mode": "view" + } + ], + "preferences": [ + { + "name": "apiKey", + "type": "password", + "required": true, + "title": "API Key", + "description": "Your Better Context API key. Get one at btca.dev/app/settings", + "placeholder": "btca_..." + } + ], + "dependencies": { + "@raycast/api": "^1.94.0", + "@raycast/utils": "^1.19.1", + "zod": "^3.24.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.4", + "@types/node": "22.13.10", + "@types/react": "19.0.12", + "eslint": "^9.22.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2" + }, + "scripts": { + "build": "ray build", + "dev": "ray develop", + "fix-lint": "ray lint --fix", + "lint": "ray lint", + "prepublishOnly": "echo \"\\n\\nIt seems like you are trying to publish the Raycast extension to npm.\\n\\nIf you did intend to publish it to npm, remove the \\`prepublishOnly\\` script and rerun \\`npm publish\\` again.\\nIf you wanted to publish it to the Raycast Store instead, use \\`npm run publish\\` instead.\\n\\n\" && exit 1", + "publish": "npx @raycast/api@latest publish" + } +} diff --git a/apps/raycast/raycast-env.d.ts b/apps/raycast/raycast-env.d.ts new file mode 100644 index 00000000..b8013089 --- /dev/null +++ b/apps/raycast/raycast-env.d.ts @@ -0,0 +1,27 @@ +/// + +/* 🚧 🚧 🚧 + * This file is auto-generated from the extension's manifest. + * Do not modify manually. Instead, update the `package.json` file. + * 🚧 🚧 🚧 */ + +/* eslint-disable @typescript-eslint/ban-types */ + +type ExtensionPreferences = { + /** API Key - Your Better Context API key. Get one at btca.dev/app/settings */ + "apiKey": string +} + +/** Preferences accessible in all the extension's commands */ +declare type Preferences = ExtensionPreferences + +declare namespace Preferences { + /** Preferences accessible in the `ask` command */ + export type Ask = ExtensionPreferences & {} +} + +declare namespace Arguments { + /** Arguments passed to the `ask` command */ + export type Ask = {} +} + diff --git a/apps/raycast/src/api.ts b/apps/raycast/src/api.ts new file mode 100644 index 00000000..5768fc70 --- /dev/null +++ b/apps/raycast/src/api.ts @@ -0,0 +1,71 @@ +import { getPreferenceValues } from '@raycast/api'; +import { ResourcesResponseSchema, type ResourcesResponse } from './types'; + +const CONVEX_URL = 'https://greedy-partridge-784.convex.site'; + +interface Preferences { + apiKey: string; +} + +function getApiKey(): string { + const preferences = getPreferenceValues(); + return preferences.apiKey; +} + +function getHeaders(): HeadersInit { + return { + Authorization: `Bearer ${getApiKey()}`, + 'Content-Type': 'application/json' + }; +} + +export async function fetchResources(): Promise { + const response = await fetch(`${CONVEX_URL}/raycast/resources`, { + method: 'GET', + headers: getHeaders() + }); + + if (!response.ok) { + const error = (await response.json().catch(() => ({ error: 'Unknown error' }))) as { + error?: string; + upgradeUrl?: string; + }; + throw new ApiError( + response.status, + error.error || 'Failed to fetch resources', + error.upgradeUrl + ); + } + + const data = await response.json(); + return ResourcesResponseSchema.parse(data); +} + +export async function askQuestion(question: string): Promise { + const response = await fetch(`${CONVEX_URL}/raycast/ask`, { + method: 'POST', + headers: getHeaders(), + body: JSON.stringify({ question }) + }); + + if (!response.ok) { + const error = (await response.json().catch(() => ({ error: 'Unknown error' }))) as { + error?: string; + upgradeUrl?: string; + }; + throw new ApiError(response.status, error.error || 'Request failed', error.upgradeUrl); + } + + return response; +} + +export class ApiError extends Error { + constructor( + public status: number, + message: string, + public upgradeUrl?: string + ) { + super(message); + this.name = 'ApiError'; + } +} diff --git a/apps/raycast/src/ask.tsx b/apps/raycast/src/ask.tsx new file mode 100644 index 00000000..dc7590f4 --- /dev/null +++ b/apps/raycast/src/ask.tsx @@ -0,0 +1,181 @@ +import { + Action, + ActionPanel, + Detail, + Form, + open, + openExtensionPreferences, + showToast, + Toast, + useNavigation +} from '@raycast/api'; +import { usePromise } from '@raycast/utils'; +import { useState } from 'react'; +import { askQuestion, fetchResources, ApiError } from './api'; +import { parseSSEStream } from './stream'; + +export default function AskCommand() { + const [question, setQuestion] = useState(''); + const { push } = useNavigation(); + + // Fetch resources on mount (for future autocomplete hints) + const { data: resourcesData, isLoading: isLoadingResources } = usePromise(async () => { + try { + return await fetchResources(); + } catch (error) { + if (error instanceof ApiError) { + handleApiError(error); + } + return null; + } + }, []); + + const handleSubmit = async (values: { question: string }) => { + if (!values.question.trim()) { + showToast({ + style: Toast.Style.Failure, + title: 'Question required', + message: 'Please enter a question' + }); + return; + } + + push(); + }; + + const resourceNames = resourcesData?.resources.map((r) => r.name) ?? []; + const resourceHint = + resourceNames.length > 0 + ? `Available: ${resourceNames + .slice(0, 5) + .map((n) => `@${n}`) + .join(', ')}${resourceNames.length > 5 ? '...' : ''}` + : ''; + + return ( +
+ + + + } + > + + + + ); +} + +function ResponseView({ question }: { question: string }) { + const [markdown, setMarkdown] = useState(''); + const [isComplete, setIsComplete] = useState(false); + + const { isLoading } = usePromise(async () => { + try { + const response = await askQuestion(question); + + for await (const event of parseSSEStream(response)) { + if (event.type === 'text') { + setMarkdown((prev) => prev + event.delta); + } else if (event.type === 'done') { + setMarkdown(event.text); + setIsComplete(true); + } else if (event.type === 'error') { + throw new Error(event.message); + } + } + } catch (error) { + if (error instanceof ApiError) { + handleApiError(error); + } + throw error; + } + }, []); + + const displayMarkdown = markdown || (isLoading ? '*Thinking...*' : ''); + + return ( + + + + ) : undefined + } + actions={ + + + + + } + /> + ); +} + +function handleApiError(error: ApiError) { + if (error.status === 401) { + showToast({ + style: Toast.Style.Failure, + title: 'Invalid API Key', + message: 'Check your API key in extension preferences', + primaryAction: { + title: 'Open Preferences', + onAction: () => openExtensionPreferences() + } + }); + } else if (error.status === 402) { + showToast({ + style: Toast.Style.Failure, + title: 'Subscription Required', + message: error.message, + primaryAction: error.upgradeUrl + ? { + title: 'Upgrade', + onAction: () => { + open(error.upgradeUrl!); + } + } + : undefined + }); + } else if (error.status === 503) { + showToast({ + style: Toast.Style.Failure, + title: 'Service Unavailable', + message: error.message + }); + } else { + showToast({ + style: Toast.Style.Failure, + title: 'Error', + message: error.message + }); + } +} diff --git a/apps/raycast/src/stream.ts b/apps/raycast/src/stream.ts new file mode 100644 index 00000000..16abec9f --- /dev/null +++ b/apps/raycast/src/stream.ts @@ -0,0 +1,63 @@ +import { StreamEventSchema, type StreamEvent } from './types'; + +export async function* parseSSEStream(response: Response): AsyncGenerator { + if (!response.body) { + throw new Error('Response body is null'); + } + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() ?? ''; + + let eventData = ''; + + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } else if (line === '' && eventData) { + try { + const parsed = JSON.parse(eventData); + const validated = StreamEventSchema.parse(parsed); + yield validated; + } catch (error) { + console.error('Failed to parse SSE event:', error); + } + eventData = ''; + } + } + } + + // Process remaining buffer + if (buffer.trim()) { + const lines = buffer.split('\n'); + let eventData = ''; + + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } + } + + if (eventData) { + try { + const parsed = JSON.parse(eventData); + const validated = StreamEventSchema.parse(parsed); + yield validated; + } catch { + // Ignore incomplete final event + } + } + } + } finally { + reader.releaseLock(); + } +} diff --git a/apps/raycast/src/types.ts b/apps/raycast/src/types.ts new file mode 100644 index 00000000..991e1524 --- /dev/null +++ b/apps/raycast/src/types.ts @@ -0,0 +1,41 @@ +import { z } from 'zod'; + +// API Response types +export const ResourceSchema = z.object({ + name: z.string(), + displayName: z.string(), + isGlobal: z.boolean() +}); + +export const ResourcesResponseSchema = z.object({ + resources: z.array(ResourceSchema) +}); + +export type Resource = z.infer; +export type ResourcesResponse = z.infer; + +// Stream event types +export const StreamEventSchema = z.discriminatedUnion('type', [ + z.object({ + type: z.literal('text'), + delta: z.string() + }), + z.object({ + type: z.literal('done'), + text: z.string() + }), + z.object({ + type: z.literal('error'), + message: z.string() + }) +]); + +export type StreamEvent = z.infer; + +// Error response +export const ErrorResponseSchema = z.object({ + error: z.string(), + upgradeUrl: z.string().optional() +}); + +export type ErrorResponse = z.infer; diff --git a/apps/raycast/tsconfig.json b/apps/raycast/tsconfig.json new file mode 100644 index 00000000..d9f4340a --- /dev/null +++ b/apps/raycast/tsconfig.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node 20", + "include": ["src/**/*"], + "compilerOptions": { + "lib": ["ES2022"], + "module": "CommonJS", + "target": "ES2022", + "strict": true, + "isolatedModules": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react-jsx", + "moduleResolution": "node", + "resolveJsonModule": true + } +} diff --git a/apps/web/src/convex/_generated/api.d.ts b/apps/web/src/convex/_generated/api.d.ts index 3e654abf..4ea281f5 100644 --- a/apps/web/src/convex/_generated/api.d.ts +++ b/apps/web/src/convex/_generated/api.d.ts @@ -19,6 +19,8 @@ import type * as instances_mutations from "../instances/mutations.js"; import type * as instances_queries from "../instances/queries.js"; import type * as mcp from "../mcp.js"; import type * as messages from "../messages.js"; +import type * as raycastAuth from "../raycastAuth.js"; +import type * as raycastUsage from "../raycastUsage.js"; import type * as resources from "../resources.js"; import type * as scheduled_queries from "../scheduled/queries.js"; import type * as scheduled_updates from "../scheduled/updates.js"; @@ -48,6 +50,8 @@ declare const fullApi: ApiFromModules<{ "instances/queries": typeof instances_queries; mcp: typeof mcp; messages: typeof messages; + raycastAuth: typeof raycastAuth; + raycastUsage: typeof raycastUsage; resources: typeof resources; "scheduled/queries": typeof scheduled_queries; "scheduled/updates": typeof scheduled_updates; diff --git a/apps/web/src/convex/apiKeys.ts b/apps/web/src/convex/apiKeys.ts index f0195edd..36f7c229 100644 --- a/apps/web/src/convex/apiKeys.ts +++ b/apps/web/src/convex/apiKeys.ts @@ -151,6 +151,29 @@ export const touchLastUsed = mutation({ } }); +export const getByKey = query({ + args: { key: v.string() }, + handler: async (ctx, args) => { + const keyHash = await hashApiKey(args.key); + + const apiKey = await ctx.db + .query('apiKeys') + .withIndex('by_key_hash', (q) => q.eq('keyHash', keyHash)) + .first(); + + if (!apiKey || apiKey.revokedAt) { + return null; + } + + return { + _id: apiKey._id, + instanceId: apiKey.instanceId, + name: apiKey.name, + status: apiKey.revokedAt ? ('revoked' as const) : ('active' as const) + }; + } +}); + async function hashApiKey(apiKey: string): Promise { const encoder = new TextEncoder(); const data = encoder.encode(apiKey); diff --git a/apps/web/src/convex/http.ts b/apps/web/src/convex/http.ts index c5dd8d73..043c94c6 100644 --- a/apps/web/src/convex/http.ts +++ b/apps/web/src/convex/http.ts @@ -8,6 +8,7 @@ import type { Id } from './_generated/dataModel.js'; import { httpAction, type ActionCtx } from './_generated/server.js'; import { AnalyticsEvents } from './analyticsEvents.js'; import { instances } from './apiHelpers.js'; +import { authenticateRaycastRequest, isAuthError } from './raycastAuth.js'; const usageActions = api.usage; const instanceActions = instances.actions; @@ -702,6 +703,285 @@ http.route({ handler: daytonaWebhook }); +// ============================================================================ +// RayCast Extension Endpoints +// ============================================================================ + +const raycastAskRequestSchema = z.object({ + question: z.string().min(1) +}); + +// Helper to extract @resource mentions from question +function extractResources(question: string): { cleanQuestion: string; resources: string[] } { + const resourcePattern = /@(\w+)/g; + const resources: string[] = []; + let match; + + while ((match = resourcePattern.exec(question)) !== null) { + resources.push(match[1]); + } + + // Keep original question - resources are contextual + const cleanQuestion = question; + + return { cleanQuestion, resources: [...new Set(resources)] }; +} + +const raycastResources = httpAction(async (ctx, request) => { + // Authenticate + const authResult = await authenticateRaycastRequest(ctx, request); + + if (isAuthError(authResult)) { + return new Response(JSON.stringify({ error: authResult.message }), { + status: authResult.status, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { instance } = authResult; + + // Fetch resources + const resources = await ctx.runQuery(api.resources.listAvailable, { + instanceId: instance._id + }); + + // Flatten and format for RayCast + const allResources = [ + ...resources.global.map((r) => ({ + name: r.name, + displayName: r.displayName, + isGlobal: true + })), + ...resources.custom.map((r) => ({ + name: r.name, + displayName: r.displayName, + isGlobal: false + })) + ]; + + return new Response(JSON.stringify({ resources: allResources }), { + status: 200, + headers: { 'Content-Type': 'application/json' } + }); +}); + +const raycastAsk = httpAction(async (ctx, request) => { + // Authenticate + const authResult = await authenticateRaycastRequest(ctx, request); + + if (isAuthError(authResult)) { + return new Response(JSON.stringify({ error: authResult.message }), { + status: authResult.status, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { instance } = authResult; + + // Parse request body + let rawBody: unknown; + try { + rawBody = await request.json(); + } catch { + return new Response(JSON.stringify({ error: 'Invalid request body' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + const parseResult = raycastAskRequestSchema.safeParse(rawBody); + if (!parseResult.success) { + return new Response(JSON.stringify({ error: 'Invalid request: question is required' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + const { question } = parseResult.data; + const { resources } = extractResources(question); + + // Check usage/subscription using internal Raycast-specific action (no JWT auth) + const usageCheck = await ctx.runAction(internal.raycastUsage.ensureUsageAvailableForRaycast, { + instanceId: instance._id, + question, + resources + }); + + if (!usageCheck?.ok) { + const reason = (usageCheck as { reason?: string }).reason; + if (reason === 'subscription_required') { + return new Response( + JSON.stringify({ + error: 'Subscription required', + upgradeUrl: 'https://btca.dev/pricing' + }), + { status: 402, headers: { 'Content-Type': 'application/json' } } + ); + } + if (reason === 'free_limit_reached') { + return new Response( + JSON.stringify({ + error: 'Free message limit reached. Upgrade to continue.', + upgradeUrl: 'https://btca.dev/pricing' + }), + { status: 402, headers: { 'Content-Type': 'application/json' } } + ); + } + return new Response(JSON.stringify({ error: 'Usage limit reached' }), { + status: 402, + headers: { 'Content-Type': 'application/json' } + }); + } + + // Ensure instance is running + let serverUrl = instance.serverUrl; + if (instance.state !== 'running' || !serverUrl) { + if (!instance.sandboxId) { + return new Response( + JSON.stringify({ error: 'Instance not provisioned. Please visit btca.dev to set up.' }), + { status: 503, headers: { 'Content-Type': 'application/json' } } + ); + } + + // Wake the instance + try { + const wakeResult = await ctx.runAction(instanceActions.wake, { + instanceId: instance._id + }); + if (!wakeResult.serverUrl) { + throw new Error('No server URL returned'); + } + serverUrl = wakeResult.serverUrl; + } catch { + return new Response(JSON.stringify({ error: 'Failed to start instance. Try again.' }), { + status: 503, + headers: { 'Content-Type': 'application/json' } + }); + } + } + + // Create SSE stream + const encoder = new TextEncoder(); + + const stream = new ReadableStream({ + async start(controller) { + const sendEvent = (data: unknown) => { + controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)); + }; + + try { + // Call btca server + const response = await fetch(`${serverUrl}/question/stream`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + question, + resources, + quiet: true + }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(errorText || `Server error: ${response.status}`); + } + + if (!response.body) { + throw new Error('No response body'); + } + + // Stream through the response + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() ?? ''; + + let eventData = ''; + for (const line of lines) { + if (line.startsWith('data: ')) { + eventData = line.slice(6); + } else if (line === '' && eventData) { + try { + const event = JSON.parse(eventData) as BtcaStreamEvent; + + // Forward relevant events to RayCast + if (event.type === 'text.delta') { + sendEvent({ type: 'text', delta: event.delta }); + } else if (event.type === 'done') { + sendEvent({ type: 'done', text: event.text }); + } else if (event.type === 'error') { + sendEvent({ type: 'error', message: event.message }); + } + // Skip meta, reasoning, tool events for simplicity + } catch { + // Ignore parse errors + } + eventData = ''; + } + } + } + + reader.releaseLock(); + + // Finalize usage using internal Raycast-specific action (no JWT auth) + await ctx.runAction(internal.raycastUsage.finalizeUsageForRaycast, { + instanceId: instance._id, + questionTokens: 0, // Simplified for RayCast + outputChars: 0, + reasoningChars: 0, + resources, + sandboxUsageHours: 0 + }); + + controller.close(); + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + sendEvent({ type: 'error', message }); + controller.close(); + } + } + }); + + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive' + } + }); +}); + +http.route({ + path: '/raycast/resources', + method: 'GET', + handler: raycastResources +}); + +http.route({ + path: '/raycast/resources', + method: 'OPTIONS', + handler: corsPreflight +}); + +http.route({ + path: '/raycast/ask', + method: 'POST', + handler: raycastAsk +}); + +http.route({ + path: '/raycast/ask', + method: 'OPTIONS', + handler: corsPreflight +}); + export default http; function getSvixHeaders(request: Request): SvixHeaders | null { diff --git a/apps/web/src/convex/raycastAuth.ts b/apps/web/src/convex/raycastAuth.ts new file mode 100644 index 00000000..c684783a --- /dev/null +++ b/apps/web/src/convex/raycastAuth.ts @@ -0,0 +1,64 @@ +import type { ActionCtx } from './_generated/server'; +import { api } from './_generated/api'; +import type { Doc } from './_generated/dataModel'; + +export type RaycastAuthResult = { + instance: Doc<'instances'>; + apiKey: { + _id: Doc<'apiKeys'>['_id']; + instanceId: Doc<'apiKeys'>['instanceId']; + name: string; + status: 'active' | 'revoked'; + }; +}; + +export type RaycastAuthError = { + status: number; + message: string; +}; + +export async function authenticateRaycastRequest( + ctx: ActionCtx, + request: Request +): Promise { + const authHeader = request.headers.get('Authorization'); + + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return { status: 401, message: 'Missing or invalid Authorization header' }; + } + + const apiKeyValue = authHeader.slice(7); // Remove 'Bearer ' + + if (!apiKeyValue) { + return { status: 401, message: 'API key is required' }; + } + + // Look up the API key + const apiKey = await ctx.runQuery(api.apiKeys.getByKey, { key: apiKeyValue }); + + if (!apiKey) { + return { status: 401, message: 'Invalid API key' }; + } + + // Check if key is active + if (apiKey.status !== 'active') { + return { status: 401, message: 'API key is inactive' }; + } + + // Get the associated instance + const instance = await ctx.runQuery(api.instances.queries.get, { + id: apiKey.instanceId + }); + + if (!instance) { + return { status: 404, message: 'Instance not found' }; + } + + return { instance, apiKey }; +} + +export function isAuthError( + result: RaycastAuthResult | RaycastAuthError +): result is RaycastAuthError { + return 'status' in result && 'message' in result && !('instance' in result); +} diff --git a/apps/web/src/convex/raycastUsage.ts b/apps/web/src/convex/raycastUsage.ts new file mode 100644 index 00000000..f9b52ef8 --- /dev/null +++ b/apps/web/src/convex/raycastUsage.ts @@ -0,0 +1,447 @@ +/** + * Raycast-specific usage functions that don't rely on JWT authentication. + * These are used by the Raycast HTTP endpoints which authenticate via API key. + */ +import { Autumn } from 'autumn-js'; +import { v } from 'convex/values'; + +import { internal } from './_generated/api.js'; +import { internalAction } from './_generated/server.js'; +import { AnalyticsEvents } from './analyticsEvents.js'; +import { instances } from './apiHelpers.js'; + +type FeatureMetrics = { + usage: number; + balance: number; + included: number; +}; + +type UsageCheckResult = + | { ok: false; reason: 'subscription_required' | 'free_limit_reached' } + | { + ok: boolean; + reason: string | null; + metrics: { + tokensIn: FeatureMetrics; + tokensOut: FeatureMetrics; + sandboxHours: FeatureMetrics; + }; + inputTokens: number; + sandboxUsageHours: number; + customerId: string; + }; + +type FinalizeUsageResult = { + outputTokens: number; + sandboxUsageHours: number; + customerId: string; +}; + +const SANDBOX_IDLE_MINUTES = 2; +const CHARS_PER_TOKEN = 4; +const FEATURE_IDS = { + tokensIn: 'tokens_in', + tokensOut: 'tokens_out', + sandboxHours: 'sandbox_hours', + chatMessages: 'chat_messages' +} as const; + +function requireEnv(name: string): string { + const value = process.env[name]; + if (!value) { + throw new Error(`${name} is not set in the Convex environment`); + } + return value; +} + +let autumnClient: Autumn | null = null; + +function getAutumnClient(): Autumn { + if (!autumnClient) { + autumnClient = new Autumn({ secretKey: requireEnv('AUTUMN_SECRET_KEY') }); + } + return autumnClient; +} + +function estimateTokensFromText(text: string): number { + const trimmed = text.trim(); + if (!trimmed) return 0; + return Math.max(1, Math.ceil(trimmed.length / CHARS_PER_TOKEN)); +} + +function estimateTokensFromChars(chars: number): number { + if (!Number.isFinite(chars) || chars <= 0) return 0; + return Math.max(1, Math.ceil(chars / CHARS_PER_TOKEN)); +} + +function estimateSandboxUsageHours(params: { lastActiveAt?: number | null; now: number }): number { + const maxWindowMs = SANDBOX_IDLE_MINUTES * 60 * 1000; + if (!params.lastActiveAt) { + return maxWindowMs / (60 * 60 * 1000); + } + const deltaMs = Math.max(0, params.now - params.lastActiveAt); + const cappedMs = Math.min(deltaMs, maxWindowMs); + return cappedMs / (60 * 60 * 1000); +} + +async function getOrCreateCustomerByClerkId(clerkId: string): Promise<{ + id: string; + products?: { + id?: string; + status?: string; + current_period_end?: number | null; + canceled_at?: number | null; + }[]; +}> { + const autumn = getAutumnClient(); + + // Try to create customer first (will fail if already exists) + const createPayload = await autumn.customers.create({ + id: clerkId + }); + + const fetchCustomer = async (customerId: string) => { + const customerPayload = await autumn.customers.get(customerId); + if (customerPayload.error) { + throw new Error(customerPayload.error.message ?? 'Failed to fetch Autumn customer'); + } + const id = customerPayload.data?.id ?? customerId; + return { + id, + products: customerPayload.data?.products ?? [] + }; + }; + + if (!createPayload.error) { + const customerId = createPayload.data?.id ?? clerkId; + return fetchCustomer(customerId); + } + + const message = createPayload.error?.message ?? 'Failed to create Autumn customer'; + const alreadyExists = message.toLowerCase().includes('already'); + if (!alreadyExists) { + throw new Error(message); + } + + return fetchCustomer(clerkId); +} + +function getActiveProduct( + products: + | { + id?: string; + status?: string; + current_period_end?: number | null; + canceled_at?: number | null; + }[] + | undefined +): { + id: string; + status?: string; + current_period_end?: number | null; + canceled_at?: number | null; +} | null { + if (!products?.length) return null; + + const proProduct = products.find( + (product) => + product.id === 'btca_pro' && (product.status === 'active' || product.status === 'trialing') + ); + if (proProduct) { + return { + id: proProduct.id ?? 'btca_pro', + status: proProduct.status, + current_period_end: proProduct.current_period_end, + canceled_at: proProduct.canceled_at + }; + } + + const freeProduct = products.find( + (product) => product.id === 'free_plan' && product.status === 'active' + ); + if (freeProduct) { + return { + id: freeProduct.id ?? 'free_plan', + status: freeProduct.status, + current_period_end: freeProduct.current_period_end, + canceled_at: freeProduct.canceled_at + }; + } + + return null; +} + +async function checkFeature(args: { + customerId: string; + featureId: string; + requiredBalance?: number; +}): Promise<{ usage: number; balance: number; included: number }> { + const autumn = getAutumnClient(); + const payload: { + customer_id: string; + feature_id: string; + required_balance?: number; + } = { + customer_id: args.customerId, + feature_id: args.featureId + }; + if (args.requiredBalance !== undefined) { + payload.required_balance = args.requiredBalance; + } + + const result = await autumn.check(payload); + if (result.error) { + throw new Error(result.error.message ?? 'Failed to check Autumn usage'); + } + + return { + usage: result.data?.usage ?? 0, + balance: result.data?.balance ?? 0, + included: result.data?.included_usage ?? 0 + }; +} + +async function trackUsage(args: { + customerId: string; + featureId: string; + value: number; +}): Promise { + const autumn = getAutumnClient(); + const result = await autumn.track({ + customer_id: args.customerId, + feature_id: args.featureId, + value: args.value + }); + if (result.error) { + throw new Error(result.error.message ?? 'Failed to track Autumn usage'); + } +} + +/** + * Check if usage is available for a Raycast request. + * This is an internal action that doesn't require JWT auth. + */ +export const ensureUsageAvailableForRaycast = internalAction({ + args: { + instanceId: v.id('instances'), + question: v.string(), + resources: v.array(v.string()) + }, + handler: async (ctx, args): Promise => { + const instance = await ctx.runQuery(instances.queries.get, { id: args.instanceId }); + if (!instance) { + throw new Error('Instance not found'); + } + + // Use clerkId directly without JWT - we already verified ownership via API key + const autumnCustomer = await getOrCreateCustomerByClerkId(instance.clerkId); + const activeProduct = getActiveProduct(autumnCustomer.products); + + if (!activeProduct) { + return { + ok: false, + reason: 'subscription_required' + }; + } + + const isFreePlan = activeProduct.id === 'free_plan'; + const isProPlan = activeProduct.id === 'btca_pro'; + + if (isFreePlan) { + const chatMessages = await checkFeature({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.chatMessages, + requiredBalance: 1 + }); + + if (chatMessages.balance <= 0) { + await ctx.scheduler.runAfter(0, internal.analytics.trackEvent, { + distinctId: instance.clerkId, + event: AnalyticsEvents.USAGE_LIMIT_REACHED, + properties: { + instanceId: args.instanceId, + limitTypes: ['chatMessages'], + chatMessagesBalance: chatMessages.balance, + source: 'raycast' + } + }); + + return { + ok: false, + reason: 'free_limit_reached' + }; + } + + return { + ok: true, + reason: null, + metrics: { + tokensIn: { usage: 0, balance: 0, included: 0 }, + tokensOut: { usage: 0, balance: 0, included: 0 }, + sandboxHours: { usage: 0, balance: 0, included: 0 } + }, + inputTokens: 0, + sandboxUsageHours: 0, + customerId: autumnCustomer.id ?? instance.clerkId + }; + } + + if (isProPlan) { + const inputTokens = estimateTokensFromText(args.question); + const now = Date.now(); + const sandboxUsageHours = args.resources.length + ? estimateSandboxUsageHours({ lastActiveAt: instance.lastActiveAt, now }) + : 0; + + const requiredTokensIn = inputTokens > 0 ? inputTokens : undefined; + const requiredTokensOut = 1; + const requiredSandboxHours = sandboxUsageHours > 0 ? sandboxUsageHours : undefined; + + const [tokensIn, tokensOut, sandboxHours] = await Promise.all([ + checkFeature({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.tokensIn, + requiredBalance: requiredTokensIn + }), + checkFeature({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.tokensOut, + requiredBalance: requiredTokensOut + }), + checkFeature({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.sandboxHours, + requiredBalance: requiredSandboxHours + }) + ]); + + const hasEnough = (balance: number, required?: number) => + required == null ? balance > 0 : balance >= required; + + const ok = + hasEnough(tokensIn.balance, requiredTokensIn) && + hasEnough(tokensOut.balance, requiredTokensOut) && + hasEnough(sandboxHours.balance, requiredSandboxHours); + + if (!ok) { + const limitTypes: string[] = []; + if (!hasEnough(tokensIn.balance, requiredTokensIn)) limitTypes.push('tokensIn'); + if (!hasEnough(tokensOut.balance, requiredTokensOut)) limitTypes.push('tokensOut'); + if (!hasEnough(sandboxHours.balance, requiredSandboxHours)) limitTypes.push('sandboxHours'); + + await ctx.scheduler.runAfter(0, internal.analytics.trackEvent, { + distinctId: instance.clerkId, + event: AnalyticsEvents.USAGE_LIMIT_REACHED, + properties: { + instanceId: args.instanceId, + limitTypes, + tokensInBalance: tokensIn.balance, + tokensOutBalance: tokensOut.balance, + sandboxHoursBalance: sandboxHours.balance, + source: 'raycast' + } + }); + } + + return { + ok, + reason: ok ? null : 'limit_reached', + metrics: { + tokensIn, + tokensOut, + sandboxHours + }, + inputTokens, + sandboxUsageHours, + customerId: autumnCustomer.id ?? instance.clerkId + }; + } + + return { + ok: false, + reason: 'subscription_required' + }; + } +}); + +/** + * Finalize usage tracking for a Raycast request. + * This is an internal action that doesn't require JWT auth. + */ +export const finalizeUsageForRaycast = internalAction({ + args: { + instanceId: v.id('instances'), + questionTokens: v.number(), + outputChars: v.number(), + reasoningChars: v.number(), + resources: v.array(v.string()), + sandboxUsageHours: v.optional(v.number()) + }, + handler: async (ctx, args): Promise => { + const instance = await ctx.runQuery(instances.queries.get, { id: args.instanceId }); + if (!instance) { + throw new Error('Instance not found'); + } + + // Use clerkId directly without JWT + const autumnCustomer = await getOrCreateCustomerByClerkId(instance.clerkId); + const activeProduct = getActiveProduct(autumnCustomer.products); + const isFreePlan = activeProduct?.id === 'free_plan'; + const isProPlan = activeProduct?.id === 'btca_pro'; + + const tasks: Promise[] = []; + + if (isFreePlan) { + tasks.push( + trackUsage({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.chatMessages, + value: 1 + }) + ); + } + + const outputTokens = isProPlan + ? estimateTokensFromChars(args.outputChars + args.reasoningChars) + : 0; + const sandboxUsageHours = isProPlan ? (args.sandboxUsageHours ?? 0) : 0; + + if (isProPlan) { + if (args.questionTokens > 0) { + tasks.push( + trackUsage({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.tokensIn, + value: args.questionTokens + }) + ); + } + if (outputTokens > 0) { + tasks.push( + trackUsage({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.tokensOut, + value: outputTokens + }) + ); + } + if (sandboxUsageHours > 0) { + tasks.push( + trackUsage({ + customerId: autumnCustomer.id ?? instance.clerkId, + featureId: FEATURE_IDS.sandboxHours, + value: sandboxUsageHours + }) + ); + } + } + + await Promise.all(tasks); + + return { + outputTokens, + sandboxUsageHours, + customerId: autumnCustomer.id ?? instance.clerkId + }; + } +}); diff --git a/bun.lock b/bun.lock index fda3b84a..b15bfdb3 100644 --- a/bun.lock +++ b/bun.lock @@ -42,6 +42,22 @@ "solid-js": "^1.9.10", }, }, + "apps/raycast": { + "name": "better-context", + "dependencies": { + "@raycast/api": "^1.94.0", + "@raycast/utils": "^1.19.1", + "zod": "^3.24.0", + }, + "devDependencies": { + "@raycast/eslint-config": "^2.0.4", + "@types/node": "22.13.10", + "@types/react": "19.0.12", + "eslint": "^9.22.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2", + }, + }, "apps/sandbox": { "name": "btca-sandbox", "version": "0.0.1", @@ -431,6 +447,24 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.0", "", { "os": "win32", "cpu": "x64" }, "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + + "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="], + + "@eslint/js": ["@eslint/js@9.39.2", "", {}, "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + "@exodus/bytes": ["@exodus/bytes@1.9.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-lagqsvnk09NKogQaN/XrtlWeUF8SRhT12odMvbTIIaVObqzwAogL6jhR4DAp0gPuKoM1AOVrKUshJpRdpMFrww=="], "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], @@ -445,6 +479,14 @@ "@formkit/auto-animate": ["@formkit/auto-animate@0.8.4", "", {}, "sha512-DHHC01EJ1p70Q0z/ZFRBIY8NDnmfKccQoyoM84Tgb6omLMat6jivCdf272Y8k3nf4Lzdin/Y4R9q8uFtU0GbnA=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], @@ -579,6 +621,14 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oclif/core": ["@oclif/core@4.8.0", "", { "dependencies": { "ansi-escapes": "^4.3.2", "ansis": "^3.17.0", "clean-stack": "^3.0.1", "cli-spinners": "^2.9.2", "debug": "^4.4.3", "ejs": "^3.1.10", "get-package-type": "^0.1.0", "indent-string": "^4.0.0", "is-wsl": "^2.2.0", "lilconfig": "^3.1.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "string-width": "^4.2.3", "supports-color": "^8", "tinyglobby": "^0.2.14", "widest-line": "^3.1.0", "wordwrap": "^1.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-jteNUQKgJHLHFbbz806aGZqf+RJJ7t4gwF4MYa8fCwCxQ8/klJNWc0MvaJiBebk7Mc+J39mdlsB4XraaCKznFw=="], + + "@oclif/plugin-autocomplete": ["@oclif/plugin-autocomplete@3.2.40", "", { "dependencies": { "@oclif/core": "^4", "ansis": "^3.16.0", "debug": "^4.4.1", "ejs": "^3.1.10" } }, "sha512-HCfDuUV3l5F5Wz7SKkaoFb+OMQ5vKul8zvsPNgI0QbZcQuGHmn3svk+392wSfXboyA1gq8kzEmKPAoQK6r6UNw=="], + + "@oclif/plugin-help": ["@oclif/plugin-help@6.2.37", "", { "dependencies": { "@oclif/core": "^4" } }, "sha512-5N/X/FzlJaYfpaHwDC0YHzOzKDWa41s9t+4FpCDu4f9OMReds4JeNBaaWk9rlIzdKjh2M6AC5Q18ORfECRkHGA=="], + + "@oclif/plugin-not-found": ["@oclif/plugin-not-found@3.2.74", "", { "dependencies": { "@inquirer/prompts": "^7.10.1", "@oclif/core": "^4.8.0", "ansis": "^3.17.0", "fast-levenshtein": "^3.0.0" } }, "sha512-6RD/EuIUGxAYR45nMQg+nw+PqwCXUxkR6Eyn+1fvbVjtb9d+60OPwB77LCRUI4zKNI+n0LOFaMniEdSpb+A7kQ=="], + "@opencode-ai/sdk": ["@opencode-ai/sdk@1.1.31", "", {}, "sha512-u273CSLeNEqmE3suulCrXDLzJzW1dfFeRheUjnfwSvmhSpf6UqM4em4MpV2CBB2WoyC0VvWg8rNwSkvDzPmEdw=="], "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], @@ -645,6 +695,14 @@ "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + "@raycast/api": ["@raycast/api@1.104.3", "", { "dependencies": { "@oclif/core": "^4.5.4", "@oclif/plugin-autocomplete": "^3.2.35", "@oclif/plugin-help": "^6.2.33", "@oclif/plugin-not-found": "^3.2.68", "@types/node": "22.13.10", "@types/react": "19.0.10", "esbuild": "^0.25.10", "react": "19.0.0" }, "peerDependencies": { "react-devtools": "6.1.1" }, "optionalPeers": ["react-devtools"], "bin": { "ray": "bin/run.js" } }, "sha512-ud3c2csFd3VywjqDuY33U184ZmbAJmY+Z7qYpiMOOAzDZye49ZE7Qjw4s/2Vob+LCLX/XduzWpVFv5omdfNThQ=="], + + "@raycast/eslint-config": ["@raycast/eslint-config@2.1.1", "", { "dependencies": { "@eslint/js": "^9.36.0", "@raycast/eslint-plugin": "^2.1.1", "eslint-config-prettier": "^10.1.8", "globals": "^16.4.0", "typescript-eslint": "^8.45.0" }, "peerDependencies": { "eslint": ">=8.23.0", "prettier": ">=2", "typescript": ">=4" } }, "sha512-W0kxF+FJ+BYQn0EKIV739j2ZrHEtjo/LclsoZgUWg3t364Dq75XKcjqYFYx+59/DBaamY0amdajlfuDAf6veAg=="], + + "@raycast/eslint-plugin": ["@raycast/eslint-plugin@2.1.1", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.1" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-r2gs8uIlNp6I2mLOyN/kReGlvigzEeuyQPl4yw7nwLy8Zxjfjhg8txMViaBux8juBWBxbSWq/IfW6ZA50oeOHQ=="], + + "@raycast/utils": ["@raycast/utils@1.19.1", "", { "dependencies": { "cross-fetch": "^3.1.6", "dequal": "^2.0.3", "object-hash": "^3.0.0", "signal-exit": "^4.0.2", "stream-chain": "^2.2.5", "stream-json": "^1.8.0" }, "peerDependencies": { "@raycast/api": ">=1.69.0" } }, "sha512-/udUGcTZCgZZwzesmjBkqG5naQZTD/ZLHbqRwkWcF+W97vf9tr9raxKyQjKsdZ17OVllw2T3sHBQsVUdEmCm2g=="], + "@react-native-async-storage/async-storage": ["@react-native-async-storage/async-storage@1.24.0", "", { "dependencies": { "merge-options": "^3.0.4" }, "peerDependencies": { "react-native": "^0.0.0-0 || >=0.60 <1.0" } }, "sha512-W4/vbwUOYOjco0x3toB8QCr7EjIP6nE9G7o8PMguvvjYT5Awg09lyV4enACRx4s++PPulBiBSjL0KTFx2u0Z/g=="], "@react-native/assets-registry": ["@react-native/assets-registry@0.83.1", "", {}, "sha512-AT7/T6UwQqO39bt/4UL5EXvidmrddXrt0yJa7ENXndAv+8yBzMsZn6fyiax6+ERMt9GLzAECikv3lj22cn2wJA=="], @@ -981,12 +1039,14 @@ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], - "@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], "@types/prettier": ["@types/prettier@3.0.0", "", { "dependencies": { "prettier": "*" } }, "sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA=="], + "@types/react": ["@types/react@19.0.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA=="], + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], @@ -1003,6 +1063,26 @@ "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.53.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/type-utils": "8.53.1", "@typescript-eslint/utils": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.53.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.53.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.53.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.53.1", "@typescript-eslint/types": "^8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1" } }, "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.53.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.53.1", "", {}, "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.53.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.53.1", "@typescript-eslint/tsconfig-utils": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.53.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260120.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260120.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260120.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260120.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-nnEf37C9ue7OBRnF2zmV/OCBmV5Y7T/K4mCHa+nxgiXcF/1w8sA0cgdFl+gHQ0mysqUJ+Bu5btAMeWgpLyjrgg=="], "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260120.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-r3pWFuR2H7mn6ScwpH5jJljKQqKto0npVuJSk6pRwFwexpTyxOGmJTZJ1V0AWiisaNxU2+CNAqWFJSJYIE/QTg=="], @@ -1049,30 +1129,40 @@ "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], "ai": ["ai@6.0.44", "", { "dependencies": { "@ai-sdk/gateway": "3.0.18", "@ai-sdk/provider": "3.0.4", "@ai-sdk/provider-utils": "4.0.8", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-fOyssuNfSB3i3ODuDeLaWambfJY+gE3LRHQf4nmWEPDrQhfiB+fcpVMVi77LbFRBfoG/h5BrmX0heVqz4Hl7ug=="], + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "alien-signals": ["alien-signals@2.0.6", "", {}, "sha512-P3TxJSe31bUHBiblg59oU1PpaWPtmxF9GhJ/cB7OkgJ0qN/ifFSKUI25/v8ZhsT+lIG6ac8DpTOplXxORX6F3Q=="], "anser": ["anser@1.4.10", "", {}, "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww=="], + "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], + "any-base": ["any-base@1.1.0", "", {}, "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="], "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], "atmn": ["atmn@0.0.30", "", { "dependencies": { "@inquirer/prompts": "^7.6.0", "@types/prettier": "^3.0.0", "axios": "^1.10.0", "chalk": "^5.2.0", "commander": "^14.0.0", "dotenv": "^17.2.0", "inquirer": "^12.7.0", "jiti": "^2.4.2", "open": "^10.1.2", "prettier": "^3.6.2", "yocto-spinner": "^1.0.0", "zod": "^4.0.0" }, "bin": { "atmn": "dist/cli.js" } }, "sha512-I8mMUbTPqNOVYN871i0dxcKtM4dzy5GMZY8WaGDesoLU6VU7YQp08/sro42x+c/X9iMg9utfq+ylhCmpeaHjKA=="], @@ -1113,6 +1203,8 @@ "baseline-browser-mapping": ["baseline-browser-mapping@2.9.17", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ=="], + "better-context": ["better-context@workspace:apps/raycast"], + "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="], "bmp-ts": ["bmp-ts@1.0.9", "", {}, "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw=="], @@ -1123,7 +1215,7 @@ "bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="], - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -1193,6 +1285,10 @@ "ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], + "clean-stack": ["clean-stack@3.0.1", "", { "dependencies": { "escape-string-regexp": "4.0.0" } }, "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], @@ -1229,6 +1325,8 @@ "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="], + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="], @@ -1251,6 +1349,8 @@ "decode-uri-component": ["decode-uri-component@0.4.1", "", {}, "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ=="], + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="], @@ -1287,6 +1387,8 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -1321,14 +1423,32 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "eslint": ["eslint@9.39.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], + "esrap": ["esrap@2.2.2", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ=="], + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], @@ -1347,10 +1467,14 @@ "eyes": ["eyes@0.1.8", "", {}, "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + "fast-stable-stringify": ["fast-stable-stringify@1.0.0", "", {}, "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag=="], "fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], @@ -1369,8 +1493,12 @@ "fflate": ["fflate@0.4.8", "", {}, "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + "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=="], + "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "filter-obj": ["filter-obj@5.1.0", "", {}, "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng=="], @@ -1381,7 +1509,11 @@ "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], - "find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="], @@ -1413,10 +1545,12 @@ "glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + "globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], @@ -1465,6 +1599,8 @@ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="], "image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="], @@ -1473,6 +1609,8 @@ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -1507,7 +1645,7 @@ "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], - "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], @@ -1521,6 +1659,8 @@ "istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="], + "jake": ["jake@10.9.4", "", { "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", "picocolors": "^1.1.1" }, "bin": { "jake": "bin/cli.js" } }, "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA=="], + "jayson": ["jayson@4.3.0", "", { "dependencies": { "@types/connect": "^3.4.33", "@types/node": "^12.12.54", "@types/ws": "^7.4.4", "commander": "^2.20.3", "delay": "^5.0.0", "es6-promisify": "^5.0.0", "eyes": "^0.1.8", "isomorphic-ws": "^4.0.1", "json-stringify-safe": "^5.0.1", "stream-json": "^1.9.1", "uuid": "^8.3.2", "ws": "^7.5.10" }, "bin": { "jayson": "bin/jayson.js" } }, "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ=="], "jest-environment-node": ["jest-environment-node@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw=="], @@ -1553,7 +1693,7 @@ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="], @@ -1561,20 +1701,30 @@ "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "json-rpc-2.0": ["json-rpc-2.0@1.7.1", "", {}, "sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg=="], "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], @@ -1601,14 +1751,18 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], - "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], @@ -1685,7 +1839,7 @@ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], @@ -1703,6 +1857,8 @@ "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], @@ -1719,6 +1875,8 @@ "ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], "omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="], @@ -1733,11 +1891,13 @@ "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "ox": ["ox@0.6.9", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug=="], - "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - "p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], @@ -1759,7 +1919,7 @@ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - "path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], @@ -1799,6 +1959,8 @@ "preact": ["preact@10.28.2", "", {}, "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "prettier-plugin-svelte": ["prettier-plugin-svelte@3.4.1", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg=="], @@ -1983,6 +2145,8 @@ "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], "strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="], @@ -2049,6 +2213,8 @@ "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + "ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "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=="], @@ -2065,13 +2231,17 @@ "turbo-windows-arm64": ["turbo-windows-arm64@2.7.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-G377Gxn6P42RnCzfMyDvsqQV7j69kVHKlhz9J4RhtJOB5+DyY4yYh/w0oTIxZQ4JRMmhjwLu3w9zncMoQ6nNDw=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="], - "type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="], + "type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "typescript-eslint": ["typescript-eslint@8.53.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.53.1", "@typescript-eslint/parser": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], @@ -2087,6 +2257,8 @@ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "uri-template-matcher": ["uri-template-matcher@1.1.2", "", {}, "sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ=="], "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], @@ -2135,7 +2307,13 @@ "which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="], - "wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + "widest-line": ["widest-line@3.1.0", "", { "dependencies": { "string-width": "^4.0.0" } }, "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], @@ -2165,6 +2343,8 @@ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "yocto-spinner": ["yocto-spinner@1.0.0", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-VPX8P/+Z2Fnpx8PC/JELbxp3QRrBxjAekio6yulGtA5gKt9YyRc5ycCb+NHgZCbZ0kx9KxwZp7gC6UlrCcCdSQ=="], "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], @@ -2209,12 +2389,26 @@ "@emotion/serialize/@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + "@istanbuljs/load-nyc-config/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + "@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], + "@istanbuljs/load-nyc-config/resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + "@jest/environment/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "@jest/fake-timers/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "@jest/transform/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "@jest/types/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@jimp/plugin-blit/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -2251,6 +2445,14 @@ "@noble/curves/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + "@oclif/core/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@oclif/core/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + + "@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "@oclif/plugin-not-found/fast-levenshtein": ["fast-levenshtein@3.0.0", "", { "dependencies": { "fastest-levenshtein": "^1.0.7" } }, "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ=="], + "@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], "@opentelemetry/resources/@opentelemetry/core": ["@opentelemetry/core@2.5.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ=="], @@ -2261,6 +2463,12 @@ "@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + "@raycast/api/@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="], + + "@raycast/api/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=="], + + "@raycast/api/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + "@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "@react-native/community-cli-plugin/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], @@ -2307,6 +2515,18 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@types/connect/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "@types/graceful-fs/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "@types/ws/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "@wallet-standard/errors/commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -2319,13 +2539,15 @@ "babel-plugin-jsx-dom-expressions/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "better-context/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "btca-server/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "chrome-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "bun-types/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], - "chromium-edge-launcher/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "chrome-launcher/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], - "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "chromium-edge-launcher/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2333,18 +2555,28 @@ "data-urls/whatwg-mimetype": ["whatwg-mimetype@5.0.0", "", {}, "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw=="], + "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="], + "glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], "http-errors/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="], + "is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "jayson/@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], "jayson/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], @@ -2353,8 +2585,16 @@ "jayson/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "jest-environment-node/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "jest-haste-map/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "jest-message-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "jest-mock/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "jest-util/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "jest-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "jest-util/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], @@ -2365,6 +2605,8 @@ "jest-validate/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "jest-worker/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2395,6 +2637,8 @@ "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], + "pkg-up/find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], + "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "posthog-js/core-js": ["core-js@3.48.0", "", {}, "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ=="], @@ -2403,6 +2647,8 @@ "pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], + "protobufjs/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "qrcode/pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="], "qrcode/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], @@ -2435,12 +2681,12 @@ "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], + "stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="], + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "test-exclude/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "viem/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], "viem/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], @@ -2451,6 +2697,8 @@ "write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "wsl-utils/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], @@ -2459,13 +2707,69 @@ "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - "@istanbuljs/load-nyc-config/find-up/path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "@react-native/codegen/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "@jest/environment/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "@react-native/dev-middleware/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "@jest/fake-timers/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@jest/types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@oclif/core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@raycast/api/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@raycast/api/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@raycast/api/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@react-native/dev-middleware/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "@raycast/api/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@raycast/api/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@raycast/api/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@raycast/api/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@raycast/api/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@raycast/api/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@raycast/api/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@raycast/api/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@raycast/api/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@raycast/api/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@raycast/api/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@raycast/api/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@raycast/api/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@raycast/api/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@raycast/api/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@raycast/api/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@raycast/api/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@raycast/api/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@raycast/api/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "@raycast/api/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@raycast/api/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@raycast/api/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@raycast/api/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + + "@react-native/dev-middleware/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], "@solana-mobile/mobile-wallet-adapter-protocol-web3js/bs58/base-x": ["base-x@4.0.1", "", {}, "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw=="], @@ -2475,20 +2779,48 @@ "@solana/wallet-standard-wallet-adapter-base/bs58/base-x": ["base-x@4.0.1", "", {}, "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw=="], - "chrome-launcher/is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "@types/connect/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/graceful-fs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "chromium-edge-launcher/is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "chrome-launcher/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "chromium-edge-launcher/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "jest-environment-node/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "jest-haste-map/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "jest-mock/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "jest-util/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "jest-worker/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], + + "protobufjs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "qrcode/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="], "qrcode/yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], @@ -2497,16 +2829,12 @@ "qrcode/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="], - "react-native/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "readable-web-to-node-stream/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "rpc-websockets/@types/ws/@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], - "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], @@ -2515,16 +2843,22 @@ "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "pkg-up/find-up/locate-path/p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], + + "pkg-up/find-up/locate-path/path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + + "qrcode/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], "qrcode/yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - "qrcode/yargs/find-up/path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "rpc-websockets/@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "qrcode/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "qrcode/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], } } From b27e87f3fd880c81e91ff99e23ac367e82fc5fab Mon Sep 17 00:00:00 2001 From: Ben Davis Date: Fri, 23 Jan 2026 21:27:48 -0800 Subject: [PATCH 4/4] fixed UI stuff --- apps/web/src/routes/+layout.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte index 2ac65ca8..ee76c656 100644 --- a/apps/web/src/routes/+layout.svelte +++ b/apps/web/src/routes/+layout.svelte @@ -178,7 +178,7 @@ -