├── sdk ├── memx_sdk │ ├── __init__.py │ ├── test_client.py │ └── client.py ├── dist │ ├── memx_sdk-0.1.1.tar.gz │ └── memx_sdk-0.1.1-py3-none-any.whl ├── pyproject.toml ├── LICENSE ├── README.md └── poetry.lock ├── assets └── example.gif ├── Makefile ├── frontend ├── memx-frontend │ ├── app │ │ ├── favicon.ico │ │ ├── components │ │ │ ├── LogoutButton.js │ │ │ ├── Header.js │ │ │ ├── KeyViewer.js │ │ │ ├── CreateKeyForm.js │ │ │ └── AuthForm.js │ │ ├── globals.css │ │ ├── layout.js │ │ ├── login │ │ │ └── page.js │ │ └── page.js │ ├── public │ │ ├── example.gif │ │ ├── vercel.svg │ │ ├── window.svg │ │ ├── file.svg │ │ ├── globe.svg │ │ └── next.svg │ ├── postcss.config.mjs │ ├── next.config.mjs │ ├── jsconfig.json │ ├── package.json │ ├── .gitignore │ ├── README.md │ └── package-lock.json └── streamlit.py ├── .gitignore ├── config └── acl.json ├── auth.py ├── Dockerfile ├── examples ├── query_agent.py ├── monitor_agent.py ├── test.py ├── explorer_agent.py └── synthesizer_agent.py ├── store.py ├── docker-compose.yml ├── schema.py ├── pubsub.py ├── pyproject.toml ├── LICENSE ├── validate_api.py ├── main.py ├── README.md └── requirements.txt /sdk/memx_sdk/__init__.py: -------------------------------------------------------------------------------- 1 | from .client import memxContext 2 | -------------------------------------------------------------------------------- /assets/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MehulG/memX/HEAD/assets/example.gif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dev: 2 | docker-compose up --build 3 | 4 | down: 5 | docker-compose down 6 | -------------------------------------------------------------------------------- /sdk/dist/memx_sdk-0.1.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MehulG/memX/HEAD/sdk/dist/memx_sdk-0.1.1.tar.gz -------------------------------------------------------------------------------- /frontend/memx-frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MehulG/memX/HEAD/frontend/memx-frontend/app/favicon.ico -------------------------------------------------------------------------------- /sdk/dist/memx_sdk-0.1.1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MehulG/memX/HEAD/sdk/dist/memx_sdk-0.1.1-py3-none-any.whl -------------------------------------------------------------------------------- /frontend/memx-frontend/public/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MehulG/memX/HEAD/frontend/memx-frontend/public/example.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__ 2 | /sdk/memx_sdk.egg-info 3 | /sdk/memx_sdk.egg-info 4 | /sdk/memx_sdk/__pycache__ 5 | /frontend/.streamlit 6 | .env -------------------------------------------------------------------------------- /frontend/memx-frontend/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /frontend/memx-frontend/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /frontend/memx-frontend/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/acl.json: -------------------------------------------------------------------------------- 1 | { 2 | "agent_key_1": [ 3 | "memx:query", 4 | "memx:context", 5 | "memx:search_results:0", 6 | "memx:thoughts:0", 7 | "memx:thoughts:1", 8 | "memx:summary" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /frontend/memx-frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // "baseUrl": ".", 4 | "paths": { 5 | // "@/*": ["./*"], 6 | // "@/components/*": ["components/*"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /auth.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | with open("config/acl.json") as f: 4 | acl = json.load(f) 5 | 6 | def is_authorized(api_key, key): 7 | scopes = acl.get(api_key, []) 8 | return any(key.startswith(scope.rstrip("*")) for scope in scopes) 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim 2 | 3 | WORKDIR /app 4 | 5 | # Install dependencies 6 | COPY requirements.txt . 7 | RUN pip install --no-cache-dir -r requirements.txt 8 | 9 | # Copy app code 10 | COPY . . 11 | 12 | EXPOSE 8000 13 | 14 | CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] 15 | -------------------------------------------------------------------------------- /examples/query_agent.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | 3 | ctx = memxContext(api_key="agent_key_1") 4 | 5 | ctx.set("memx:query", "Impacts of open-source LLMs on enterprise adoption") 6 | ctx.set("memx:context", "Customer is preparing a technical brief for leadership") 7 | 8 | print("🧠 QueryAgent: seeded query + context") 9 | -------------------------------------------------------------------------------- /store.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | store = {} 4 | 5 | def get_value(key): 6 | return store.get(key) 7 | 8 | def set_value(key, value): 9 | now = time.time() 10 | prev = store.get(key) 11 | if not prev or now > prev['ts']: 12 | store[key] = {'value': value, 'ts': now} 13 | return True 14 | return False 15 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | memx-backend: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile 6 | container_name: memx-backend 7 | ports: 8 | - "8000:8000" 9 | environment: 10 | SUPABASE_URL: ${SUPABASE_URL} 11 | SUPABASE_SERVICE_KEY: ${SUPABASE_SERVICE_KEY} 12 | restart: unless-stopped 13 | dns: 14 | - 8.8.8.8 15 | -------------------------------------------------------------------------------- /frontend/memx-frontend/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/memx-frontend/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/monitor_agent.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | import time 3 | 4 | ctx = memxContext(api_key="agent_key_1") 5 | 6 | def log(data): 7 | print(f"📡 Monitor saw: {data['key']} → {data['value']}") 8 | 9 | for k in [ 10 | "memx:query", 11 | "memx:context", 12 | "memx:search_results:0", 13 | "memx:summary", 14 | "memx:thoughts:0", 15 | "memx:thoughts:1" 16 | ]: 17 | ctx.subscribe(k, log) 18 | 19 | while True: 20 | time.sleep(1) 21 | -------------------------------------------------------------------------------- /schema.py: -------------------------------------------------------------------------------- 1 | import jsonschema 2 | 3 | schemas = {} 4 | 5 | def register_schema(key, schema_dict): 6 | jsonschema.Draft7Validator.check_schema(schema_dict) 7 | schemas[key] = schema_dict 8 | 9 | def validate_schema(key, value): 10 | schema = schemas.get(key) 11 | if schema: 12 | jsonschema.validate(instance=value, schema=schema) 13 | 14 | def get_schema(key): 15 | return schemas.get(key) 16 | 17 | def delete_schema(key): 18 | return schemas.pop(key, None) 19 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/components/LogoutButton.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"; 3 | 4 | export default function LogoutButton({ onLogout }) { 5 | const supabase = createClientComponentClient(); 6 | 7 | async function handleLogout() { 8 | await supabase.auth.signOut(); 9 | onLogout(); 10 | } 11 | 12 | return ( 13 | 19 | ); 20 | } -------------------------------------------------------------------------------- /pubsub.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | subscriptions = defaultdict(list) 4 | 5 | def subscribe(key, websocket): 6 | subscriptions[key].append(websocket) 7 | 8 | async def publish(key, value): 9 | disconnected = [] 10 | for ws in subscriptions.get(key, []): 11 | try: 12 | await ws.send_json({"key": key, "value": value}) 13 | except Exception as e: 14 | print(f"[WARN] Failed to send to WebSocket: {e}") 15 | disconnected.append(ws) 16 | 17 | # Remove dead sockets 18 | for ws in disconnected: 19 | subscriptions[key].remove(ws) 20 | -------------------------------------------------------------------------------- /frontend/memx-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memx-frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev --turbopack", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@supabase/auth-helpers-nextjs": "^0.10.0", 13 | "next": "15.3.4", 14 | "react": "^19.0.0", 15 | "react-dom": "^19.0.0" 16 | }, 17 | "devDependencies": { 18 | "@tailwindcss/postcss": "^4", 19 | "autoprefixer": "^10.4.21", 20 | "postcss": "^8.5.6", 21 | "tailwindcss": "^4.1.10" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/globals.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | 3 | :root { 4 | --background: #ffffff; 5 | --foreground: #171717; 6 | } 7 | 8 | @theme inline { 9 | --color-background: var(--background); 10 | --color-foreground: var(--foreground); 11 | --font-sans: var(--font-geist-sans); 12 | --font-mono: var(--font-geist-mono); 13 | } 14 | 15 | @media (prefers-color-scheme: dark) { 16 | :root { 17 | --background: #0a0a0a; 18 | --foreground: #ededed; 19 | } 20 | } 21 | 22 | body { 23 | background: var(--background); 24 | color: var(--foreground); 25 | font-family: Arial, Helvetica, sans-serif; 26 | } 27 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/components/Header.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import LogoutButton from "./LogoutButton"; 3 | 4 | export default function Header({ onLogout, showLogout = true }) { 5 | return ( 6 |
7 |
8 | 9 |

memX

10 |

A real-time shared memory layer for multi-agent LLM systems.

11 |
12 |
13 | {showLogout && } 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /sdk/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "memx-sdk" 3 | version = "0.1.1" 4 | description = "Python client for memX shared memory platform" 5 | authors = [{ name="Mehul", email="memx.founders@gmail.com" }] 6 | license = { text = "MIT" } 7 | readme = "README.md" 8 | requires-python = ">=3.8" 9 | dependencies = [ 10 | "httpx>=0.24.0", 11 | "websockets", 12 | "hatchling (>=1.27.0,<2.0.0)" 13 | ] 14 | 15 | [build-system] 16 | requires = ["hatchling"] 17 | build-backend = "hatchling.build" 18 | 19 | [project.urls] 20 | "Homepage" = "https://github.com/MehulG/memx" 21 | "Repository" = "https://github.com/MehulG/memx" 22 | "Documentation" = "https://github.com/MehulG/memx#readme" -------------------------------------------------------------------------------- /sdk/memx_sdk/test_client.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | import time 3 | 4 | schema = { 5 | "type": "object", 6 | "properties": { "x": { "type": "number" }, "y": { "type": "number" } }, 7 | "required": ["x", "y"] 8 | } 9 | ctx = memxContext(api_key="agent_key_1") 10 | 11 | 12 | ctx.set_schema("agent:state", schema) 13 | print(ctx.get_schema("agent:state")) 14 | # ctx.delete_schema("agent:state") 15 | 16 | 17 | def on_update(data): 18 | print("🔥 Update received:", data) 19 | 20 | ctx.subscribe("agent:goal", on_update) 21 | 22 | ctx.set("agent:goal", "go to kitchen") 23 | time.sleep(1) 24 | ctx.set("agent:goal", "go to hallway") 25 | time.sleep(3) 26 | 27 | 28 | -------------------------------------------------------------------------------- /frontend/memx-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "memx" 3 | version = "0.1.0" 4 | description = "" 5 | authors = [ 6 | {name = "Mehul Gaidhani",email = "mehulgaidhani@gmail.com"} 7 | ] 8 | readme = "README.md" 9 | requires-python = ">=3.12,<4.0" 10 | dependencies = [ 11 | "fastapi[all] (>=0.115.12,<0.116.0)", 12 | "jsonschema (>=4.24.0,<5.0.0)", 13 | "requests (>=2.32.4,<3.0.0)", 14 | "supabase (>=2.15.3,<3.0.0)", 15 | "streamlit (>=1.46.0,<2.0.0)", 16 | "python-dotenv (>=1.1.1,<2.0.0)", 17 | "hatchling (>=1.27.0,<2.0.0)" 18 | ] 19 | 20 | 21 | [build-system] 22 | requires = ["poetry-core>=2.0.0,<3.0.0"] 23 | build-backend = "poetry.core.masonry.api" 24 | 25 | [tool.poetry.requires-plugins] 26 | poetry-plugin-export = ">=1.8" -------------------------------------------------------------------------------- /frontend/memx-frontend/app/layout.js: -------------------------------------------------------------------------------- 1 | import { Geist, Geist_Mono } from "next/font/google"; 2 | import "./globals.css"; 3 | 4 | const geistSans = Geist({ 5 | variable: "--font-geist-sans", 6 | subsets: ["latin"], 7 | }); 8 | 9 | const geistMono = Geist_Mono({ 10 | variable: "--font-geist-mono", 11 | subsets: ["latin"], 12 | }); 13 | 14 | export const metadata = { 15 | title: "memX", 16 | description: "A real-time shared memory layer for multi-agent LLM systems.", 17 | }; 18 | 19 | export default function RootLayout({ children }) { 20 | return ( 21 | 22 | 25 | {children} 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /examples/test.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | 3 | 4 | ctx = memxContext(api_key="74748d89f9cef9987ecc9dbe16b72daf") 5 | 6 | ctx.set_schema("agent:goal", { 7 | "type": "object", 8 | "properties": { 9 | "x": { "type": "number" }, 10 | "y": { "type": "number" } 11 | }, 12 | "required": ["x", "y"] 13 | }) 14 | 15 | get1 = ctx.get("agent:goal") 16 | 17 | print(get1) 18 | 19 | ctx.set("agent:goal", {"x":1, "y":7}) 20 | 21 | get2 = ctx.get("agent:goal") 22 | 23 | print(get2) 24 | 25 | for i in range(0,10): 26 | ctx.set_schema("agent:goal:"+str(i), { 27 | "type": "object", 28 | "properties": { 29 | "x": { "type": "number" }, 30 | "y": { "type": "number" } 31 | }, 32 | "required": ["x", "y"] 33 | }) 34 | ctx.set("agent:goal"+str(i), {"x":i, "y":i*2}) 35 | get1 = ctx.get("agent:goal"+str(i)) 36 | 37 | print(get1) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/login/page.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState, useCallback } from "react"; 3 | import AuthForm from "../components/AuthForm"; 4 | import KeyViewer from "../components/KeyViewer"; 5 | import CreateKeyForm from "../components/CreateKeyForm"; 6 | import Header from "../components/Header"; 7 | 8 | export default function Login() { 9 | const [session, setSession] = useState(null); 10 | const [reload, setReload] = useState(0); 11 | 12 | const triggerReload = useCallback(() => { 13 | setReload((prev) => prev + 1); 14 | }, []); 15 | 16 | if (!session) { 17 | return ; 18 | } 19 | 20 | return ( 21 |
22 |
setSession(null)} /> 23 | 24 | 25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /frontend/memx-frontend/public/globe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Mehul Gaidhani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /sdk/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Mehul Gaidhani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the “Software”), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /frontend/memx-frontend/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/memx-frontend/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 37 | -------------------------------------------------------------------------------- /sdk/README.md: -------------------------------------------------------------------------------- 1 | # 🧠 memx-sdk 2 | 3 | A Python client for [memX](https://github.com/MehulG/memX) — a real-time shared memory layer for multi-agent LLM systems. 4 | 5 | Built for fast, schema-validated coordination between autonomous agents. Supports JSON key/value operations, schema enforcement, and pub/sub via WebSocket. 6 | 7 | --- 8 | 9 | ## 🚀 Features 10 | 11 | - 🔑 Authenticate via API keys 12 | - 📥 Get/set JSON values by key 13 | - 📐 Define and validate key schemas 14 | - 🔄 Real-time memory sync via WebSocket 15 | - 🔔 Pub/sub for key-level updates 16 | 17 | --- 18 | 19 | ## 📦 Installation 20 | 21 | ```bash 22 | pip install memx-sdk 23 | ``` 24 | 25 | ## 🧪 Usage Example 26 | 27 | Log in to [dashboard](https://mem-x.vercel.app) and create api keys with relevent scopes. 28 | 29 | ```python 30 | from memx_sdk import memxContext 31 | 32 | client = memxContext(api_key="your-api-key") 33 | 34 | # Define schema 35 | client.set_schema("agent:goal", { 36 | "type": "object", 37 | "properties": { "x": { "type": "number" }, "y": { "type": "number" } }, 38 | "required": ["x", "y"] 39 | }) 40 | 41 | # Set a value 42 | client.set("agent:goal", {"x": 3, "y": 5}) 43 | 44 | # Get a value 45 | value = client.get("agent:goal") 46 | print(value) 47 | 48 | # Subscribe to updates 49 | def on_update(data): 50 | print("Updated:", data) 51 | 52 | client.subscribe("agent:goal", callback=on_update) 53 | ``` 54 | 55 | ## 🛠️ Requirements 56 | - Python 3.7+ 57 | - httpx 58 | - websockets 59 | 60 | ## 📄 License 61 | MIT 62 | 63 | ## 🧠 Learn More 64 | - Dashboard: https://mem-x.vercel.app 65 | - Project: [memX README](https://github.com/MehulG/memX) -------------------------------------------------------------------------------- /examples/explorer_agent.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | import time 3 | import requests 4 | 5 | ctx = memxContext(api_key="agent_key_1") 6 | 7 | query_handled = False 8 | summary_handled = False 9 | 10 | def call_mistral(prompt: str) -> str: 11 | res = requests.post("http://localhost:11434/api/generate", json={ 12 | "model": "mistral", 13 | "prompt": prompt, 14 | "stream": False 15 | }) 16 | return res.json()["response"].strip() if res.status_code == 200 else "LLM error." 17 | 18 | def on_memory(data): 19 | global query_handled, summary_handled 20 | 21 | key, value = data["key"], data["value"] 22 | 23 | if key == "memx:query" and not query_handled: 24 | context = ctx.get("memx:context")["value"] 25 | prompt = f"""You are a research assistant. 26 | Given the query: "{value}" and context: "{context}", list one relevant source and one key observation.""" 27 | print("🔍 ExplorerAgent: generating initial info with Mistral...") 28 | output = call_mistral(prompt) 29 | ctx.set("memx:search_results:0", output) 30 | ctx.set("memx:thoughts:0", f"Initial observation: {output}") 31 | query_handled = True 32 | 33 | elif key == "memx:summary" and not summary_handled: 34 | prompt = f"""You are a second-pass reviewer. 35 | Based on this summary: "{value}", what additional consideration should be mentioned?""" 36 | print("🔄 ExplorerAgent: reacting to summary via Mistral...") 37 | thought = call_mistral(prompt) 38 | ctx.set("memx:thoughts:1", f"Follow-up observation: {thought}") 39 | summary_handled = True 40 | 41 | ctx.subscribe("memx:query", on_memory) 42 | ctx.subscribe("memx:summary", on_memory) 43 | 44 | while True: 45 | time.sleep(1) 46 | -------------------------------------------------------------------------------- /validate_api.py: -------------------------------------------------------------------------------- 1 | import fnmatch 2 | from fastapi import Request, HTTPException, WebSocket 3 | from supabase import create_client 4 | import os 5 | from dotenv import load_dotenv 6 | load_dotenv() 7 | 8 | supabase = create_client(os.getenv("SUPABASE_URL"), os.getenv("SUPABASE_SERVICE_KEY")) 9 | 10 | def _check_scope(scopes: dict, action: str, key: str, user_id: str): 11 | namespaced_key = f"{user_id[:8]}:{key}" 12 | return any(fnmatch.fnmatch(namespaced_key, pattern) for pattern in scopes.get(action, [])) 13 | 14 | async def validate_api_key(request: Request, key: str, action: str = "write"): 15 | api_key = request.headers.get("x-api-key") 16 | if not api_key: 17 | raise HTTPException(status_code=401, detail="Missing API key") 18 | 19 | res = supabase.from_("api_keys").select("*").eq("key", api_key).eq("active", True).execute() 20 | if not res.data: 21 | raise HTTPException(status_code=403, detail="Invalid or inactive API key") 22 | 23 | record = res.data[0] 24 | scopes = record.get("scopes", {}) 25 | user_id = record.get("user_id", "") 26 | 27 | if not _check_scope(scopes, action, key, user_id): 28 | raise HTTPException(status_code=403, detail=f"{action.upper()} not permitted for key '{key}'") 29 | 30 | request.state.api_key = record 31 | 32 | async def validate_websocket(websocket: WebSocket, key: str) -> bool: 33 | api_key = websocket.headers.get("x-api-key") 34 | if not api_key: 35 | await websocket.close(code=4401, reason="Missing API key") 36 | return False 37 | 38 | res = supabase.table("api_keys").select("*").eq("key", api_key).eq("active", True).execute() 39 | if not res.data: 40 | await websocket.close(code=4403, reason="Invalid API key") 41 | return False 42 | 43 | record = res.data[0] 44 | scopes = record.get("scopes", {}) 45 | user_id = record.get("user_id", "") 46 | 47 | if not _check_scope(scopes, "read", key, user_id): 48 | await websocket.close(code=4403, reason="Unauthorized to subscribe to this key") 49 | return False 50 | 51 | return True 52 | -------------------------------------------------------------------------------- /examples/synthesizer_agent.py: -------------------------------------------------------------------------------- 1 | from memx_sdk import memxContext 2 | import time 3 | import requests 4 | import hashlib 5 | 6 | ctx = memxContext(api_key="agent_key_1") 7 | last_summary_hash = None 8 | final_summary = '' 9 | count = 0 10 | def hash_text(text): 11 | return hashlib.sha256(text.encode()).hexdigest() 12 | 13 | def call_mistral(prompt: str) -> str: 14 | try: 15 | res = requests.post("http://localhost:11434/api/generate", json={ 16 | "model": "mistral", 17 | "prompt": prompt, 18 | "stream": False 19 | }) 20 | res.raise_for_status() 21 | return res.json()["response"].strip() 22 | except Exception as e: 23 | print("❌ Mistral error:", e) 24 | return "LLM error." 25 | 26 | def summarize(): 27 | global last_summary_hash 28 | global final_summary 29 | global count 30 | try: 31 | query = ctx.get("memx:query")["value"] 32 | results = ctx.get("memx:search_results:0")["value"] 33 | thoughts = [ctx.get("memx:thoughts:0")["value"]] 34 | try: 35 | thoughts.append(ctx.get("memx:thoughts:1")["value"]) 36 | except: 37 | pass # optional follow-up thought 38 | except: 39 | print("⏳ Waiting for all inputs...") 40 | return 41 | 42 | prompt = f"""You are a summarizer agent. 43 | 44 | Based on the following: 45 | - Query: {query} 46 | - Search Result: {results} 47 | - Thoughts: 48 | {"".join(f"- {t}\n" for t in thoughts)} 49 | 50 | Write a final 2-sentence summary suitable for a leadership audience. 51 | """ 52 | 53 | print("🧠 SynthesizerAgent: summarizing via Mistral...") 54 | summary = call_mistral(prompt) 55 | summary_hash = hash_text(summary) 56 | 57 | if summary_hash != last_summary_hash: 58 | ctx.set("memx:summary", summary) 59 | last_summary_hash = summary_hash 60 | final_summary = summary 61 | count += 1 62 | if count > 1: 63 | print("✅ Final summary written:\n", final_summary, "\n") 64 | else: 65 | print("⚠️ Summary unchanged — skipping write.") 66 | 67 | def on_data(_): 68 | summarize() 69 | 70 | # ctx.subscribe("memx:search_results:0", on_data) 71 | ctx.subscribe("memx:thoughts:0", on_data) 72 | ctx.subscribe("memx:thoughts:1", on_data) 73 | 74 | 75 | 76 | while True: 77 | time.sleep(1) 78 | -------------------------------------------------------------------------------- /sdk/memx_sdk/client.py: -------------------------------------------------------------------------------- 1 | import httpx 2 | import asyncio 3 | import websockets 4 | import threading 5 | import json 6 | 7 | class memxContext: 8 | def __init__(self, api_key, base_url="https://memx-production.up.railway.app"): 9 | self.api_key = api_key 10 | self.base_url = base_url 11 | 12 | def set(self, key, value): 13 | res = httpx.post( 14 | f"{self.base_url}/set", 15 | headers={"x-api-key": self.api_key}, 16 | json={"key": key, "value": value} 17 | ) 18 | res.raise_for_status() 19 | return res.json() 20 | 21 | def get(self, key): 22 | res = httpx.get( 23 | f"{self.base_url}/get", 24 | headers={"x-api-key": self.api_key}, 25 | params={"key": key} 26 | ) 27 | res.raise_for_status() 28 | return res.json() 29 | 30 | def subscribe(self, key, callback): 31 | def _listen(): 32 | uri = f"{self.base_url.replace('http', 'ws')}/subscribe/{key}" 33 | async def _inner(): 34 | async with websockets.connect(uri, additional_headers={"x-api-key": self.api_key}) as ws: 35 | while True: 36 | try: 37 | msg = await ws.recv() 38 | data = json.loads(msg) 39 | callback(data) 40 | except Exception as e: 41 | print("[WebSocket error]", e) 42 | break 43 | asyncio.run(_inner()) 44 | 45 | thread = threading.Thread(target=_listen, daemon=True) 46 | thread.start() 47 | 48 | def set_schema(self, key, schema): 49 | res = httpx.post( 50 | f"{self.base_url}/schema", 51 | headers={"x-api-key": self.api_key}, 52 | json={"key": key, "schema": schema} 53 | ) 54 | res.raise_for_status() 55 | return res.json() 56 | 57 | def get_schema(self, key): 58 | res = httpx.get( 59 | f"{self.base_url}/schema", 60 | headers={"x-api-key": self.api_key}, 61 | params={"key": key} 62 | ) 63 | res.raise_for_status() 64 | return res.json() 65 | 66 | def delete_schema(self, key): 67 | res = httpx.delete( 68 | f"{self.base_url}/schema", 69 | headers={"x-api-key": self.api_key}, 70 | params={"key": key} 71 | ) 72 | res.raise_for_status() 73 | return res.json() 74 | 75 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, WebSocket, Request, HTTPException 2 | from store import get_value, set_value 3 | from pubsub import subscribe, publish 4 | from schema import register_schema, validate_schema, get_schema, delete_schema 5 | import asyncio 6 | import jsonschema 7 | import validate_api 8 | 9 | app = FastAPI() 10 | 11 | @app.get("/get") 12 | async def get(key: str, request: Request): 13 | await validate_api.validate_api_key(request, key, action="read") 14 | return get_value(key) 15 | 16 | @app.post("/set") 17 | async def set(request: Request): 18 | body = await request.json() 19 | value = body["value"] 20 | key = body["key"] 21 | 22 | await validate_api.validate_api_key(request, key, action="write") 23 | 24 | try: 25 | validate_schema(key, value) 26 | except jsonschema.exceptions.ValidationError as e: 27 | raise HTTPException(400, detail=str(e)) 28 | 29 | updated = set_value(key, value) 30 | if updated: 31 | await publish(key, value) 32 | 33 | return {"ok": True, "updated": updated} 34 | 35 | @app.websocket("/subscribe/{key}") 36 | async def websocket_endpoint(websocket: WebSocket, key: str): 37 | await websocket.accept() 38 | if not await validate_api.validate_websocket(websocket, key): 39 | return 40 | print(f"[WebSocket] Subscribed to {key}") 41 | subscribe(key, websocket) 42 | try: 43 | while True: 44 | await asyncio.sleep(1) 45 | except: 46 | print(f"[WebSocket] closed: {key}") 47 | 48 | @app.post("/schema") 49 | async def set_schema(request: Request): 50 | body = await request.json() 51 | key = body["key"] 52 | schema = body["schema"] 53 | 54 | await validate_api.validate_api_key(request, key, action="write") 55 | 56 | try: 57 | register_schema(key, schema) 58 | except jsonschema.exceptions.SchemaError as e: 59 | raise HTTPException(400, detail=f"Invalid schema: {e}") 60 | return {"ok": True} 61 | 62 | @app.get("/schema") 63 | async def fetch_schema(key: str, request: Request): 64 | await validate_api.validate_api_key(request, key, action="read") 65 | schema = get_schema(key) 66 | if not schema: 67 | raise HTTPException(404, detail="Schema not found") 68 | return {"key": key, "schema": schema} 69 | 70 | @app.delete("/schema") 71 | async def remove_schema(key: str, request: Request): 72 | await validate_api.validate_api_key(request, key, action="write") 73 | deleted = delete_schema(key) 74 | if not deleted: 75 | raise HTTPException(404, detail="Schema not found") 76 | return {"ok": True} 77 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/components/KeyViewer.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useEffect, useState } from "react"; 3 | import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"; 4 | 5 | export default function KeyViewer({ session }) { 6 | const supabase = createClientComponentClient(); 7 | const [keys, setKeys] = useState([]); 8 | const [loading, setLoading] = useState(true); 9 | const [deleting, setDeleting] = useState(null); 10 | 11 | const fetchKeys = async () => { 12 | setLoading(true); 13 | const { data } = await supabase.from("api_keys").select("*"); 14 | setKeys(data || []); 15 | setLoading(false); 16 | }; 17 | 18 | useEffect(() => { 19 | fetchKeys(); 20 | }, []); 21 | 22 | const deleteKey = async (key) => { 23 | setDeleting(key); 24 | await supabase.from("api_keys").delete().eq("key", key); 25 | setDeleting(null); 26 | fetchKeys(); 27 | }; 28 | 29 | const userPrefix = session.user.id.slice(0, 8); 30 | 31 | return ( 32 |
33 |

🔑 Your API Keys

34 |

Namespace: {userPrefix}

35 | {loading ? ( 36 |

Loading keys...

37 | ) : keys.length === 0 ? ( 38 |

No keys found.

39 | ) : ( 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {keys.map((k) => ( 53 | 54 | 55 | 56 | 57 | 58 | 59 | 68 | 69 | ))} 70 | 71 |
NameKeyRead ScopeWrite ScopeCreated AtActions
{k.name}{k.key}{k.scopes.read?.join(", ")}{k.scopes.write?.join(", ")}{new Date(k.created_at).toLocaleString()} 60 | 67 |
72 | )} 73 |
74 | ); 75 | } -------------------------------------------------------------------------------- /frontend/memx-frontend/app/components/CreateKeyForm.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"; 4 | 5 | export default function CreateKeyForm({ session, onCreated }) { 6 | const supabase = createClientComponentClient(); 7 | const [name, setName] = useState(""); 8 | const [readScope, setReadScope] = useState("agent:*"); 9 | const [writeScope, setWriteScope] = useState("agent:goal"); 10 | const [status, setStatus] = useState(null); 11 | const [loading, setLoading] = useState(false); 12 | 13 | const userPrefix = session.user.id.slice(0, 8); 14 | 15 | async function handleCreate(e) { 16 | e.preventDefault(); 17 | setLoading(true); 18 | const apiKey = crypto.randomUUID().replace(/-/g, "").slice(0, 32); 19 | const scopes = { 20 | read: readScope.split(",").map((s) => `${userPrefix}:${s.trim()}`), 21 | write: writeScope.split(",").map((s) => `${userPrefix}:${s.trim()}`), 22 | }; 23 | 24 | const { error } = await supabase.rpc("create_api_key", { 25 | key_name: name, 26 | key_value: apiKey, 27 | scopes, 28 | is_active: true, 29 | }); 30 | 31 | if (error) { 32 | setStatus(`Error: ${error.message}`); 33 | } else { 34 | setStatus(`API Key Created: ${apiKey}`); 35 | setName(""); 36 | setReadScope("agent:*"); 37 | setWriteScope("agent:goal"); 38 | if (onCreated) onCreated(); 39 | } 40 | setLoading(false); 41 | } 42 | 43 | return ( 44 |
45 |

➕ Create New API Key

46 | Key name: 47 | setName(e.target.value)} 52 | required 53 | /> 54 | Read scope (comma separated): 55 | setReadScope(e.target.value)} 60 | required 61 | /> 62 | Write scope (comma separated): 63 | setWriteScope(e.target.value)} 68 | required 69 | /> 70 | 77 | {status &&

{status}

} 78 |
79 | ); 80 | } 81 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/components/AuthForm.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useState } from "react"; 3 | import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"; 4 | import Header from "./Header"; 5 | 6 | export default function AuthForm({ onAuth }) { 7 | const supabase = createClientComponentClient(); 8 | const [email, setEmail] = useState(""); 9 | const [password, setPassword] = useState(""); 10 | const [mode, setMode] = useState("login"); 11 | const [error, setError] = useState(null); 12 | const [info, setInfo] = useState(null); 13 | const [loading, setLoading] = useState(false); 14 | 15 | async function handleSubmit(e) { 16 | e.preventDefault(); 17 | setError(null); 18 | setInfo(null); 19 | setLoading(true); 20 | try { 21 | if (mode === "login") { 22 | const { data, error } = await supabase.auth.signInWithPassword({ email, password }); 23 | if (error) throw error; 24 | onAuth(data.session); 25 | } else { 26 | const { error: signupError } = await supabase.auth.signUp({ email, password }); 27 | if (signupError) throw signupError; 28 | setInfo("Signed up successfully. Please check your email to confirm your account."); 29 | } 30 | } catch (err) { 31 | setError(err.message); 32 | } finally { 33 | setLoading(false); 34 | } 35 | } 36 | 37 | return ( 38 |
39 |
40 |
41 |
42 |

{mode === "login" ? "Login" : "Signup"}

43 |
44 | setEmail(e.target.value)} 50 | required 51 | /> 52 | setPassword(e.target.value)} 58 | required 59 | /> 60 | 67 | {error &&

{error}

} 68 | {info &&

{info}

} 69 |
70 |

71 | {mode === "login" ? "Don't have an account?" : "Already have an account?"} {" "} 72 | 79 |

80 |
81 |
82 |
83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /frontend/memx-frontend/app/page.js: -------------------------------------------------------------------------------- 1 | export default function LandingPage() { 2 | return ( 3 |
4 | {/* Hero Section */} 5 |
6 |

🧠 memX

7 |

8 | Real-time shared memory for multi-agent LLM systems: no chat, no controller. 9 |

10 |

11 | No setup. Free to use. Just shared memory between agents. 12 |

13 | 14 |
15 | 19 | Get Started 20 | 21 | 25 | GitHub 26 | 27 |
28 |
29 | 30 | {/* Features */} 31 |
32 |

⚡ Why memX?

33 |
    34 |
  • Real-time shared key-value store
  • 35 |
  • Pub/Sub updates across agents
  • 36 |
  • JSON Schema enforcement
  • 37 |
  • API-key-based access control
  • 38 |
39 |
40 | 41 | {/* Quickstart */} 42 |
43 |

🚀 Quickstart

44 |
    45 |
  1. Install SDK: pip install memx_sdk
  2. 46 |
  3. Get your API key
  4. 47 |
  5. Start coding:
  6. 48 |
49 |
50 |           {`from memx_sdk import memxContext
51 | 
52 | ctx = memxContext(api_key="your_api_key")
53 | 
54 | ctx.set_schema("agent:goal", {
55 |   "type": "object",
56 |   "properties": {"x": {"type": "number"}, "y": {"type": "number"}},
57 |   "required": ["x", "y"]
58 | })
59 | 
60 | ctx.set("agent:goal", {"x": 1, "y": 7})
61 | print(ctx.get("agent:goal"))
62 | `}
63 |         
64 |
65 | 66 | {/* Agent Table */} 67 |
68 |

🧬 Example: Multi Agents, One Memory

69 | memX demo 74 | 75 |
76 | 77 | 78 | 79 | {/* Use Cases */} 80 |
81 |

🌐 Use Cases

82 |
    83 |
  • Autonomous research agents
  • 84 |
  • LangGraph / CrewAI memory plugins
  • 85 |
  • LLM workflows with persistent state
  • 86 |
87 |
88 | 89 | {/* Footer */} 90 | 94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /frontend/streamlit.py: -------------------------------------------------------------------------------- 1 | # memX Streamlit Dashboard MVP 2 | 3 | import streamlit as st 4 | import secrets 5 | import json 6 | import time 7 | import pandas as pd 8 | from supabase import create_client, Client, ClientOptions 9 | 10 | # --- Setup --- 11 | SUPABASE_URL = st.secrets["SUPABASE_URL"] 12 | SUPABASE_KEY = st.secrets["SUPABASE_SERVICE_KEY"] 13 | 14 | # Initialize temporary client for login/signup 15 | supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) 16 | 17 | # --- Auth (signup/login) --- 18 | st.title("🔐 memX Dashboard") 19 | if "session" not in st.session_state: 20 | st.session_state.session = None 21 | if "auth_mode" not in st.session_state: 22 | st.session_state.auth_mode = "login" 23 | 24 | st.sidebar.title("Account") 25 | auth_mode = st.sidebar.radio("Select Mode", ["login", "signup"]) 26 | st.session_state.auth_mode = auth_mode 27 | 28 | if not st.session_state.session: 29 | with st.form("Auth"): 30 | email = st.text_input("Email") 31 | password = st.text_input("Password", type="password") 32 | submitted = st.form_submit_button("Submit") 33 | if submitted: 34 | try: 35 | if st.session_state.auth_mode == "login": 36 | session = supabase.auth.sign_in_with_password({"email": email, "password": password}) 37 | st.session_state.session = session 38 | st.success(f"Logged in as {email}") 39 | time.sleep(1) 40 | st.rerun() 41 | else: 42 | session = supabase.auth.sign_up({"email": email, "password": password}) 43 | st.success(f"Signed up as {email}. Please check your email to confirm.") 44 | st.session_state.session = session 45 | time.sleep(1) 46 | st.rerun() 47 | except Exception as e: 48 | st.error("{} failed: {}".format(st.session_state.auth_mode.capitalize(), str(e))) 49 | st.stop() 50 | 51 | access_token = st.session_state.session.session.access_token 52 | supabase = create_client( 53 | SUPABASE_URL, 54 | SUPABASE_KEY, 55 | options=ClientOptions(headers={"Authorization": f"Bearer {access_token}"}) 56 | ) 57 | 58 | user_id = st.session_state.session.user.id 59 | user_prefix = user_id[:8] # used to namespace scope keys 60 | 61 | # --- API Key Viewer --- 62 | st.header("🔑 Your API Keys") 63 | st.caption(f"🔒 Namespace: `{user_prefix}` (automatically applied to all scopes)") 64 | 65 | keys = supabase.table("api_keys").select("*").execute() 66 | if keys.data: 67 | table_data = [ 68 | { 69 | "Key": k["key"], 70 | "Read Scope": ", ".join(k["scopes"].get("read", [])), 71 | "Write Scope": ", ".join(k["scopes"].get("write", [])), 72 | "Created At": k["created_at"] 73 | } 74 | for k in keys.data 75 | ] 76 | df = pd.DataFrame(table_data) 77 | st.dataframe(df) 78 | else: 79 | st.info("No keys found.") 80 | 81 | # --- API Key Creator --- 82 | st.header("➕ Create New API Key") 83 | 84 | with st.form("create_key"): 85 | key_name = st.text_input("Name") 86 | read_scope = st.text_input("Read scope (comma-separated)", "agent:*") 87 | write_scope = st.text_input("Write scope (comma-separated)", "agent:goal") 88 | submit_key = st.form_submit_button("Create") 89 | 90 | if submit_key: 91 | api_key = secrets.token_hex(16) 92 | scopes = { 93 | "read": [f"{user_prefix}:{s.strip()}" for s in read_scope.split(",")], 94 | "write": [f"{user_prefix}:{s.strip()}" for s in write_scope.split(",")] 95 | } 96 | supabase.rpc("create_api_key", { 97 | "key_name": key_name, 98 | "key_value": api_key, 99 | "scopes": scopes, 100 | "is_active": True 101 | }).execute() 102 | st.success("API Key Created: {}".format(api_key)) 103 | 104 | # --- Memory Viewer (Optional) --- 105 | # You could add polling here to connect to your FastAPI memX backend 106 | # and display live key-value state or pub/sub logs. 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧠 memX: Shared Memory for Multi-Agent LLM Systems 2 | 3 | **memX** is an open-source real-time shared memory layer designed for agent-based systems powered by LLMs. It enables **coordination-first workflows** via: 4 | 5 | * ⚡ Real-time CRDT-style state sync 6 | * 📐 JSON Schema enforcement for data sanity 7 | * 🔐 API-key-based access control 8 | * 📣 Pub/Sub updates for reactive agents 9 | 10 | --- 11 | 12 | ## 🔍 What Problem Does memX Solve? 13 | 14 | Modern multi-agent setups—whether using LangGraph, Autogen, or custom orchestration—lack a reliable way to **share evolving context** (state, goals, thoughts) between agents. memX provides a simple and secure memory layer that agents can read/write from in real-time — no message-passing or controller required. 15 | 16 | --- 17 | 18 | ## 🤖 Example: Collaborative LLM Agents Using memX 19 | 20 | Three autonomous agents solving a research task, fully decentralized: 21 | 22 | | Agent | Behavior | 23 | | ------------------ | ---------------------------------------------------- | 24 | | `QueryAgent` | Seeds the research question + background context | 25 | | `ExplorerAgent` | Adds search results + working notes | 26 | | `SynthesizerAgent` | Summarizes the shared context into final insights | 27 | | `MonitorAgent` | Logs real-time evolution of memory for observability | 28 | 29 | > All communication flows through **shared keys** in memX — not through chat or a controller. 30 | 31 | ![memX agent demo](./assets/example.gif) 32 | 33 | --- 34 | 35 | ## 🚀 Features at a Glance 36 | 37 | ✅ Real-time memory sync (WebSocket) 38 | 📬 Pub/Sub updates on change 39 | 📐 Per-key JSON Schema validation 40 | 🔐 Fine-grained ACLs via API keys 41 | 🐍 Python SDK (`memx-sdk`) for easy integration 42 | 🐳 Docker-compatible for local hosting or cloud deployment 43 | 44 | --- 45 | 46 | ## ⚡ Quickstart 47 | 48 | ### 1. Install the SDK 49 | 50 | ```bash 51 | pip install memx-sdk 52 | ``` 53 | 54 | ### 2. Generate an API Key 55 | 56 | Visit: [mem-x.vercel.com](https://mem-x.vercel.com) 57 | Generate scoped API keys with just a few clicks. 58 | 59 | ### 3. Use in Python 60 | 61 | ```python 62 | from memx_sdk import memxContext 63 | 64 | ctx = memxContext(api_key="your_api_key") 65 | 66 | ctx.set_schema("agent:goal", { 67 | "type": "object", 68 | "properties": {"x": {"type": "number"}, "y": {"type": "number"}}, 69 | "required": ["x", "y"] 70 | }) 71 | 72 | ctx.set("agent:goal", {"x": 1, "y": 7}) 73 | print(ctx.get("agent:goal")) 74 | ``` 75 | 76 | --- 77 | 78 | ## 🧰 Running memX Locally 79 | 80 | ### Option 1: Dev Server 81 | 82 | ```bash 83 | uvicorn main:app --reload 84 | ``` 85 | 86 | ### Option 2: Docker 87 | 88 | ```bash 89 | docker-compose up --build 90 | ``` 91 | 92 | Swagger docs: [http://localhost:8000/docs](http://localhost:8000/docs) 93 | 94 | --- 95 | 96 | ## 🔑 API Key Management 97 | 98 | ### Hosted 99 | 100 | 1. Log in at [mem-x.vercel.com](https://mem-x.vercel.com) 101 | 2. Generate API keys with scoped access control 102 | 103 | ### Local Config 104 | 105 | Edit `config/acl.json` to define access scopes: 106 | 107 | ```json 108 | { 109 | "agent_key_1": ["agent:*"], 110 | "planner_key": ["agent:goal"] 111 | } 112 | ``` 113 | 114 | --- 115 | 116 | ## 📐 Define Schemas (Optional but Recommended) 117 | 118 | Set schema for a key via API: 119 | 120 | ```bash 121 | POST /schema 122 | Headers: x-api-key: your_key 123 | Body: 124 | { 125 | "key": "agent:state", 126 | "schema": { 127 | "type": "object", 128 | "properties": {"x": {"type": "number"}, "y": {"type": "number"}}, 129 | "required": ["x", "y"] 130 | } 131 | } 132 | ``` 133 | 134 | Or via SDK: 135 | 136 | ```python 137 | ctx.set_schema("agent:state", schema_dict) 138 | ``` 139 | 140 | --- 141 | 142 | ## 🗂 Project Structure 143 | 144 | ``` 145 | core/ # FastAPI + WebSocket backend 146 | sdk/ # Python SDK (pip installable) 147 | config/ # Access control & schemas 148 | examples/ # LLM agent integration demos 149 | ``` 150 | 151 | --- 152 | 153 | ## 🌐 Use Cases 154 | 155 | * LangGraph / Autogen workflows with shared memory 156 | * Autonomous research or planning agents 157 | * IoT / robotics with real-time state coordination 158 | * Any multi-agent system needing structured memory 159 | 160 | --- 161 | 162 | ## 📣 Join Us 163 | 164 | memX is built for developers pushing the frontier of multi-agent systems. 165 | Explore the SDK, try out agent demos, and contribute! 166 | 167 | --- 168 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohappyeyeballs==2.6.1 ; python_version >= "3.12" and python_version < "4.0" 2 | aiohttp==3.12.13 ; python_version >= "3.12" and python_version < "4.0" 3 | aiosignal==1.3.2 ; python_version >= "3.12" and python_version < "4.0" 4 | altair==5.5.0 ; python_version >= "3.12" and python_version < "4.0" 5 | annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "4.0" 6 | anyio==4.9.0 ; python_version >= "3.12" and python_version < "4.0" 7 | attrs==25.3.0 ; python_version >= "3.12" and python_version < "4.0" 8 | blinker==1.9.0 ; python_version >= "3.12" and python_version < "4.0" 9 | cachetools==6.1.0 ; python_version >= "3.12" and python_version < "4.0" 10 | certifi==2025.4.26 ; python_version >= "3.12" and python_version < "4.0" 11 | charset-normalizer==3.4.2 ; python_version >= "3.12" and python_version < "4.0" 12 | click==8.2.1 ; python_version >= "3.12" and python_version < "4.0" 13 | colorama==0.4.6 ; python_version >= "3.12" and python_version < "4.0" and (platform_system == "Windows" or sys_platform == "win32") 14 | deprecation==2.1.0 ; python_version >= "3.12" and python_version < "4.0" 15 | dnspython==2.7.0 ; python_version >= "3.12" and python_version < "4.0" 16 | email-validator==2.2.0 ; python_version >= "3.12" and python_version < "4.0" 17 | fastapi-cli==0.0.7 ; python_version >= "3.12" and python_version < "4.0" 18 | fastapi==0.115.12 ; python_version >= "3.12" and python_version < "4.0" 19 | frozenlist==1.7.0 ; python_version >= "3.12" and python_version < "4.0" 20 | gitdb==4.0.12 ; python_version >= "3.12" and python_version < "4.0" 21 | gitpython==3.1.44 ; python_version >= "3.12" and python_version < "4.0" 22 | gotrue==2.12.0 ; python_version >= "3.12" and python_version < "4.0" 23 | h11==0.16.0 ; python_version >= "3.12" and python_version < "4.0" 24 | h2==4.2.0 ; python_version >= "3.12" and python_version < "4.0" 25 | hpack==4.1.0 ; python_version >= "3.12" and python_version < "4.0" 26 | httpcore==1.0.9 ; python_version >= "3.12" and python_version < "4.0" 27 | httptools==0.6.4 ; python_version >= "3.12" and python_version < "4.0" 28 | httpx==0.28.1 ; python_version >= "3.12" and python_version < "4.0" 29 | hyperframe==6.1.0 ; python_version >= "3.12" and python_version < "4.0" 30 | idna==3.10 ; python_version >= "3.12" and python_version < "4.0" 31 | iniconfig==2.1.0 ; python_version >= "3.12" and python_version < "4.0" 32 | itsdangerous==2.2.0 ; python_version >= "3.12" and python_version < "4.0" 33 | jinja2==3.1.6 ; python_version >= "3.12" and python_version < "4.0" 34 | jsonschema-specifications==2025.4.1 ; python_version >= "3.12" and python_version < "4.0" 35 | jsonschema==4.24.0 ; python_version >= "3.12" and python_version < "4.0" 36 | markdown-it-py==3.0.0 ; python_version >= "3.12" and python_version < "4.0" 37 | markupsafe==3.0.2 ; python_version >= "3.12" and python_version < "4.0" 38 | mdurl==0.1.2 ; python_version >= "3.12" and python_version < "4.0" 39 | multidict==6.5.0 ; python_version >= "3.12" and python_version < "4.0" 40 | narwhals==1.44.0 ; python_version >= "3.12" and python_version < "4.0" 41 | numpy==2.3.1 ; python_version >= "3.12" and python_version < "4.0" 42 | orjson==3.10.18 ; python_version >= "3.12" and python_version < "4.0" 43 | packaging==25.0 ; python_version >= "3.12" and python_version < "4.0" 44 | pandas==2.3.0 ; python_version >= "3.12" and python_version < "4.0" 45 | pillow==11.2.1 ; python_version >= "3.12" and python_version < "4.0" 46 | pluggy==1.6.0 ; python_version >= "3.12" and python_version < "4.0" 47 | postgrest==1.0.2 ; python_version >= "3.12" and python_version < "4.0" 48 | propcache==0.3.2 ; python_version >= "3.12" and python_version < "4.0" 49 | protobuf==6.31.1 ; python_version >= "3.12" and python_version < "4.0" 50 | pyarrow==20.0.0 ; python_version >= "3.12" and python_version < "4.0" 51 | pydantic-core==2.33.2 ; python_version >= "3.12" and python_version < "4.0" 52 | pydantic-extra-types==2.10.5 ; python_version >= "3.12" and python_version < "4.0" 53 | pydantic-settings==2.9.1 ; python_version >= "3.12" and python_version < "4.0" 54 | pydantic==2.11.7 ; python_version >= "3.12" and python_version < "4.0" 55 | pydeck==0.9.1 ; python_version >= "3.12" and python_version < "4.0" 56 | pygments==2.19.1 ; python_version >= "3.12" and python_version < "4.0" 57 | pyjwt==2.10.1 ; python_version >= "3.12" and python_version < "4.0" 58 | pytest-mock==3.14.1 ; python_version >= "3.12" and python_version < "4.0" 59 | pytest==8.4.1 ; python_version >= "3.12" and python_version < "4.0" 60 | python-dateutil==2.9.0.post0 ; python_version >= "3.12" and python_version < "4.0" 61 | python-dotenv==1.1.0 ; python_version >= "3.12" and python_version < "4.0" 62 | python-multipart==0.0.20 ; python_version >= "3.12" and python_version < "4.0" 63 | pytz==2025.2 ; python_version >= "3.12" and python_version < "4.0" 64 | pyyaml==6.0.2 ; python_version >= "3.12" and python_version < "4.0" 65 | realtime==2.4.3 ; python_version >= "3.12" and python_version < "4.0" 66 | referencing==0.36.2 ; python_version >= "3.12" and python_version < "4.0" 67 | requests==2.32.4 ; python_version >= "3.12" and python_version < "4.0" 68 | rich-toolkit==0.14.7 ; python_version >= "3.12" and python_version < "4.0" 69 | rich==14.0.0 ; python_version >= "3.12" and python_version < "4.0" 70 | rpds-py==0.25.1 ; python_version >= "3.12" and python_version < "4.0" 71 | shellingham==1.5.4 ; python_version >= "3.12" and python_version < "4.0" 72 | six==1.17.0 ; python_version >= "3.12" and python_version < "4.0" 73 | smmap==5.0.2 ; python_version >= "3.12" and python_version < "4.0" 74 | sniffio==1.3.1 ; python_version >= "3.12" and python_version < "4.0" 75 | starlette==0.46.2 ; python_version >= "3.12" and python_version < "4.0" 76 | storage3==0.11.3 ; python_version >= "3.12" and python_version < "4.0" 77 | streamlit==1.46.0 ; python_version >= "3.12" and python_version < "4.0" 78 | strenum==0.4.15 ; python_version >= "3.12" and python_version < "4.0" 79 | supabase==2.15.3 ; python_version >= "3.12" and python_version < "4.0" 80 | supafunc==0.9.4 ; python_version >= "3.12" and python_version < "4.0" 81 | tenacity==9.1.2 ; python_version >= "3.12" and python_version < "4.0" 82 | toml==0.10.2 ; python_version >= "3.12" and python_version < "4.0" 83 | tornado==6.5.1 ; python_version >= "3.12" and python_version < "4.0" 84 | typer==0.16.0 ; python_version >= "3.12" and python_version < "4.0" 85 | typing-extensions==4.14.0 ; python_version >= "3.12" and python_version < "4.0" 86 | typing-inspection==0.4.1 ; python_version >= "3.12" and python_version < "4.0" 87 | tzdata==2025.2 ; python_version >= "3.12" and python_version < "4.0" 88 | ujson==5.10.0 ; python_version >= "3.12" and python_version < "4.0" 89 | urllib3==2.4.0 ; python_version >= "3.12" and python_version < "4.0" 90 | uvicorn==0.34.3 ; python_version >= "3.12" and python_version < "4.0" 91 | uvloop==0.21.0 ; python_version >= "3.12" and python_version < "4.0" and sys_platform != "win32" and sys_platform != "cygwin" and platform_python_implementation != "PyPy" 92 | watchdog==6.0.0 ; python_version >= "3.12" and python_version < "4.0" and platform_system != "Darwin" 93 | watchfiles==1.0.5 ; python_version >= "3.12" and python_version < "4.0" 94 | websockets==14.2 ; python_version >= "3.12" and python_version < "4.0" 95 | yarl==1.20.1 ; python_version >= "3.12" and python_version < "4.0" 96 | -------------------------------------------------------------------------------- /sdk/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "anyio" 5 | version = "4.5.2" 6 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 7 | optional = false 8 | python-versions = ">=3.8" 9 | groups = ["main"] 10 | files = [ 11 | {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, 12 | {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, 13 | ] 14 | 15 | [package.dependencies] 16 | exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} 17 | idna = ">=2.8" 18 | sniffio = ">=1.1" 19 | typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} 20 | 21 | [package.extras] 22 | doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] 23 | test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21.0b1) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] 24 | trio = ["trio (>=0.26.1)"] 25 | 26 | [[package]] 27 | name = "certifi" 28 | version = "2025.6.15" 29 | description = "Python package for providing Mozilla's CA Bundle." 30 | optional = false 31 | python-versions = ">=3.7" 32 | groups = ["main"] 33 | files = [ 34 | {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"}, 35 | {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"}, 36 | ] 37 | 38 | [[package]] 39 | name = "exceptiongroup" 40 | version = "1.3.0" 41 | description = "Backport of PEP 654 (exception groups)" 42 | optional = false 43 | python-versions = ">=3.7" 44 | groups = ["main"] 45 | markers = "python_version < \"3.11\"" 46 | files = [ 47 | {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, 48 | {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, 49 | ] 50 | 51 | [package.dependencies] 52 | typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} 53 | 54 | [package.extras] 55 | test = ["pytest (>=6)"] 56 | 57 | [[package]] 58 | name = "h11" 59 | version = "0.16.0" 60 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 61 | optional = false 62 | python-versions = ">=3.8" 63 | groups = ["main"] 64 | files = [ 65 | {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, 66 | {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, 67 | ] 68 | 69 | [[package]] 70 | name = "hatchling" 71 | version = "1.27.0" 72 | description = "Modern, extensible Python build backend" 73 | optional = false 74 | python-versions = ">=3.8" 75 | groups = ["main"] 76 | files = [ 77 | {file = "hatchling-1.27.0-py3-none-any.whl", hash = "sha256:d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b"}, 78 | {file = "hatchling-1.27.0.tar.gz", hash = "sha256:971c296d9819abb3811112fc52c7a9751c8d381898f36533bb16f9791e941fd6"}, 79 | ] 80 | 81 | [package.dependencies] 82 | packaging = ">=24.2" 83 | pathspec = ">=0.10.1" 84 | pluggy = ">=1.0.0" 85 | tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} 86 | trove-classifiers = "*" 87 | 88 | [[package]] 89 | name = "httpcore" 90 | version = "1.0.9" 91 | description = "A minimal low-level HTTP client." 92 | optional = false 93 | python-versions = ">=3.8" 94 | groups = ["main"] 95 | files = [ 96 | {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, 97 | {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, 98 | ] 99 | 100 | [package.dependencies] 101 | certifi = "*" 102 | h11 = ">=0.16" 103 | 104 | [package.extras] 105 | asyncio = ["anyio (>=4.0,<5.0)"] 106 | http2 = ["h2 (>=3,<5)"] 107 | socks = ["socksio (==1.*)"] 108 | trio = ["trio (>=0.22.0,<1.0)"] 109 | 110 | [[package]] 111 | name = "httpx" 112 | version = "0.28.1" 113 | description = "The next generation HTTP client." 114 | optional = false 115 | python-versions = ">=3.8" 116 | groups = ["main"] 117 | files = [ 118 | {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, 119 | {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, 120 | ] 121 | 122 | [package.dependencies] 123 | anyio = "*" 124 | certifi = "*" 125 | httpcore = "==1.*" 126 | idna = "*" 127 | 128 | [package.extras] 129 | brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] 130 | cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] 131 | http2 = ["h2 (>=3,<5)"] 132 | socks = ["socksio (==1.*)"] 133 | zstd = ["zstandard (>=0.18.0)"] 134 | 135 | [[package]] 136 | name = "idna" 137 | version = "3.10" 138 | description = "Internationalized Domain Names in Applications (IDNA)" 139 | optional = false 140 | python-versions = ">=3.6" 141 | groups = ["main"] 142 | files = [ 143 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 144 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 145 | ] 146 | 147 | [package.extras] 148 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 149 | 150 | [[package]] 151 | name = "packaging" 152 | version = "25.0" 153 | description = "Core utilities for Python packages" 154 | optional = false 155 | python-versions = ">=3.8" 156 | groups = ["main"] 157 | files = [ 158 | {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, 159 | {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, 160 | ] 161 | 162 | [[package]] 163 | name = "pathspec" 164 | version = "0.12.1" 165 | description = "Utility library for gitignore style pattern matching of file paths." 166 | optional = false 167 | python-versions = ">=3.8" 168 | groups = ["main"] 169 | files = [ 170 | {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, 171 | {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, 172 | ] 173 | 174 | [[package]] 175 | name = "pluggy" 176 | version = "1.5.0" 177 | description = "plugin and hook calling mechanisms for python" 178 | optional = false 179 | python-versions = ">=3.8" 180 | groups = ["main"] 181 | files = [ 182 | {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, 183 | {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, 184 | ] 185 | 186 | [package.extras] 187 | dev = ["pre-commit", "tox"] 188 | testing = ["pytest", "pytest-benchmark"] 189 | 190 | [[package]] 191 | name = "sniffio" 192 | version = "1.3.1" 193 | description = "Sniff out which async library your code is running under" 194 | optional = false 195 | python-versions = ">=3.7" 196 | groups = ["main"] 197 | files = [ 198 | {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, 199 | {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, 200 | ] 201 | 202 | [[package]] 203 | name = "tomli" 204 | version = "2.2.1" 205 | description = "A lil' TOML parser" 206 | optional = false 207 | python-versions = ">=3.8" 208 | groups = ["main"] 209 | markers = "python_version < \"3.11\"" 210 | files = [ 211 | {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, 212 | {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, 213 | {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, 214 | {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, 215 | {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, 216 | {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, 217 | {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, 218 | {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, 219 | {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, 220 | {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, 221 | {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, 222 | {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, 223 | {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, 224 | {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, 225 | {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, 226 | {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, 227 | {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, 228 | {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, 229 | {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, 230 | {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, 231 | {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, 232 | {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, 233 | {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, 234 | {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, 235 | {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, 236 | {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, 237 | {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, 238 | {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, 239 | {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, 240 | {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, 241 | {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, 242 | {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, 243 | ] 244 | 245 | [[package]] 246 | name = "trove-classifiers" 247 | version = "2025.5.9.12" 248 | description = "Canonical source for classifiers on PyPI (pypi.org)." 249 | optional = false 250 | python-versions = "*" 251 | groups = ["main"] 252 | files = [ 253 | {file = "trove_classifiers-2025.5.9.12-py3-none-any.whl", hash = "sha256:e381c05537adac78881c8fa345fd0e9970159f4e4a04fcc42cfd3129cca640ce"}, 254 | {file = "trove_classifiers-2025.5.9.12.tar.gz", hash = "sha256:7ca7c8a7a76e2cd314468c677c69d12cc2357711fcab4a60f87994c1589e5cb5"}, 255 | ] 256 | 257 | [[package]] 258 | name = "typing-extensions" 259 | version = "4.13.2" 260 | description = "Backported and Experimental Type Hints for Python 3.8+" 261 | optional = false 262 | python-versions = ">=3.8" 263 | groups = ["main"] 264 | markers = "python_version < \"3.11\"" 265 | files = [ 266 | {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, 267 | {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, 268 | ] 269 | 270 | [[package]] 271 | name = "websockets" 272 | version = "13.1" 273 | description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" 274 | optional = false 275 | python-versions = ">=3.8" 276 | groups = ["main"] 277 | files = [ 278 | {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, 279 | {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, 280 | {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, 281 | {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, 282 | {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, 283 | {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, 284 | {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, 285 | {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, 286 | {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, 287 | {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, 288 | {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, 289 | {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, 290 | {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, 291 | {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, 292 | {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, 293 | {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, 294 | {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, 295 | {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, 296 | {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, 297 | {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, 298 | {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, 299 | {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, 300 | {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, 301 | {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, 302 | {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, 303 | {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, 304 | {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, 305 | {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, 306 | {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, 307 | {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, 308 | {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, 309 | {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, 310 | {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, 311 | {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, 312 | {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, 313 | {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, 314 | {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, 315 | {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, 316 | {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, 317 | {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, 318 | {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, 319 | {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, 320 | {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, 321 | {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, 322 | {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, 323 | {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, 324 | {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, 325 | {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, 326 | {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, 327 | {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, 328 | {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, 329 | {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, 330 | {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, 331 | {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, 332 | {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, 333 | {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, 334 | {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, 335 | {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, 336 | {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, 337 | {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, 338 | {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, 339 | {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, 340 | {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, 341 | {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, 342 | {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, 343 | {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, 344 | {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, 345 | {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, 346 | {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, 347 | {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"}, 348 | {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"}, 349 | {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"}, 350 | {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"}, 351 | {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"}, 352 | {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"}, 353 | {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"}, 354 | {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"}, 355 | {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"}, 356 | {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"}, 357 | {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"}, 358 | {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"}, 359 | {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"}, 360 | {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"}, 361 | {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"}, 362 | {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"}, 363 | {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"}, 364 | ] 365 | 366 | [metadata] 367 | lock-version = "2.1" 368 | python-versions = ">=3.8" 369 | content-hash = "79368ff0df91343e168832d4f749fac1cc63e5c82c57915a1f1f0528ca9298f7" 370 | -------------------------------------------------------------------------------- /frontend/memx-frontend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memx-frontend", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "memx-frontend", 9 | "version": "0.1.0", 10 | "dependencies": { 11 | "@supabase/auth-helpers-nextjs": "^0.10.0", 12 | "next": "15.3.4", 13 | "react": "^19.0.0", 14 | "react-dom": "^19.0.0" 15 | }, 16 | "devDependencies": { 17 | "@tailwindcss/postcss": "^4", 18 | "autoprefixer": "^10.4.21", 19 | "postcss": "^8.5.6", 20 | "tailwindcss": "^4.1.10" 21 | } 22 | }, 23 | "node_modules/@alloc/quick-lru": { 24 | "version": "5.2.0", 25 | "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 26 | "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 27 | "dev": true, 28 | "license": "MIT", 29 | "engines": { 30 | "node": ">=10" 31 | }, 32 | "funding": { 33 | "url": "https://github.com/sponsors/sindresorhus" 34 | } 35 | }, 36 | "node_modules/@ampproject/remapping": { 37 | "version": "2.3.0", 38 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", 39 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 40 | "dev": true, 41 | "license": "Apache-2.0", 42 | "dependencies": { 43 | "@jridgewell/gen-mapping": "^0.3.5", 44 | "@jridgewell/trace-mapping": "^0.3.24" 45 | }, 46 | "engines": { 47 | "node": ">=6.0.0" 48 | } 49 | }, 50 | "node_modules/@emnapi/runtime": { 51 | "version": "1.4.3", 52 | "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", 53 | "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", 54 | "license": "MIT", 55 | "optional": true, 56 | "dependencies": { 57 | "tslib": "^2.4.0" 58 | } 59 | }, 60 | "node_modules/@img/sharp-darwin-arm64": { 61 | "version": "0.34.2", 62 | "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", 63 | "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", 64 | "cpu": [ 65 | "arm64" 66 | ], 67 | "license": "Apache-2.0", 68 | "optional": true, 69 | "os": [ 70 | "darwin" 71 | ], 72 | "engines": { 73 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 74 | }, 75 | "funding": { 76 | "url": "https://opencollective.com/libvips" 77 | }, 78 | "optionalDependencies": { 79 | "@img/sharp-libvips-darwin-arm64": "1.1.0" 80 | } 81 | }, 82 | "node_modules/@img/sharp-darwin-x64": { 83 | "version": "0.34.2", 84 | "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", 85 | "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", 86 | "cpu": [ 87 | "x64" 88 | ], 89 | "license": "Apache-2.0", 90 | "optional": true, 91 | "os": [ 92 | "darwin" 93 | ], 94 | "engines": { 95 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 96 | }, 97 | "funding": { 98 | "url": "https://opencollective.com/libvips" 99 | }, 100 | "optionalDependencies": { 101 | "@img/sharp-libvips-darwin-x64": "1.1.0" 102 | } 103 | }, 104 | "node_modules/@img/sharp-libvips-darwin-arm64": { 105 | "version": "1.1.0", 106 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", 107 | "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", 108 | "cpu": [ 109 | "arm64" 110 | ], 111 | "license": "LGPL-3.0-or-later", 112 | "optional": true, 113 | "os": [ 114 | "darwin" 115 | ], 116 | "funding": { 117 | "url": "https://opencollective.com/libvips" 118 | } 119 | }, 120 | "node_modules/@img/sharp-libvips-darwin-x64": { 121 | "version": "1.1.0", 122 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", 123 | "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", 124 | "cpu": [ 125 | "x64" 126 | ], 127 | "license": "LGPL-3.0-or-later", 128 | "optional": true, 129 | "os": [ 130 | "darwin" 131 | ], 132 | "funding": { 133 | "url": "https://opencollective.com/libvips" 134 | } 135 | }, 136 | "node_modules/@img/sharp-libvips-linux-arm": { 137 | "version": "1.1.0", 138 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", 139 | "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", 140 | "cpu": [ 141 | "arm" 142 | ], 143 | "license": "LGPL-3.0-or-later", 144 | "optional": true, 145 | "os": [ 146 | "linux" 147 | ], 148 | "funding": { 149 | "url": "https://opencollective.com/libvips" 150 | } 151 | }, 152 | "node_modules/@img/sharp-libvips-linux-arm64": { 153 | "version": "1.1.0", 154 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", 155 | "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", 156 | "cpu": [ 157 | "arm64" 158 | ], 159 | "license": "LGPL-3.0-or-later", 160 | "optional": true, 161 | "os": [ 162 | "linux" 163 | ], 164 | "funding": { 165 | "url": "https://opencollective.com/libvips" 166 | } 167 | }, 168 | "node_modules/@img/sharp-libvips-linux-ppc64": { 169 | "version": "1.1.0", 170 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", 171 | "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", 172 | "cpu": [ 173 | "ppc64" 174 | ], 175 | "license": "LGPL-3.0-or-later", 176 | "optional": true, 177 | "os": [ 178 | "linux" 179 | ], 180 | "funding": { 181 | "url": "https://opencollective.com/libvips" 182 | } 183 | }, 184 | "node_modules/@img/sharp-libvips-linux-s390x": { 185 | "version": "1.1.0", 186 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", 187 | "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", 188 | "cpu": [ 189 | "s390x" 190 | ], 191 | "license": "LGPL-3.0-or-later", 192 | "optional": true, 193 | "os": [ 194 | "linux" 195 | ], 196 | "funding": { 197 | "url": "https://opencollective.com/libvips" 198 | } 199 | }, 200 | "node_modules/@img/sharp-libvips-linux-x64": { 201 | "version": "1.1.0", 202 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", 203 | "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", 204 | "cpu": [ 205 | "x64" 206 | ], 207 | "license": "LGPL-3.0-or-later", 208 | "optional": true, 209 | "os": [ 210 | "linux" 211 | ], 212 | "funding": { 213 | "url": "https://opencollective.com/libvips" 214 | } 215 | }, 216 | "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 217 | "version": "1.1.0", 218 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", 219 | "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "license": "LGPL-3.0-or-later", 224 | "optional": true, 225 | "os": [ 226 | "linux" 227 | ], 228 | "funding": { 229 | "url": "https://opencollective.com/libvips" 230 | } 231 | }, 232 | "node_modules/@img/sharp-libvips-linuxmusl-x64": { 233 | "version": "1.1.0", 234 | "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", 235 | "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", 236 | "cpu": [ 237 | "x64" 238 | ], 239 | "license": "LGPL-3.0-or-later", 240 | "optional": true, 241 | "os": [ 242 | "linux" 243 | ], 244 | "funding": { 245 | "url": "https://opencollective.com/libvips" 246 | } 247 | }, 248 | "node_modules/@img/sharp-linux-arm": { 249 | "version": "0.34.2", 250 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", 251 | "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", 252 | "cpu": [ 253 | "arm" 254 | ], 255 | "license": "Apache-2.0", 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 262 | }, 263 | "funding": { 264 | "url": "https://opencollective.com/libvips" 265 | }, 266 | "optionalDependencies": { 267 | "@img/sharp-libvips-linux-arm": "1.1.0" 268 | } 269 | }, 270 | "node_modules/@img/sharp-linux-arm64": { 271 | "version": "0.34.2", 272 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", 273 | "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", 274 | "cpu": [ 275 | "arm64" 276 | ], 277 | "license": "Apache-2.0", 278 | "optional": true, 279 | "os": [ 280 | "linux" 281 | ], 282 | "engines": { 283 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 284 | }, 285 | "funding": { 286 | "url": "https://opencollective.com/libvips" 287 | }, 288 | "optionalDependencies": { 289 | "@img/sharp-libvips-linux-arm64": "1.1.0" 290 | } 291 | }, 292 | "node_modules/@img/sharp-linux-s390x": { 293 | "version": "0.34.2", 294 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", 295 | "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", 296 | "cpu": [ 297 | "s390x" 298 | ], 299 | "license": "Apache-2.0", 300 | "optional": true, 301 | "os": [ 302 | "linux" 303 | ], 304 | "engines": { 305 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 306 | }, 307 | "funding": { 308 | "url": "https://opencollective.com/libvips" 309 | }, 310 | "optionalDependencies": { 311 | "@img/sharp-libvips-linux-s390x": "1.1.0" 312 | } 313 | }, 314 | "node_modules/@img/sharp-linux-x64": { 315 | "version": "0.34.2", 316 | "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", 317 | "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", 318 | "cpu": [ 319 | "x64" 320 | ], 321 | "license": "Apache-2.0", 322 | "optional": true, 323 | "os": [ 324 | "linux" 325 | ], 326 | "engines": { 327 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 328 | }, 329 | "funding": { 330 | "url": "https://opencollective.com/libvips" 331 | }, 332 | "optionalDependencies": { 333 | "@img/sharp-libvips-linux-x64": "1.1.0" 334 | } 335 | }, 336 | "node_modules/@img/sharp-linuxmusl-arm64": { 337 | "version": "0.34.2", 338 | "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", 339 | "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", 340 | "cpu": [ 341 | "arm64" 342 | ], 343 | "license": "Apache-2.0", 344 | "optional": true, 345 | "os": [ 346 | "linux" 347 | ], 348 | "engines": { 349 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 350 | }, 351 | "funding": { 352 | "url": "https://opencollective.com/libvips" 353 | }, 354 | "optionalDependencies": { 355 | "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" 356 | } 357 | }, 358 | "node_modules/@img/sharp-linuxmusl-x64": { 359 | "version": "0.34.2", 360 | "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", 361 | "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", 362 | "cpu": [ 363 | "x64" 364 | ], 365 | "license": "Apache-2.0", 366 | "optional": true, 367 | "os": [ 368 | "linux" 369 | ], 370 | "engines": { 371 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 372 | }, 373 | "funding": { 374 | "url": "https://opencollective.com/libvips" 375 | }, 376 | "optionalDependencies": { 377 | "@img/sharp-libvips-linuxmusl-x64": "1.1.0" 378 | } 379 | }, 380 | "node_modules/@img/sharp-wasm32": { 381 | "version": "0.34.2", 382 | "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", 383 | "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", 384 | "cpu": [ 385 | "wasm32" 386 | ], 387 | "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 388 | "optional": true, 389 | "dependencies": { 390 | "@emnapi/runtime": "^1.4.3" 391 | }, 392 | "engines": { 393 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 394 | }, 395 | "funding": { 396 | "url": "https://opencollective.com/libvips" 397 | } 398 | }, 399 | "node_modules/@img/sharp-win32-arm64": { 400 | "version": "0.34.2", 401 | "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", 402 | "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", 403 | "cpu": [ 404 | "arm64" 405 | ], 406 | "license": "Apache-2.0 AND LGPL-3.0-or-later", 407 | "optional": true, 408 | "os": [ 409 | "win32" 410 | ], 411 | "engines": { 412 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 413 | }, 414 | "funding": { 415 | "url": "https://opencollective.com/libvips" 416 | } 417 | }, 418 | "node_modules/@img/sharp-win32-ia32": { 419 | "version": "0.34.2", 420 | "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", 421 | "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", 422 | "cpu": [ 423 | "ia32" 424 | ], 425 | "license": "Apache-2.0 AND LGPL-3.0-or-later", 426 | "optional": true, 427 | "os": [ 428 | "win32" 429 | ], 430 | "engines": { 431 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 432 | }, 433 | "funding": { 434 | "url": "https://opencollective.com/libvips" 435 | } 436 | }, 437 | "node_modules/@img/sharp-win32-x64": { 438 | "version": "0.34.2", 439 | "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", 440 | "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", 441 | "cpu": [ 442 | "x64" 443 | ], 444 | "license": "Apache-2.0 AND LGPL-3.0-or-later", 445 | "optional": true, 446 | "os": [ 447 | "win32" 448 | ], 449 | "engines": { 450 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 451 | }, 452 | "funding": { 453 | "url": "https://opencollective.com/libvips" 454 | } 455 | }, 456 | "node_modules/@isaacs/fs-minipass": { 457 | "version": "4.0.1", 458 | "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", 459 | "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", 460 | "dev": true, 461 | "license": "ISC", 462 | "dependencies": { 463 | "minipass": "^7.0.4" 464 | }, 465 | "engines": { 466 | "node": ">=18.0.0" 467 | } 468 | }, 469 | "node_modules/@jridgewell/gen-mapping": { 470 | "version": "0.3.8", 471 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", 472 | "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", 473 | "dev": true, 474 | "license": "MIT", 475 | "dependencies": { 476 | "@jridgewell/set-array": "^1.2.1", 477 | "@jridgewell/sourcemap-codec": "^1.4.10", 478 | "@jridgewell/trace-mapping": "^0.3.24" 479 | }, 480 | "engines": { 481 | "node": ">=6.0.0" 482 | } 483 | }, 484 | "node_modules/@jridgewell/resolve-uri": { 485 | "version": "3.1.2", 486 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 487 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 488 | "dev": true, 489 | "license": "MIT", 490 | "engines": { 491 | "node": ">=6.0.0" 492 | } 493 | }, 494 | "node_modules/@jridgewell/set-array": { 495 | "version": "1.2.1", 496 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 497 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 498 | "dev": true, 499 | "license": "MIT", 500 | "engines": { 501 | "node": ">=6.0.0" 502 | } 503 | }, 504 | "node_modules/@jridgewell/sourcemap-codec": { 505 | "version": "1.5.0", 506 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 507 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 508 | "dev": true, 509 | "license": "MIT" 510 | }, 511 | "node_modules/@jridgewell/trace-mapping": { 512 | "version": "0.3.25", 513 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 514 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 515 | "dev": true, 516 | "license": "MIT", 517 | "dependencies": { 518 | "@jridgewell/resolve-uri": "^3.1.0", 519 | "@jridgewell/sourcemap-codec": "^1.4.14" 520 | } 521 | }, 522 | "node_modules/@next/env": { 523 | "version": "15.3.4", 524 | "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.4.tgz", 525 | "integrity": "sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==", 526 | "license": "MIT" 527 | }, 528 | "node_modules/@next/swc-darwin-arm64": { 529 | "version": "15.3.4", 530 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.4.tgz", 531 | "integrity": "sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==", 532 | "cpu": [ 533 | "arm64" 534 | ], 535 | "license": "MIT", 536 | "optional": true, 537 | "os": [ 538 | "darwin" 539 | ], 540 | "engines": { 541 | "node": ">= 10" 542 | } 543 | }, 544 | "node_modules/@next/swc-darwin-x64": { 545 | "version": "15.3.4", 546 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.4.tgz", 547 | "integrity": "sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==", 548 | "cpu": [ 549 | "x64" 550 | ], 551 | "license": "MIT", 552 | "optional": true, 553 | "os": [ 554 | "darwin" 555 | ], 556 | "engines": { 557 | "node": ">= 10" 558 | } 559 | }, 560 | "node_modules/@next/swc-linux-arm64-gnu": { 561 | "version": "15.3.4", 562 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.4.tgz", 563 | "integrity": "sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==", 564 | "cpu": [ 565 | "arm64" 566 | ], 567 | "license": "MIT", 568 | "optional": true, 569 | "os": [ 570 | "linux" 571 | ], 572 | "engines": { 573 | "node": ">= 10" 574 | } 575 | }, 576 | "node_modules/@next/swc-linux-arm64-musl": { 577 | "version": "15.3.4", 578 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.4.tgz", 579 | "integrity": "sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==", 580 | "cpu": [ 581 | "arm64" 582 | ], 583 | "license": "MIT", 584 | "optional": true, 585 | "os": [ 586 | "linux" 587 | ], 588 | "engines": { 589 | "node": ">= 10" 590 | } 591 | }, 592 | "node_modules/@next/swc-linux-x64-gnu": { 593 | "version": "15.3.4", 594 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.4.tgz", 595 | "integrity": "sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==", 596 | "cpu": [ 597 | "x64" 598 | ], 599 | "license": "MIT", 600 | "optional": true, 601 | "os": [ 602 | "linux" 603 | ], 604 | "engines": { 605 | "node": ">= 10" 606 | } 607 | }, 608 | "node_modules/@next/swc-linux-x64-musl": { 609 | "version": "15.3.4", 610 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.4.tgz", 611 | "integrity": "sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==", 612 | "cpu": [ 613 | "x64" 614 | ], 615 | "license": "MIT", 616 | "optional": true, 617 | "os": [ 618 | "linux" 619 | ], 620 | "engines": { 621 | "node": ">= 10" 622 | } 623 | }, 624 | "node_modules/@next/swc-win32-arm64-msvc": { 625 | "version": "15.3.4", 626 | "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.4.tgz", 627 | "integrity": "sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==", 628 | "cpu": [ 629 | "arm64" 630 | ], 631 | "license": "MIT", 632 | "optional": true, 633 | "os": [ 634 | "win32" 635 | ], 636 | "engines": { 637 | "node": ">= 10" 638 | } 639 | }, 640 | "node_modules/@next/swc-win32-x64-msvc": { 641 | "version": "15.3.4", 642 | "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.4.tgz", 643 | "integrity": "sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==", 644 | "cpu": [ 645 | "x64" 646 | ], 647 | "license": "MIT", 648 | "optional": true, 649 | "os": [ 650 | "win32" 651 | ], 652 | "engines": { 653 | "node": ">= 10" 654 | } 655 | }, 656 | "node_modules/@supabase/auth-helpers-nextjs": { 657 | "version": "0.10.0", 658 | "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.10.0.tgz", 659 | "integrity": "sha512-2dfOGsM4yZt0oS4TPiE7bD4vf7EVz7NRz/IJrV6vLg0GP7sMUx8wndv2euLGq4BjN9lUCpu6DG/uCC8j+ylwPg==", 660 | "deprecated": "This package is now deprecated - please use the @supabase/ssr package instead.", 661 | "license": "MIT", 662 | "dependencies": { 663 | "@supabase/auth-helpers-shared": "0.7.0", 664 | "set-cookie-parser": "^2.6.0" 665 | }, 666 | "peerDependencies": { 667 | "@supabase/supabase-js": "^2.39.8" 668 | } 669 | }, 670 | "node_modules/@supabase/auth-helpers-shared": { 671 | "version": "0.7.0", 672 | "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.7.0.tgz", 673 | "integrity": "sha512-FBFf2ei2R7QC+B/5wWkthMha8Ca2bWHAndN+syfuEUUfufv4mLcAgBCcgNg5nJR8L0gZfyuaxgubtOc9aW3Cpg==", 674 | "deprecated": "This package is now deprecated - please use the @supabase/ssr package instead.", 675 | "license": "MIT", 676 | "dependencies": { 677 | "jose": "^4.14.4" 678 | }, 679 | "peerDependencies": { 680 | "@supabase/supabase-js": "^2.39.8" 681 | } 682 | }, 683 | "node_modules/@supabase/auth-js": { 684 | "version": "2.70.0", 685 | "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.70.0.tgz", 686 | "integrity": "sha512-BaAK/tOAZFJtzF1sE3gJ2FwTjLf4ky3PSvcvLGEgEmO4BSBkwWKu8l67rLLIBZPDnCyV7Owk2uPyKHa0kj5QGg==", 687 | "license": "MIT", 688 | "peer": true, 689 | "dependencies": { 690 | "@supabase/node-fetch": "^2.6.14" 691 | } 692 | }, 693 | "node_modules/@supabase/functions-js": { 694 | "version": "2.4.4", 695 | "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.4.tgz", 696 | "integrity": "sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==", 697 | "license": "MIT", 698 | "peer": true, 699 | "dependencies": { 700 | "@supabase/node-fetch": "^2.6.14" 701 | } 702 | }, 703 | "node_modules/@supabase/node-fetch": { 704 | "version": "2.6.15", 705 | "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", 706 | "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", 707 | "license": "MIT", 708 | "peer": true, 709 | "dependencies": { 710 | "whatwg-url": "^5.0.0" 711 | }, 712 | "engines": { 713 | "node": "4.x || >=6.0.0" 714 | } 715 | }, 716 | "node_modules/@supabase/postgrest-js": { 717 | "version": "1.19.4", 718 | "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz", 719 | "integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==", 720 | "license": "MIT", 721 | "peer": true, 722 | "dependencies": { 723 | "@supabase/node-fetch": "^2.6.14" 724 | } 725 | }, 726 | "node_modules/@supabase/realtime-js": { 727 | "version": "2.11.15", 728 | "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.15.tgz", 729 | "integrity": "sha512-HQKRnwAqdVqJW/P9TjKVK+/ETpW4yQ8tyDPPtRMKOH4Uh3vQD74vmj353CYs8+YwVBKubeUOOEpI9CT8mT4obw==", 730 | "license": "MIT", 731 | "peer": true, 732 | "dependencies": { 733 | "@supabase/node-fetch": "^2.6.13", 734 | "@types/phoenix": "^1.6.6", 735 | "@types/ws": "^8.18.1", 736 | "isows": "^1.0.7", 737 | "ws": "^8.18.2" 738 | } 739 | }, 740 | "node_modules/@supabase/storage-js": { 741 | "version": "2.7.1", 742 | "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz", 743 | "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", 744 | "license": "MIT", 745 | "peer": true, 746 | "dependencies": { 747 | "@supabase/node-fetch": "^2.6.14" 748 | } 749 | }, 750 | "node_modules/@supabase/supabase-js": { 751 | "version": "2.50.2", 752 | "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.50.2.tgz", 753 | "integrity": "sha512-+27xlGgw7VyfwXXe+OiDJQosJNS+PPtjj1EnLR4uk+PKKZ91RA0/8NbIQybe6AGPanAaPtgOFFMMCArC6fZ++Q==", 754 | "license": "MIT", 755 | "peer": true, 756 | "dependencies": { 757 | "@supabase/auth-js": "2.70.0", 758 | "@supabase/functions-js": "2.4.4", 759 | "@supabase/node-fetch": "2.6.15", 760 | "@supabase/postgrest-js": "1.19.4", 761 | "@supabase/realtime-js": "2.11.15", 762 | "@supabase/storage-js": "2.7.1" 763 | } 764 | }, 765 | "node_modules/@swc/counter": { 766 | "version": "0.1.3", 767 | "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", 768 | "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", 769 | "license": "Apache-2.0" 770 | }, 771 | "node_modules/@swc/helpers": { 772 | "version": "0.5.15", 773 | "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", 774 | "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", 775 | "license": "Apache-2.0", 776 | "dependencies": { 777 | "tslib": "^2.8.0" 778 | } 779 | }, 780 | "node_modules/@tailwindcss/node": { 781 | "version": "4.1.10", 782 | "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz", 783 | "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", 784 | "dev": true, 785 | "license": "MIT", 786 | "dependencies": { 787 | "@ampproject/remapping": "^2.3.0", 788 | "enhanced-resolve": "^5.18.1", 789 | "jiti": "^2.4.2", 790 | "lightningcss": "1.30.1", 791 | "magic-string": "^0.30.17", 792 | "source-map-js": "^1.2.1", 793 | "tailwindcss": "4.1.10" 794 | } 795 | }, 796 | "node_modules/@tailwindcss/oxide": { 797 | "version": "4.1.10", 798 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz", 799 | "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", 800 | "dev": true, 801 | "hasInstallScript": true, 802 | "license": "MIT", 803 | "dependencies": { 804 | "detect-libc": "^2.0.4", 805 | "tar": "^7.4.3" 806 | }, 807 | "engines": { 808 | "node": ">= 10" 809 | }, 810 | "optionalDependencies": { 811 | "@tailwindcss/oxide-android-arm64": "4.1.10", 812 | "@tailwindcss/oxide-darwin-arm64": "4.1.10", 813 | "@tailwindcss/oxide-darwin-x64": "4.1.10", 814 | "@tailwindcss/oxide-freebsd-x64": "4.1.10", 815 | "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10", 816 | "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10", 817 | "@tailwindcss/oxide-linux-arm64-musl": "4.1.10", 818 | "@tailwindcss/oxide-linux-x64-gnu": "4.1.10", 819 | "@tailwindcss/oxide-linux-x64-musl": "4.1.10", 820 | "@tailwindcss/oxide-wasm32-wasi": "4.1.10", 821 | "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10", 822 | "@tailwindcss/oxide-win32-x64-msvc": "4.1.10" 823 | } 824 | }, 825 | "node_modules/@tailwindcss/oxide-android-arm64": { 826 | "version": "4.1.10", 827 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz", 828 | "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", 829 | "cpu": [ 830 | "arm64" 831 | ], 832 | "dev": true, 833 | "license": "MIT", 834 | "optional": true, 835 | "os": [ 836 | "android" 837 | ], 838 | "engines": { 839 | "node": ">= 10" 840 | } 841 | }, 842 | "node_modules/@tailwindcss/oxide-darwin-arm64": { 843 | "version": "4.1.10", 844 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz", 845 | "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", 846 | "cpu": [ 847 | "arm64" 848 | ], 849 | "dev": true, 850 | "license": "MIT", 851 | "optional": true, 852 | "os": [ 853 | "darwin" 854 | ], 855 | "engines": { 856 | "node": ">= 10" 857 | } 858 | }, 859 | "node_modules/@tailwindcss/oxide-darwin-x64": { 860 | "version": "4.1.10", 861 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz", 862 | "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", 863 | "cpu": [ 864 | "x64" 865 | ], 866 | "dev": true, 867 | "license": "MIT", 868 | "optional": true, 869 | "os": [ 870 | "darwin" 871 | ], 872 | "engines": { 873 | "node": ">= 10" 874 | } 875 | }, 876 | "node_modules/@tailwindcss/oxide-freebsd-x64": { 877 | "version": "4.1.10", 878 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz", 879 | "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", 880 | "cpu": [ 881 | "x64" 882 | ], 883 | "dev": true, 884 | "license": "MIT", 885 | "optional": true, 886 | "os": [ 887 | "freebsd" 888 | ], 889 | "engines": { 890 | "node": ">= 10" 891 | } 892 | }, 893 | "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { 894 | "version": "4.1.10", 895 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz", 896 | "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", 897 | "cpu": [ 898 | "arm" 899 | ], 900 | "dev": true, 901 | "license": "MIT", 902 | "optional": true, 903 | "os": [ 904 | "linux" 905 | ], 906 | "engines": { 907 | "node": ">= 10" 908 | } 909 | }, 910 | "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { 911 | "version": "4.1.10", 912 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz", 913 | "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", 914 | "cpu": [ 915 | "arm64" 916 | ], 917 | "dev": true, 918 | "license": "MIT", 919 | "optional": true, 920 | "os": [ 921 | "linux" 922 | ], 923 | "engines": { 924 | "node": ">= 10" 925 | } 926 | }, 927 | "node_modules/@tailwindcss/oxide-linux-arm64-musl": { 928 | "version": "4.1.10", 929 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz", 930 | "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", 931 | "cpu": [ 932 | "arm64" 933 | ], 934 | "dev": true, 935 | "license": "MIT", 936 | "optional": true, 937 | "os": [ 938 | "linux" 939 | ], 940 | "engines": { 941 | "node": ">= 10" 942 | } 943 | }, 944 | "node_modules/@tailwindcss/oxide-linux-x64-gnu": { 945 | "version": "4.1.10", 946 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz", 947 | "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", 948 | "cpu": [ 949 | "x64" 950 | ], 951 | "dev": true, 952 | "license": "MIT", 953 | "optional": true, 954 | "os": [ 955 | "linux" 956 | ], 957 | "engines": { 958 | "node": ">= 10" 959 | } 960 | }, 961 | "node_modules/@tailwindcss/oxide-linux-x64-musl": { 962 | "version": "4.1.10", 963 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz", 964 | "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", 965 | "cpu": [ 966 | "x64" 967 | ], 968 | "dev": true, 969 | "license": "MIT", 970 | "optional": true, 971 | "os": [ 972 | "linux" 973 | ], 974 | "engines": { 975 | "node": ">= 10" 976 | } 977 | }, 978 | "node_modules/@tailwindcss/oxide-wasm32-wasi": { 979 | "version": "4.1.10", 980 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz", 981 | "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", 982 | "bundleDependencies": [ 983 | "@napi-rs/wasm-runtime", 984 | "@emnapi/core", 985 | "@emnapi/runtime", 986 | "@tybys/wasm-util", 987 | "@emnapi/wasi-threads", 988 | "tslib" 989 | ], 990 | "cpu": [ 991 | "wasm32" 992 | ], 993 | "dev": true, 994 | "license": "MIT", 995 | "optional": true, 996 | "dependencies": { 997 | "@emnapi/core": "^1.4.3", 998 | "@emnapi/runtime": "^1.4.3", 999 | "@emnapi/wasi-threads": "^1.0.2", 1000 | "@napi-rs/wasm-runtime": "^0.2.10", 1001 | "@tybys/wasm-util": "^0.9.0", 1002 | "tslib": "^2.8.0" 1003 | }, 1004 | "engines": { 1005 | "node": ">=14.0.0" 1006 | } 1007 | }, 1008 | "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { 1009 | "version": "4.1.10", 1010 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz", 1011 | "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", 1012 | "cpu": [ 1013 | "arm64" 1014 | ], 1015 | "dev": true, 1016 | "license": "MIT", 1017 | "optional": true, 1018 | "os": [ 1019 | "win32" 1020 | ], 1021 | "engines": { 1022 | "node": ">= 10" 1023 | } 1024 | }, 1025 | "node_modules/@tailwindcss/oxide-win32-x64-msvc": { 1026 | "version": "4.1.10", 1027 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz", 1028 | "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", 1029 | "cpu": [ 1030 | "x64" 1031 | ], 1032 | "dev": true, 1033 | "license": "MIT", 1034 | "optional": true, 1035 | "os": [ 1036 | "win32" 1037 | ], 1038 | "engines": { 1039 | "node": ">= 10" 1040 | } 1041 | }, 1042 | "node_modules/@tailwindcss/postcss": { 1043 | "version": "4.1.10", 1044 | "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.10.tgz", 1045 | "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", 1046 | "dev": true, 1047 | "license": "MIT", 1048 | "dependencies": { 1049 | "@alloc/quick-lru": "^5.2.0", 1050 | "@tailwindcss/node": "4.1.10", 1051 | "@tailwindcss/oxide": "4.1.10", 1052 | "postcss": "^8.4.41", 1053 | "tailwindcss": "4.1.10" 1054 | } 1055 | }, 1056 | "node_modules/@types/node": { 1057 | "version": "24.0.4", 1058 | "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz", 1059 | "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", 1060 | "license": "MIT", 1061 | "peer": true, 1062 | "dependencies": { 1063 | "undici-types": "~7.8.0" 1064 | } 1065 | }, 1066 | "node_modules/@types/phoenix": { 1067 | "version": "1.6.6", 1068 | "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", 1069 | "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==", 1070 | "license": "MIT", 1071 | "peer": true 1072 | }, 1073 | "node_modules/@types/ws": { 1074 | "version": "8.18.1", 1075 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", 1076 | "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", 1077 | "license": "MIT", 1078 | "peer": true, 1079 | "dependencies": { 1080 | "@types/node": "*" 1081 | } 1082 | }, 1083 | "node_modules/autoprefixer": { 1084 | "version": "10.4.21", 1085 | "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", 1086 | "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", 1087 | "dev": true, 1088 | "funding": [ 1089 | { 1090 | "type": "opencollective", 1091 | "url": "https://opencollective.com/postcss/" 1092 | }, 1093 | { 1094 | "type": "tidelift", 1095 | "url": "https://tidelift.com/funding/github/npm/autoprefixer" 1096 | }, 1097 | { 1098 | "type": "github", 1099 | "url": "https://github.com/sponsors/ai" 1100 | } 1101 | ], 1102 | "license": "MIT", 1103 | "dependencies": { 1104 | "browserslist": "^4.24.4", 1105 | "caniuse-lite": "^1.0.30001702", 1106 | "fraction.js": "^4.3.7", 1107 | "normalize-range": "^0.1.2", 1108 | "picocolors": "^1.1.1", 1109 | "postcss-value-parser": "^4.2.0" 1110 | }, 1111 | "bin": { 1112 | "autoprefixer": "bin/autoprefixer" 1113 | }, 1114 | "engines": { 1115 | "node": "^10 || ^12 || >=14" 1116 | }, 1117 | "peerDependencies": { 1118 | "postcss": "^8.1.0" 1119 | } 1120 | }, 1121 | "node_modules/browserslist": { 1122 | "version": "4.25.1", 1123 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", 1124 | "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", 1125 | "dev": true, 1126 | "funding": [ 1127 | { 1128 | "type": "opencollective", 1129 | "url": "https://opencollective.com/browserslist" 1130 | }, 1131 | { 1132 | "type": "tidelift", 1133 | "url": "https://tidelift.com/funding/github/npm/browserslist" 1134 | }, 1135 | { 1136 | "type": "github", 1137 | "url": "https://github.com/sponsors/ai" 1138 | } 1139 | ], 1140 | "license": "MIT", 1141 | "dependencies": { 1142 | "caniuse-lite": "^1.0.30001726", 1143 | "electron-to-chromium": "^1.5.173", 1144 | "node-releases": "^2.0.19", 1145 | "update-browserslist-db": "^1.1.3" 1146 | }, 1147 | "bin": { 1148 | "browserslist": "cli.js" 1149 | }, 1150 | "engines": { 1151 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 1152 | } 1153 | }, 1154 | "node_modules/busboy": { 1155 | "version": "1.6.0", 1156 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 1157 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 1158 | "dependencies": { 1159 | "streamsearch": "^1.1.0" 1160 | }, 1161 | "engines": { 1162 | "node": ">=10.16.0" 1163 | } 1164 | }, 1165 | "node_modules/caniuse-lite": { 1166 | "version": "1.0.30001726", 1167 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", 1168 | "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", 1169 | "funding": [ 1170 | { 1171 | "type": "opencollective", 1172 | "url": "https://opencollective.com/browserslist" 1173 | }, 1174 | { 1175 | "type": "tidelift", 1176 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 1177 | }, 1178 | { 1179 | "type": "github", 1180 | "url": "https://github.com/sponsors/ai" 1181 | } 1182 | ], 1183 | "license": "CC-BY-4.0" 1184 | }, 1185 | "node_modules/chownr": { 1186 | "version": "3.0.0", 1187 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", 1188 | "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", 1189 | "dev": true, 1190 | "license": "BlueOak-1.0.0", 1191 | "engines": { 1192 | "node": ">=18" 1193 | } 1194 | }, 1195 | "node_modules/client-only": { 1196 | "version": "0.0.1", 1197 | "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 1198 | "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", 1199 | "license": "MIT" 1200 | }, 1201 | "node_modules/color": { 1202 | "version": "4.2.3", 1203 | "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 1204 | "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 1205 | "license": "MIT", 1206 | "optional": true, 1207 | "dependencies": { 1208 | "color-convert": "^2.0.1", 1209 | "color-string": "^1.9.0" 1210 | }, 1211 | "engines": { 1212 | "node": ">=12.5.0" 1213 | } 1214 | }, 1215 | "node_modules/color-convert": { 1216 | "version": "2.0.1", 1217 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1218 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1219 | "license": "MIT", 1220 | "optional": true, 1221 | "dependencies": { 1222 | "color-name": "~1.1.4" 1223 | }, 1224 | "engines": { 1225 | "node": ">=7.0.0" 1226 | } 1227 | }, 1228 | "node_modules/color-name": { 1229 | "version": "1.1.4", 1230 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1231 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1232 | "license": "MIT", 1233 | "optional": true 1234 | }, 1235 | "node_modules/color-string": { 1236 | "version": "1.9.1", 1237 | "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 1238 | "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 1239 | "license": "MIT", 1240 | "optional": true, 1241 | "dependencies": { 1242 | "color-name": "^1.0.0", 1243 | "simple-swizzle": "^0.2.2" 1244 | } 1245 | }, 1246 | "node_modules/detect-libc": { 1247 | "version": "2.0.4", 1248 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 1249 | "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 1250 | "devOptional": true, 1251 | "license": "Apache-2.0", 1252 | "engines": { 1253 | "node": ">=8" 1254 | } 1255 | }, 1256 | "node_modules/electron-to-chromium": { 1257 | "version": "1.5.176", 1258 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.176.tgz", 1259 | "integrity": "sha512-2nDK9orkm7M9ZZkjO3PjbEd3VUulQLyg5T9O3enJdFvUg46Hzd4DUvTvAuEgbdHYXyFsiG4A5sO9IzToMH1cDg==", 1260 | "dev": true, 1261 | "license": "ISC" 1262 | }, 1263 | "node_modules/enhanced-resolve": { 1264 | "version": "5.18.2", 1265 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", 1266 | "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", 1267 | "dev": true, 1268 | "license": "MIT", 1269 | "dependencies": { 1270 | "graceful-fs": "^4.2.4", 1271 | "tapable": "^2.2.0" 1272 | }, 1273 | "engines": { 1274 | "node": ">=10.13.0" 1275 | } 1276 | }, 1277 | "node_modules/escalade": { 1278 | "version": "3.2.0", 1279 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 1280 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 1281 | "dev": true, 1282 | "license": "MIT", 1283 | "engines": { 1284 | "node": ">=6" 1285 | } 1286 | }, 1287 | "node_modules/fraction.js": { 1288 | "version": "4.3.7", 1289 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", 1290 | "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", 1291 | "dev": true, 1292 | "license": "MIT", 1293 | "engines": { 1294 | "node": "*" 1295 | }, 1296 | "funding": { 1297 | "type": "patreon", 1298 | "url": "https://github.com/sponsors/rawify" 1299 | } 1300 | }, 1301 | "node_modules/graceful-fs": { 1302 | "version": "4.2.11", 1303 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1304 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1305 | "dev": true, 1306 | "license": "ISC" 1307 | }, 1308 | "node_modules/is-arrayish": { 1309 | "version": "0.3.2", 1310 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1311 | "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1312 | "license": "MIT", 1313 | "optional": true 1314 | }, 1315 | "node_modules/isows": { 1316 | "version": "1.0.7", 1317 | "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", 1318 | "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", 1319 | "funding": [ 1320 | { 1321 | "type": "github", 1322 | "url": "https://github.com/sponsors/wevm" 1323 | } 1324 | ], 1325 | "license": "MIT", 1326 | "peer": true, 1327 | "peerDependencies": { 1328 | "ws": "*" 1329 | } 1330 | }, 1331 | "node_modules/jiti": { 1332 | "version": "2.4.2", 1333 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", 1334 | "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", 1335 | "dev": true, 1336 | "license": "MIT", 1337 | "bin": { 1338 | "jiti": "lib/jiti-cli.mjs" 1339 | } 1340 | }, 1341 | "node_modules/jose": { 1342 | "version": "4.15.9", 1343 | "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", 1344 | "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", 1345 | "license": "MIT", 1346 | "funding": { 1347 | "url": "https://github.com/sponsors/panva" 1348 | } 1349 | }, 1350 | "node_modules/lightningcss": { 1351 | "version": "1.30.1", 1352 | "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", 1353 | "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", 1354 | "dev": true, 1355 | "license": "MPL-2.0", 1356 | "dependencies": { 1357 | "detect-libc": "^2.0.3" 1358 | }, 1359 | "engines": { 1360 | "node": ">= 12.0.0" 1361 | }, 1362 | "funding": { 1363 | "type": "opencollective", 1364 | "url": "https://opencollective.com/parcel" 1365 | }, 1366 | "optionalDependencies": { 1367 | "lightningcss-darwin-arm64": "1.30.1", 1368 | "lightningcss-darwin-x64": "1.30.1", 1369 | "lightningcss-freebsd-x64": "1.30.1", 1370 | "lightningcss-linux-arm-gnueabihf": "1.30.1", 1371 | "lightningcss-linux-arm64-gnu": "1.30.1", 1372 | "lightningcss-linux-arm64-musl": "1.30.1", 1373 | "lightningcss-linux-x64-gnu": "1.30.1", 1374 | "lightningcss-linux-x64-musl": "1.30.1", 1375 | "lightningcss-win32-arm64-msvc": "1.30.1", 1376 | "lightningcss-win32-x64-msvc": "1.30.1" 1377 | } 1378 | }, 1379 | "node_modules/lightningcss-darwin-arm64": { 1380 | "version": "1.30.1", 1381 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", 1382 | "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", 1383 | "cpu": [ 1384 | "arm64" 1385 | ], 1386 | "dev": true, 1387 | "license": "MPL-2.0", 1388 | "optional": true, 1389 | "os": [ 1390 | "darwin" 1391 | ], 1392 | "engines": { 1393 | "node": ">= 12.0.0" 1394 | }, 1395 | "funding": { 1396 | "type": "opencollective", 1397 | "url": "https://opencollective.com/parcel" 1398 | } 1399 | }, 1400 | "node_modules/lightningcss-darwin-x64": { 1401 | "version": "1.30.1", 1402 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", 1403 | "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", 1404 | "cpu": [ 1405 | "x64" 1406 | ], 1407 | "dev": true, 1408 | "license": "MPL-2.0", 1409 | "optional": true, 1410 | "os": [ 1411 | "darwin" 1412 | ], 1413 | "engines": { 1414 | "node": ">= 12.0.0" 1415 | }, 1416 | "funding": { 1417 | "type": "opencollective", 1418 | "url": "https://opencollective.com/parcel" 1419 | } 1420 | }, 1421 | "node_modules/lightningcss-freebsd-x64": { 1422 | "version": "1.30.1", 1423 | "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", 1424 | "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", 1425 | "cpu": [ 1426 | "x64" 1427 | ], 1428 | "dev": true, 1429 | "license": "MPL-2.0", 1430 | "optional": true, 1431 | "os": [ 1432 | "freebsd" 1433 | ], 1434 | "engines": { 1435 | "node": ">= 12.0.0" 1436 | }, 1437 | "funding": { 1438 | "type": "opencollective", 1439 | "url": "https://opencollective.com/parcel" 1440 | } 1441 | }, 1442 | "node_modules/lightningcss-linux-arm-gnueabihf": { 1443 | "version": "1.30.1", 1444 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", 1445 | "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", 1446 | "cpu": [ 1447 | "arm" 1448 | ], 1449 | "dev": true, 1450 | "license": "MPL-2.0", 1451 | "optional": true, 1452 | "os": [ 1453 | "linux" 1454 | ], 1455 | "engines": { 1456 | "node": ">= 12.0.0" 1457 | }, 1458 | "funding": { 1459 | "type": "opencollective", 1460 | "url": "https://opencollective.com/parcel" 1461 | } 1462 | }, 1463 | "node_modules/lightningcss-linux-arm64-gnu": { 1464 | "version": "1.30.1", 1465 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", 1466 | "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", 1467 | "cpu": [ 1468 | "arm64" 1469 | ], 1470 | "dev": true, 1471 | "license": "MPL-2.0", 1472 | "optional": true, 1473 | "os": [ 1474 | "linux" 1475 | ], 1476 | "engines": { 1477 | "node": ">= 12.0.0" 1478 | }, 1479 | "funding": { 1480 | "type": "opencollective", 1481 | "url": "https://opencollective.com/parcel" 1482 | } 1483 | }, 1484 | "node_modules/lightningcss-linux-arm64-musl": { 1485 | "version": "1.30.1", 1486 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", 1487 | "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", 1488 | "cpu": [ 1489 | "arm64" 1490 | ], 1491 | "dev": true, 1492 | "license": "MPL-2.0", 1493 | "optional": true, 1494 | "os": [ 1495 | "linux" 1496 | ], 1497 | "engines": { 1498 | "node": ">= 12.0.0" 1499 | }, 1500 | "funding": { 1501 | "type": "opencollective", 1502 | "url": "https://opencollective.com/parcel" 1503 | } 1504 | }, 1505 | "node_modules/lightningcss-linux-x64-gnu": { 1506 | "version": "1.30.1", 1507 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", 1508 | "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", 1509 | "cpu": [ 1510 | "x64" 1511 | ], 1512 | "dev": true, 1513 | "license": "MPL-2.0", 1514 | "optional": true, 1515 | "os": [ 1516 | "linux" 1517 | ], 1518 | "engines": { 1519 | "node": ">= 12.0.0" 1520 | }, 1521 | "funding": { 1522 | "type": "opencollective", 1523 | "url": "https://opencollective.com/parcel" 1524 | } 1525 | }, 1526 | "node_modules/lightningcss-linux-x64-musl": { 1527 | "version": "1.30.1", 1528 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", 1529 | "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", 1530 | "cpu": [ 1531 | "x64" 1532 | ], 1533 | "dev": true, 1534 | "license": "MPL-2.0", 1535 | "optional": true, 1536 | "os": [ 1537 | "linux" 1538 | ], 1539 | "engines": { 1540 | "node": ">= 12.0.0" 1541 | }, 1542 | "funding": { 1543 | "type": "opencollective", 1544 | "url": "https://opencollective.com/parcel" 1545 | } 1546 | }, 1547 | "node_modules/lightningcss-win32-arm64-msvc": { 1548 | "version": "1.30.1", 1549 | "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", 1550 | "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", 1551 | "cpu": [ 1552 | "arm64" 1553 | ], 1554 | "dev": true, 1555 | "license": "MPL-2.0", 1556 | "optional": true, 1557 | "os": [ 1558 | "win32" 1559 | ], 1560 | "engines": { 1561 | "node": ">= 12.0.0" 1562 | }, 1563 | "funding": { 1564 | "type": "opencollective", 1565 | "url": "https://opencollective.com/parcel" 1566 | } 1567 | }, 1568 | "node_modules/lightningcss-win32-x64-msvc": { 1569 | "version": "1.30.1", 1570 | "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", 1571 | "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", 1572 | "cpu": [ 1573 | "x64" 1574 | ], 1575 | "dev": true, 1576 | "license": "MPL-2.0", 1577 | "optional": true, 1578 | "os": [ 1579 | "win32" 1580 | ], 1581 | "engines": { 1582 | "node": ">= 12.0.0" 1583 | }, 1584 | "funding": { 1585 | "type": "opencollective", 1586 | "url": "https://opencollective.com/parcel" 1587 | } 1588 | }, 1589 | "node_modules/magic-string": { 1590 | "version": "0.30.17", 1591 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1592 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1593 | "dev": true, 1594 | "license": "MIT", 1595 | "dependencies": { 1596 | "@jridgewell/sourcemap-codec": "^1.5.0" 1597 | } 1598 | }, 1599 | "node_modules/minipass": { 1600 | "version": "7.1.2", 1601 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 1602 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 1603 | "dev": true, 1604 | "license": "ISC", 1605 | "engines": { 1606 | "node": ">=16 || 14 >=14.17" 1607 | } 1608 | }, 1609 | "node_modules/minizlib": { 1610 | "version": "3.0.2", 1611 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", 1612 | "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", 1613 | "dev": true, 1614 | "license": "MIT", 1615 | "dependencies": { 1616 | "minipass": "^7.1.2" 1617 | }, 1618 | "engines": { 1619 | "node": ">= 18" 1620 | } 1621 | }, 1622 | "node_modules/mkdirp": { 1623 | "version": "3.0.1", 1624 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", 1625 | "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", 1626 | "dev": true, 1627 | "license": "MIT", 1628 | "bin": { 1629 | "mkdirp": "dist/cjs/src/bin.js" 1630 | }, 1631 | "engines": { 1632 | "node": ">=10" 1633 | }, 1634 | "funding": { 1635 | "url": "https://github.com/sponsors/isaacs" 1636 | } 1637 | }, 1638 | "node_modules/nanoid": { 1639 | "version": "3.3.11", 1640 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1641 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1642 | "funding": [ 1643 | { 1644 | "type": "github", 1645 | "url": "https://github.com/sponsors/ai" 1646 | } 1647 | ], 1648 | "license": "MIT", 1649 | "bin": { 1650 | "nanoid": "bin/nanoid.cjs" 1651 | }, 1652 | "engines": { 1653 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1654 | } 1655 | }, 1656 | "node_modules/next": { 1657 | "version": "15.3.4", 1658 | "resolved": "https://registry.npmjs.org/next/-/next-15.3.4.tgz", 1659 | "integrity": "sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==", 1660 | "license": "MIT", 1661 | "dependencies": { 1662 | "@next/env": "15.3.4", 1663 | "@swc/counter": "0.1.3", 1664 | "@swc/helpers": "0.5.15", 1665 | "busboy": "1.6.0", 1666 | "caniuse-lite": "^1.0.30001579", 1667 | "postcss": "8.4.31", 1668 | "styled-jsx": "5.1.6" 1669 | }, 1670 | "bin": { 1671 | "next": "dist/bin/next" 1672 | }, 1673 | "engines": { 1674 | "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" 1675 | }, 1676 | "optionalDependencies": { 1677 | "@next/swc-darwin-arm64": "15.3.4", 1678 | "@next/swc-darwin-x64": "15.3.4", 1679 | "@next/swc-linux-arm64-gnu": "15.3.4", 1680 | "@next/swc-linux-arm64-musl": "15.3.4", 1681 | "@next/swc-linux-x64-gnu": "15.3.4", 1682 | "@next/swc-linux-x64-musl": "15.3.4", 1683 | "@next/swc-win32-arm64-msvc": "15.3.4", 1684 | "@next/swc-win32-x64-msvc": "15.3.4", 1685 | "sharp": "^0.34.1" 1686 | }, 1687 | "peerDependencies": { 1688 | "@opentelemetry/api": "^1.1.0", 1689 | "@playwright/test": "^1.41.2", 1690 | "babel-plugin-react-compiler": "*", 1691 | "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", 1692 | "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", 1693 | "sass": "^1.3.0" 1694 | }, 1695 | "peerDependenciesMeta": { 1696 | "@opentelemetry/api": { 1697 | "optional": true 1698 | }, 1699 | "@playwright/test": { 1700 | "optional": true 1701 | }, 1702 | "babel-plugin-react-compiler": { 1703 | "optional": true 1704 | }, 1705 | "sass": { 1706 | "optional": true 1707 | } 1708 | } 1709 | }, 1710 | "node_modules/next/node_modules/postcss": { 1711 | "version": "8.4.31", 1712 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", 1713 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", 1714 | "funding": [ 1715 | { 1716 | "type": "opencollective", 1717 | "url": "https://opencollective.com/postcss/" 1718 | }, 1719 | { 1720 | "type": "tidelift", 1721 | "url": "https://tidelift.com/funding/github/npm/postcss" 1722 | }, 1723 | { 1724 | "type": "github", 1725 | "url": "https://github.com/sponsors/ai" 1726 | } 1727 | ], 1728 | "license": "MIT", 1729 | "dependencies": { 1730 | "nanoid": "^3.3.6", 1731 | "picocolors": "^1.0.0", 1732 | "source-map-js": "^1.0.2" 1733 | }, 1734 | "engines": { 1735 | "node": "^10 || ^12 || >=14" 1736 | } 1737 | }, 1738 | "node_modules/node-releases": { 1739 | "version": "2.0.19", 1740 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", 1741 | "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", 1742 | "dev": true, 1743 | "license": "MIT" 1744 | }, 1745 | "node_modules/normalize-range": { 1746 | "version": "0.1.2", 1747 | "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", 1748 | "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", 1749 | "dev": true, 1750 | "license": "MIT", 1751 | "engines": { 1752 | "node": ">=0.10.0" 1753 | } 1754 | }, 1755 | "node_modules/picocolors": { 1756 | "version": "1.1.1", 1757 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1758 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1759 | "license": "ISC" 1760 | }, 1761 | "node_modules/postcss": { 1762 | "version": "8.5.6", 1763 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 1764 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 1765 | "dev": true, 1766 | "funding": [ 1767 | { 1768 | "type": "opencollective", 1769 | "url": "https://opencollective.com/postcss/" 1770 | }, 1771 | { 1772 | "type": "tidelift", 1773 | "url": "https://tidelift.com/funding/github/npm/postcss" 1774 | }, 1775 | { 1776 | "type": "github", 1777 | "url": "https://github.com/sponsors/ai" 1778 | } 1779 | ], 1780 | "license": "MIT", 1781 | "dependencies": { 1782 | "nanoid": "^3.3.11", 1783 | "picocolors": "^1.1.1", 1784 | "source-map-js": "^1.2.1" 1785 | }, 1786 | "engines": { 1787 | "node": "^10 || ^12 || >=14" 1788 | } 1789 | }, 1790 | "node_modules/postcss-value-parser": { 1791 | "version": "4.2.0", 1792 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 1793 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 1794 | "dev": true, 1795 | "license": "MIT" 1796 | }, 1797 | "node_modules/react": { 1798 | "version": "19.1.0", 1799 | "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", 1800 | "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", 1801 | "license": "MIT", 1802 | "engines": { 1803 | "node": ">=0.10.0" 1804 | } 1805 | }, 1806 | "node_modules/react-dom": { 1807 | "version": "19.1.0", 1808 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", 1809 | "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", 1810 | "license": "MIT", 1811 | "dependencies": { 1812 | "scheduler": "^0.26.0" 1813 | }, 1814 | "peerDependencies": { 1815 | "react": "^19.1.0" 1816 | } 1817 | }, 1818 | "node_modules/scheduler": { 1819 | "version": "0.26.0", 1820 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", 1821 | "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", 1822 | "license": "MIT" 1823 | }, 1824 | "node_modules/semver": { 1825 | "version": "7.7.2", 1826 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", 1827 | "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", 1828 | "license": "ISC", 1829 | "optional": true, 1830 | "bin": { 1831 | "semver": "bin/semver.js" 1832 | }, 1833 | "engines": { 1834 | "node": ">=10" 1835 | } 1836 | }, 1837 | "node_modules/set-cookie-parser": { 1838 | "version": "2.7.1", 1839 | "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", 1840 | "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", 1841 | "license": "MIT" 1842 | }, 1843 | "node_modules/sharp": { 1844 | "version": "0.34.2", 1845 | "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", 1846 | "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", 1847 | "hasInstallScript": true, 1848 | "license": "Apache-2.0", 1849 | "optional": true, 1850 | "dependencies": { 1851 | "color": "^4.2.3", 1852 | "detect-libc": "^2.0.4", 1853 | "semver": "^7.7.2" 1854 | }, 1855 | "engines": { 1856 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1857 | }, 1858 | "funding": { 1859 | "url": "https://opencollective.com/libvips" 1860 | }, 1861 | "optionalDependencies": { 1862 | "@img/sharp-darwin-arm64": "0.34.2", 1863 | "@img/sharp-darwin-x64": "0.34.2", 1864 | "@img/sharp-libvips-darwin-arm64": "1.1.0", 1865 | "@img/sharp-libvips-darwin-x64": "1.1.0", 1866 | "@img/sharp-libvips-linux-arm": "1.1.0", 1867 | "@img/sharp-libvips-linux-arm64": "1.1.0", 1868 | "@img/sharp-libvips-linux-ppc64": "1.1.0", 1869 | "@img/sharp-libvips-linux-s390x": "1.1.0", 1870 | "@img/sharp-libvips-linux-x64": "1.1.0", 1871 | "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", 1872 | "@img/sharp-libvips-linuxmusl-x64": "1.1.0", 1873 | "@img/sharp-linux-arm": "0.34.2", 1874 | "@img/sharp-linux-arm64": "0.34.2", 1875 | "@img/sharp-linux-s390x": "0.34.2", 1876 | "@img/sharp-linux-x64": "0.34.2", 1877 | "@img/sharp-linuxmusl-arm64": "0.34.2", 1878 | "@img/sharp-linuxmusl-x64": "0.34.2", 1879 | "@img/sharp-wasm32": "0.34.2", 1880 | "@img/sharp-win32-arm64": "0.34.2", 1881 | "@img/sharp-win32-ia32": "0.34.2", 1882 | "@img/sharp-win32-x64": "0.34.2" 1883 | } 1884 | }, 1885 | "node_modules/simple-swizzle": { 1886 | "version": "0.2.2", 1887 | "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 1888 | "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 1889 | "license": "MIT", 1890 | "optional": true, 1891 | "dependencies": { 1892 | "is-arrayish": "^0.3.1" 1893 | } 1894 | }, 1895 | "node_modules/source-map-js": { 1896 | "version": "1.2.1", 1897 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1898 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1899 | "license": "BSD-3-Clause", 1900 | "engines": { 1901 | "node": ">=0.10.0" 1902 | } 1903 | }, 1904 | "node_modules/streamsearch": { 1905 | "version": "1.1.0", 1906 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 1907 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", 1908 | "engines": { 1909 | "node": ">=10.0.0" 1910 | } 1911 | }, 1912 | "node_modules/styled-jsx": { 1913 | "version": "5.1.6", 1914 | "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", 1915 | "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", 1916 | "license": "MIT", 1917 | "dependencies": { 1918 | "client-only": "0.0.1" 1919 | }, 1920 | "engines": { 1921 | "node": ">= 12.0.0" 1922 | }, 1923 | "peerDependencies": { 1924 | "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" 1925 | }, 1926 | "peerDependenciesMeta": { 1927 | "@babel/core": { 1928 | "optional": true 1929 | }, 1930 | "babel-plugin-macros": { 1931 | "optional": true 1932 | } 1933 | } 1934 | }, 1935 | "node_modules/tailwindcss": { 1936 | "version": "4.1.10", 1937 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", 1938 | "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", 1939 | "dev": true, 1940 | "license": "MIT" 1941 | }, 1942 | "node_modules/tapable": { 1943 | "version": "2.2.2", 1944 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", 1945 | "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", 1946 | "dev": true, 1947 | "license": "MIT", 1948 | "engines": { 1949 | "node": ">=6" 1950 | } 1951 | }, 1952 | "node_modules/tar": { 1953 | "version": "7.4.3", 1954 | "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", 1955 | "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", 1956 | "dev": true, 1957 | "license": "ISC", 1958 | "dependencies": { 1959 | "@isaacs/fs-minipass": "^4.0.0", 1960 | "chownr": "^3.0.0", 1961 | "minipass": "^7.1.2", 1962 | "minizlib": "^3.0.1", 1963 | "mkdirp": "^3.0.1", 1964 | "yallist": "^5.0.0" 1965 | }, 1966 | "engines": { 1967 | "node": ">=18" 1968 | } 1969 | }, 1970 | "node_modules/tr46": { 1971 | "version": "0.0.3", 1972 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1973 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", 1974 | "license": "MIT", 1975 | "peer": true 1976 | }, 1977 | "node_modules/tslib": { 1978 | "version": "2.8.1", 1979 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 1980 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 1981 | "license": "0BSD" 1982 | }, 1983 | "node_modules/undici-types": { 1984 | "version": "7.8.0", 1985 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", 1986 | "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", 1987 | "license": "MIT", 1988 | "peer": true 1989 | }, 1990 | "node_modules/update-browserslist-db": { 1991 | "version": "1.1.3", 1992 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", 1993 | "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", 1994 | "dev": true, 1995 | "funding": [ 1996 | { 1997 | "type": "opencollective", 1998 | "url": "https://opencollective.com/browserslist" 1999 | }, 2000 | { 2001 | "type": "tidelift", 2002 | "url": "https://tidelift.com/funding/github/npm/browserslist" 2003 | }, 2004 | { 2005 | "type": "github", 2006 | "url": "https://github.com/sponsors/ai" 2007 | } 2008 | ], 2009 | "license": "MIT", 2010 | "dependencies": { 2011 | "escalade": "^3.2.0", 2012 | "picocolors": "^1.1.1" 2013 | }, 2014 | "bin": { 2015 | "update-browserslist-db": "cli.js" 2016 | }, 2017 | "peerDependencies": { 2018 | "browserslist": ">= 4.21.0" 2019 | } 2020 | }, 2021 | "node_modules/webidl-conversions": { 2022 | "version": "3.0.1", 2023 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2024 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", 2025 | "license": "BSD-2-Clause", 2026 | "peer": true 2027 | }, 2028 | "node_modules/whatwg-url": { 2029 | "version": "5.0.0", 2030 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2031 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2032 | "license": "MIT", 2033 | "peer": true, 2034 | "dependencies": { 2035 | "tr46": "~0.0.3", 2036 | "webidl-conversions": "^3.0.0" 2037 | } 2038 | }, 2039 | "node_modules/ws": { 2040 | "version": "8.18.2", 2041 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", 2042 | "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", 2043 | "license": "MIT", 2044 | "peer": true, 2045 | "engines": { 2046 | "node": ">=10.0.0" 2047 | }, 2048 | "peerDependencies": { 2049 | "bufferutil": "^4.0.1", 2050 | "utf-8-validate": ">=5.0.2" 2051 | }, 2052 | "peerDependenciesMeta": { 2053 | "bufferutil": { 2054 | "optional": true 2055 | }, 2056 | "utf-8-validate": { 2057 | "optional": true 2058 | } 2059 | } 2060 | }, 2061 | "node_modules/yallist": { 2062 | "version": "5.0.0", 2063 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", 2064 | "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", 2065 | "dev": true, 2066 | "license": "BlueOak-1.0.0", 2067 | "engines": { 2068 | "node": ">=18" 2069 | } 2070 | } 2071 | } 2072 | } 2073 | --------------------------------------------------------------------------------