From dbaf5fa06356e4c736178b72697696b92d233275 Mon Sep 17 00:00:00 2001 From: drjones Date: Tue, 11 Aug 2026 04:32:35 +0000 Subject: [PATCH] Initial commit: DroidFleet Visor - Fleet management dashboard --- .gitignore | 5 + README.md | 20 + index.html | 13 + metadata.json | 6 + package-lock.json | 4295 +++++++++++++++++ package.json | 34 + server.ts | 1268 +++++ src/App.tsx | 364 ++ src/components/AdbConsole.tsx | 224 + src/components/AndroidScreenViewer.tsx | 1765 +++++++ src/components/BootloaderStudio.tsx | 224 + src/components/DeployVmWizardModal.tsx | 350 ++ src/components/FacebookAppView.tsx | 619 +++ src/components/GmailAppView.tsx | 356 ++ src/components/HypervisorConsole.tsx | 365 ++ src/components/InstagramAppView.tsx | 1046 ++++ src/components/McpApiStudio.tsx | 618 +++ src/components/Navbar.tsx | 169 + src/components/PricingModal.tsx | 240 + .../ProgrammaticAutomationStudio.tsx | 474 ++ src/components/ProxyManagerStudio.tsx | 619 +++ src/data/deviceProfiles.ts | 133 + src/main.tsx | 9 + src/types.ts | 170 + 24 files changed, 13386 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.html create mode 100644 metadata.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 server.ts create mode 100644 src/App.tsx create mode 100644 src/components/AdbConsole.tsx create mode 100644 src/components/AndroidScreenViewer.tsx create mode 100644 src/components/BootloaderStudio.tsx create mode 100644 src/components/DeployVmWizardModal.tsx create mode 100644 src/components/FacebookAppView.tsx create mode 100644 src/components/GmailAppView.tsx create mode 100644 src/components/HypervisorConsole.tsx create mode 100644 src/components/InstagramAppView.tsx create mode 100644 src/components/McpApiStudio.tsx create mode 100644 src/components/Navbar.tsx create mode 100644 src/components/PricingModal.tsx create mode 100644 src/components/ProgrammaticAutomationStudio.tsx create mode 100644 src/components/ProxyManagerStudio.tsx create mode 100644 src/data/deviceProfiles.ts create mode 100644 src/main.tsx create mode 100644 src/types.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4274b51 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.env +*.log +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..e81068b --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +
+GHBanner +
+ +# Run and deploy your AI Studio app + +This contains everything you need to run your app locally. + +View your app in AI Studio: https://ai.studio/apps/4a310be8-e39a-4b78-b317-f2fffa484015 + +## Run Locally + +**Prerequisites:** Node.js + + +1. Install dependencies: + `npm install` +2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key +3. Run the app: + `npm run dev` diff --git a/index.html b/index.html new file mode 100644 index 0000000..f1564cf --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + DroidFleet Visor + + + +
+ + + diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..e30f35b --- /dev/null +++ b/metadata.json @@ -0,0 +1,6 @@ +{ + "name": "Android Hypervisor Cloud", + "description": "Cloud virtualization platform for deploying, managing, and renting Android virtual devices with custom bootloaders, root access, and interactive WebRTC/ADB screen streaming.", + "requestFramePermissions": [], + "majorCapabilities": ["MAJOR_CAPABILITY_SERVER_SIDE_GEMINI_API"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..acdfc3e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4295 @@ +{ + "name": "react-example", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "react-example", + "version": "0.0.0", + "dependencies": { + "@google/genai": "^2.4.0", + "@tailwindcss/vite": "^4.1.14", + "@vitejs/plugin-react": "^5.0.4", + "dotenv": "^17.2.3", + "express": "^4.21.2", + "lucide-react": "^0.546.0", + "motion": "^12.23.24", + "react": "^19.0.1", + "react-dom": "^19.0.1", + "vite": "^6.2.3" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/node": "^22.14.0", + "autoprefixer": "^10.4.21", + "esbuild": "^0.25.0", + "tailwindcss": "^4.1.14", + "tsx": "^4.21.0", + "typescript": "~5.8.2", + "vite": "^6.2.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@google/genai": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.16.0.tgz", + "integrity": "sha512-K+1C1sqR0u7NJ5xpKJCQBws0QXpfuklo3WTNuUIMvtbQfNW2O5OohX0BYT2V+PXzsUzQEwGCXPWQxttLyGQ6xw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "license": "BSD-3-Clause" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", + "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.6", + "caniuse-lite": "^1.0.30001806", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", + "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.404", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.404.tgz", + "integrity": "sha512-3WJtd7/lVq2Jnuz6wed1l9+1ZD2u2Tet1/1NBc4Iedkmgbu+I7YuAqdAQ8T+VZtnwysMsAf3IqSq9D1gyZjA2g==", + "license": "ISC" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/framer-motion": { + "version": "12.43.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.43.0.tgz", + "integrity": "sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.43.0", + "motion-utils": "^12.39.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.0.tgz", + "integrity": "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.546.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz", + "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/motion": { + "version": "12.43.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.43.0.tgz", + "integrity": "sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.43.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.43.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.43.0.tgz", + "integrity": "sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.39.0" + } + }, + "node_modules/motion-utils": { + "version": "12.39.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", + "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.8" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rollup": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.23.12", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz", + "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8b9110e --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "react-example", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "tsx server.ts", + "build": "vite build && esbuild server.ts --bundle --platform=node --format=cjs --packages=external --sourcemap --outfile=dist/server.cjs", + "start": "node dist/server.cjs", + "lint": "tsc --noEmit" + }, + "dependencies": { + "@google/genai": "^2.4.0", + "@tailwindcss/vite": "^4.1.14", + "@vitejs/plugin-react": "^5.0.4", + "lucide-react": "^0.546.0", + "react": "^19.0.1", + "react-dom": "^19.0.1", + "vite": "^6.2.3", + "express": "^4.21.2", + "dotenv": "^17.2.3", + "motion": "^12.23.24" + }, + "devDependencies": { + "@types/node": "^22.14.0", + "autoprefixer": "^10.4.21", + "esbuild": "^0.25.0", + "tailwindcss": "^4.1.14", + "tsx": "^4.21.0", + "typescript": "~5.8.2", + "vite": "^6.2.3", + "@types/express": "^4.17.21" + } +} diff --git a/server.ts b/server.ts new file mode 100644 index 0000000..28f9e2f --- /dev/null +++ b/server.ts @@ -0,0 +1,1268 @@ +import express from 'express'; +import { createServer as createViteServer } from 'vite'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import dotenv from 'dotenv'; +import { + AndroidVM, + UserSubscription, + AndroidVersion, + Architecture, + BootloaderConfig, + DeviceProfileId, + ProxyConfig, + ProxyType, +} from './src/types.js'; +import { HardwareProfiles, DEFAULT_ANDROID_APPS } from './src/data/deviceProfiles.js'; + +dotenv.config(); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const app = express(); +const PORT = 3000; + +app.use(express.json({ limit: '50mb' })); + +// In-Memory Database for Hypervisor & Rental Subscriptions +let userSubscription: UserSubscription = { + plan: 'free', + maxVms: 1, // 1 Free VM instance + pricePerMonth: 0, + activeVmCount: 1, + renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), + paymentMethod: 'Free Tier Active', +}; + +let virtualMachines: AndroidVM[] = [ + { + id: 'vm-cloud-001', + name: 'Pixel 8 Pro - Android 14 (AOSP)', + androidVersion: '14 (UpsideDownCake)', + arch: 'x86_64', + profile: HardwareProfiles.PIXEL_8_PRO, + ramGb: 8, + vcpu: 4, + storageGb: 64, + bootloader: { + isUnlocked: true, + rootMethod: 'magisk', + customRecovery: true, + selinuxMode: 'permissive', + kernelCmdline: 'console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=permissive', + gpuAcceleration: 'swiftshader', + }, + status: 'running', + ipAddress: '192.168.122.105', + adbPort: 5555, + vncPort: 5901, + batteryLevel: 94, + isCharging: true, + orientation: 'portrait', + location: { + latitude: 37.7749, + longitude: -122.4194, + addressName: 'San Francisco, CA, USA', + }, + metrics: { + cpuUsagePct: 18.5, + ramUsageMb: 3420, + totalRamMb: 8192, + fps: 60, + networkRxKbps: 450, + networkTxKbps: 120, + uptimeSeconds: 14200, + }, + installedApps: [...DEFAULT_ANDROID_APPS], + currentAppPackage: 'com.android.launcher3', + proxy: { + id: 'px-1', + enabled: true, + type: 'SOCKS5', + host: '104.28.19.42', + port: 1080, + country: 'United States', + countryCode: 'US', + anonymity: 'Elite', + latencyMs: 38, + externalIp: '104.28.19.42', + }, + createdAt: new Date(Date.now() - 4 * 3600 * 1000).toISOString(), + snapshotCount: 2, + }, +]; + +// Proxifly Master Proxy Pool Dataset +const PROXIFLY_PROXIES: ProxyConfig[] = [ + { id: 'px-1', enabled: true, type: 'SOCKS5', host: '104.28.19.42', port: 1080, country: 'United States', countryCode: 'US', anonymity: 'Elite', latencyMs: 38, externalIp: '104.28.19.42' }, + { id: 'px-2', enabled: true, type: 'HTTP', host: '185.220.101.5', port: 8080, country: 'Germany', countryCode: 'DE', anonymity: 'Elite', latencyMs: 62, externalIp: '185.220.101.5' }, + { id: 'px-3', enabled: true, type: 'SOCKS5', host: '139.162.24.11', port: 1080, country: 'Japan', countryCode: 'JP', anonymity: 'Elite', latencyMs: 110, externalIp: '139.162.24.11' }, + { id: 'px-4', enabled: true, type: 'HTTPS', host: '51.15.22.180', port: 3128, country: 'France', countryCode: 'FR', anonymity: 'Anonymous', latencyMs: 75, externalIp: '51.15.22.180' }, + { id: 'px-5', enabled: true, type: 'SOCKS5', host: '128.199.201.89', port: 1080, country: 'Singapore', countryCode: 'SG', anonymity: 'Elite', latencyMs: 145, externalIp: '128.199.201.89' }, + { id: 'px-6', enabled: true, type: 'HTTP', host: '198.244.180.20', port: 8000, country: 'United Kingdom', countryCode: 'GB', anonymity: 'Elite', latencyMs: 54, externalIp: '198.244.180.20' }, + { id: 'px-7', enabled: true, type: 'SOCKS5', host: '159.203.42.109', port: 1080, country: 'Canada', countryCode: 'CA', anonymity: 'Elite', latencyMs: 42, externalIp: '159.203.42.109' }, + { id: 'px-8', enabled: true, type: 'HTTP', host: '177.71.180.4', port: 8080, country: 'Brazil', countryCode: 'BR', anonymity: 'Anonymous', latencyMs: 168, externalIp: '177.71.180.4' }, + { id: 'px-9', enabled: true, type: 'SOCKS5', host: '103.214.112.50', port: 1080, country: 'India', countryCode: 'IN', anonymity: 'Elite', latencyMs: 195, externalIp: '103.214.112.50' }, + { id: 'px-10', enabled: true, type: 'HTTPS', host: '45.76.182.90', port: 8443, country: 'Australia', countryCode: 'AU', anonymity: 'Elite', latencyMs: 180, externalIp: '45.76.182.90' }, + { id: 'px-11', enabled: true, type: 'SOCKS5', host: '211.233.72.18', port: 1080, country: 'South Korea', countryCode: 'KR', anonymity: 'Elite', latencyMs: 128, externalIp: '211.233.72.18' }, + { id: 'px-12', enabled: true, type: 'HTTP', host: '94.23.148.10', port: 3128, country: 'Netherlands', countryCode: 'NL', anonymity: 'Elite', latencyMs: 49, externalIp: '94.23.148.10' }, +]; + +// Synchronize Subscription Count +function syncActiveVmCount() { + userSubscription.activeVmCount = virtualMachines.length; +} + +// Background simulation for VM metrics (CPU, RAM, FPS updates) +setInterval(() => { + virtualMachines.forEach((vm) => { + if (vm.status === 'running') { + vm.metrics.cpuUsagePct = Math.round((10 + Math.random() * 35) * 10) / 10; + vm.metrics.fps = Math.round(55 + Math.random() * 5); + vm.metrics.networkRxKbps = Math.round(100 + Math.random() * 800); + vm.metrics.networkTxKbps = Math.round(20 + Math.random() * 200); + vm.metrics.uptimeSeconds += 2; + } + }); +}, 2000); + +// ================= API ENDPOINTS ================= // + +// 1. Health check +app.get('/api/health', (req, res) => { + res.json({ + status: 'ok', + kvmAvailable: true, + hypervisorVersion: 'KVM/QEMU 8.2.0 (VirtIO-GPU Accelerated)', + vmsActive: virtualMachines.length, + timestamp: new Date().toISOString(), + }); +}); + +// 2. Get User Rental Subscription Status +app.get('/api/user/subscription', (req, res) => { + syncActiveVmCount(); + res.json(userSubscription); +}); + +// 3. Upgrade or Switch Subscription Tier ($5/mo for 5 VMs) +app.post('/api/user/subscription/upgrade', (req, res) => { + const { targetPlan, paymentMethod } = req.body; + + if (targetPlan === 'pro') { + userSubscription = { + plan: 'pro', + maxVms: 5, // 5 VMs for $5/mo + pricePerMonth: 5, + activeVmCount: virtualMachines.length, + renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), + paymentMethod: paymentMethod || 'Visa ending in 4242', + }; + } else { + userSubscription = { + plan: 'free', + maxVms: 1, // 1 Free VM + pricePerMonth: 0, + activeVmCount: virtualMachines.length, + renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), + paymentMethod: 'Free Tier Active', + }; + } + + res.json({ + message: `Successfully updated subscription to ${userSubscription.plan.toUpperCase()} tier!`, + subscription: userSubscription, + }); +}); + +// 4. List All Virtual Machines +app.get('/api/vms', (req, res) => { + res.json(virtualMachines); +}); + +// 5. Create / Deploy New Android Virtual Device +app.post('/api/vms/create', (req, res) => { + syncActiveVmCount(); + + // Enforce Rental Tier Limit + if (virtualMachines.length >= userSubscription.maxVms) { + return res.status(403).json({ + error: 'SUBSCRIPTION_LIMIT_EXCEEDED', + message: `Your current ${userSubscription.plan.toUpperCase()} plan limit is ${userSubscription.maxVms} Android VM(s). Upgrade to Pro ($5/mo for 5 Android VMs) to deploy more instances!`, + currentPlan: userSubscription.plan, + maxVms: userSubscription.maxVms, + }); + } + + const { + name, + androidVersion = '14 (UpsideDownCake)', + arch = 'x86_64', + profileId = 'pixel-8-pro', + ramGb = 8, + vcpu = 4, + storageGb = 64, + bootloaderUnlocked = true, + rootMethod = 'magisk', + selinuxMode = 'permissive', + gpuAcceleration = 'swiftshader', + } = req.body; + + let selectedProfile = HardwareProfiles.PIXEL_8_PRO; + if (profileId === 'galaxy-s24-ultra') selectedProfile = HardwareProfiles.GALAXY_S24_ULTRA; + if (profileId === 'oneplus-12') selectedProfile = HardwareProfiles.ONEPLUS_12; + if (profileId === 'aosp-tablet-10') selectedProfile = HardwareProfiles.AOSP_TABLET; + + const newVmId = `vm-cloud-00${virtualMachines.length + 1}`; + const assignedAdbPort = 5555 + virtualMachines.length; + const assignedVncPort = 5901 + virtualMachines.length; + + const newVm: AndroidVM = { + id: newVmId, + name: name || `${selectedProfile.name} - Android ${androidVersion.split(' ')[0]}`, + androidVersion: androidVersion as AndroidVersion, + arch: arch as Architecture, + profile: selectedProfile, + ramGb: Number(ramGb), + vcpu: Number(vcpu), + storageGb: Number(storageGb), + bootloader: { + isUnlocked: Boolean(bootloaderUnlocked), + rootMethod: rootMethod, + customRecovery: true, + selinuxMode: selinuxMode, + kernelCmdline: `console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=${selinuxMode}`, + gpuAcceleration: gpuAcceleration, + }, + status: 'running', + ipAddress: `192.168.122.${105 + virtualMachines.length}`, + adbPort: assignedAdbPort, + vncPort: assignedVncPort, + batteryLevel: 100, + isCharging: true, + orientation: 'portrait', + location: { + latitude: 37.7749, + longitude: -122.4194, + addressName: 'San Francisco, CA, USA', + }, + metrics: { + cpuUsagePct: 12.0, + ramUsageMb: Math.round(Number(ramGb) * 1024 * 0.35), + totalRamMb: Number(ramGb) * 1024, + fps: 60, + networkRxKbps: 320, + networkTxKbps: 80, + uptimeSeconds: 10, + }, + installedApps: [...DEFAULT_ANDROID_APPS], + currentAppPackage: 'com.android.launcher3', + createdAt: new Date().toISOString(), + snapshotCount: 1, + }; + + virtualMachines.push(newVm); + syncActiveVmCount(); + + res.status(201).json(newVm); +}); + +// 6. Delete / Terminate Android VM Instance +app.delete('/api/vms/:id', (req, res) => { + const { id } = req.params; + const initialLen = virtualMachines.length; + virtualMachines = virtualMachines.filter((vm) => vm.id !== id); + + if (virtualMachines.length === initialLen) { + return res.status(404).json({ error: 'VM instance not found' }); + } + + syncActiveVmCount(); + res.json({ message: `Terminated VM instance ${id}`, activeVms: virtualMachines.length }); +}); + +// 7. Power Actions (Start, Reboot, Stop, Fastboot, Recovery, Reset) +app.post('/api/vms/:id/power', (req, res) => { + const { id } = req.params; + const { action } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) { + return res.status(404).json({ error: 'VM not found' }); + } + + if (action === 'start') { + vm.status = 'running'; + vm.metrics.uptimeSeconds = 0; + } else if (action === 'stop') { + vm.status = 'stopped'; + } else if (action === 'reboot') { + vm.status = 'booting'; + setTimeout(() => { + vm.status = 'running'; + vm.metrics.uptimeSeconds = 0; + }, 2000); + } else if (action === 'boot_fastboot') { + vm.status = 'fastboot'; + } else if (action === 'boot_recovery') { + vm.status = 'recovery'; + } else if (action === 'reset') { + vm.installedApps = [...DEFAULT_ANDROID_APPS]; + vm.currentAppPackage = 'com.android.launcher3'; + vm.status = 'running'; + } + + res.json({ message: `Executed power action ${action} on ${vm.name}`, vm }); +}); + +// 8. Execute ADB Shell Commands +app.post('/api/vms/:id/adb', (req, res) => { + const { id } = req.params; + const { command } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + const cmd = (command || '').trim(); + let output = ''; + + if (cmd.includes('settings get global http_proxy')) { + output = vm.proxy && vm.proxy.enabled ? `${vm.proxy.host}:${vm.proxy.port}` : ':0'; + } else if (cmd.includes('settings put global http_proxy')) { + const val = cmd.split('http_proxy')[1]?.trim() || ''; + if (val === ':0' || val === 'none' || val === '""') { + if (vm.proxy) vm.proxy.enabled = false; + output = `Global HTTP proxy reset to direct WAN.`; + } else { + const [host, portStr] = val.split(':'); + const port = parseInt(portStr || '8080'); + vm.proxy = { + enabled: true, + type: 'HTTP', + host: host || '127.0.0.1', + port, + country: 'Configured Proxy', + countryCode: 'US', + externalIp: host, + latencyMs: 45, + }; + output = `Global HTTP proxy set to ${host}:${port}`; + } + } else if (cmd.includes('curl ifconfig.me') || cmd.includes('myip') || cmd.includes('ip route')) { + if (vm.proxy && vm.proxy.enabled) { + output = `[Proxy Route Active via ${vm.proxy.type}]\nExit IP: ${vm.proxy.externalIp || vm.proxy.host}\nHost Port: ${vm.proxy.host}:${vm.proxy.port}\nLocation: ${vm.proxy.country || 'Global Proxy'} (${vm.proxy.countryCode || 'US'})\nAnonymity Level: ${vm.proxy.anonymity || 'Elite'}`; + } else { + output = `[Direct WAN Connection]\nPublic IP: ${vm.ipAddress}\nProxy: Disabled (Direct Connection)`; + } + } else if (cmd.startsWith('adb shell getprop') || cmd === 'getprop') { + output = `[ro.build.version.release]: [${vm.androidVersion.split(' ')[0]}] +[ro.build.version.sdk]: [34] +[ro.product.model]: [${vm.profile.name}] +[ro.product.brand]: [${vm.profile.manufacturer}] +[ro.boot.flash.locked]: [${vm.bootloader.isUnlocked ? '0' : '1'}] +[ro.boot.selinux]: [${vm.bootloader.selinuxMode}] +[ro.hardware]: [qcom] +[ro.sf.lcd_density]: [${vm.profile.densityDpi}] +[net.dns1]: [8.8.8.8]`; + } else if (cmd.includes('input tap')) { + const parts = cmd.split('input tap')[1]?.trim().split(/\s+/) || ['0', '0']; + const x = parts[0] || '100'; + const y = parts[1] || '200'; + output = `[Input Event] Simulated touch tap at (${x}, ${y}) on device screen display_id=0`; + } else if (cmd.includes('input text')) { + const text = cmd.split('input text')[1]?.trim() || ''; + output = `[Input Event] Injected IME text string: "${text.replace(/^['"]|['"]$/g, '')}"`; + } else if (cmd.includes('input keyevent')) { + const key = cmd.split('input keyevent')[1]?.trim() || 'HOME'; + output = `[Input Event] Injected hardware keyevent: ${key}`; + } else if (cmd.includes('input swipe')) { + output = `[Input Event] Simulated touch drag gesture ${cmd}`; + } else if (cmd.includes('am start')) { + const pkgMatch = cmd.match(/(com\.[a-zA-Z0-0_.]+)/); + const targetPkg = pkgMatch ? pkgMatch[1] : 'com.android.launcher3'; + vm.currentAppPackage = targetPkg; + output = `Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=${targetPkg} }\nStatus: Activity launched successfully on VM display #0`; + } else if (cmd.includes('monkey')) { + const pkgMatch = cmd.match(/-p\s+(com\.[a-zA-Z0-0_.]+)/); + const targetPkg = pkgMatch ? pkgMatch[1] : vm.currentAppPackage; + output = `:Monkey: seed=1723328200 count=100 +:AllowPackage: ${targetPkg} +:IncludeCategory: android.intent.category.LAUNCHER +// Event injected: 100 pseudo-random touch/drag/key gestures +// Activity: ${targetPkg} handled 100/100 events with 0 crashes or ANRs. +Events injected: 100 +System appear to be: aOK (animator stops, top activity=${targetPkg})`; + } else if (cmd.startsWith('adb install') || cmd.includes('pm install')) { + const apkName = cmd.split('/').pop()?.replace('.apk', '') || 'CustomApp'; + const pkgName = `com.custom.${apkName.toLowerCase().replace(/[^a-z0-0]/g, '')}`; + const exists = vm.installedApps.some((a) => a.packageName === pkgName); + if (!exists) { + vm.installedApps.push({ + packageName: pkgName, + appName: apkName.toUpperCase(), + version: '1.0.0-release', + iconName: 'Smartphone', + isSystem: false, + sizeMb: 24.5, + }); + } + output = `Performing Streamed Install\nSuccess: Package ${pkgName} installed on system storage`; + } else if (cmd.includes('pm list packages') || cmd === 'pm list') { + output = vm.installedApps.map((a) => `package:${a.packageName}`).join('\n'); + } else if (cmd.startsWith('su')) { + if (vm.bootloader.rootMethod !== 'none') { + output = `# root@${vm.profile.id}:/# id\nuid=0(root) gid=0(root) groups=0(root) context=u:r:su:s0\nRoot privilege granted via ${vm.bootloader.rootMethod.toUpperCase()}`; + } else { + output = `Permission denied: Root privilege unavailable (Bootloader Root is NONE)`; + } + } else if (cmd.includes('cat /proc/cpuinfo')) { + output = `Processor\t: ARMv8 Processor rev 4 (v8l) +processor\t: 0..${vm.vcpu - 1} +BogoMIPS\t: 38.40 +Features\t: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp +CPU implementer\t: 0x51 +CPU architecture: 8 +CPU variant\t: 0x2 +CPU part\t: 0x805 +CPU revision\t: 1 +Hardware\t: Hypervisor VirtIO QEMU`; + } else if (cmd.includes('dumpsys battery')) { + output = `Current Battery Service state: + AC powered: false + USB powered: ${vm.isCharging} + Wireless powered: false + level: ${vm.batteryLevel} + scale: 100 + voltage: 4210 + temperature: 284 + technology: Li-ion`; + } else if (cmd.includes('dumpsys activity')) { + output = `ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) + Display #0 (activities from top to bottom): + Stack #1: type=standard mode=fullscreen + Task id #12 + * ActivityRecord{b4a12c u0 ${vm.currentAppPackage} t12} + running=true visible=true task=Task{b4a12c #12}`; + } else if (cmd.includes('logcat')) { + output = `08-10 18:00:12.102 1024 1024 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=${vm.currentAppPackage}} +08-10 18:00:12.145 1024 1240 D SurfaceFlinger: Layer ${vm.currentAppPackage} rendered at 60.0 FPS +08-10 18:00:12.210 512 512 I Magisk : [SU] Shell (uid: 2000) granted superuser permissions`; + } else { + output = `[adb shell @ ${vm.ipAddress}:${vm.adbPort}]\n$ ${cmd}\nCommand executed successfully with status 0.`; + } + + res.json({ output, exitCode: 0, executionTimeMs: 38 }); +}); + +// 8b. Execute Programmatic Automation Script Endpoint +app.post('/api/vms/:id/automation/run', (req, res) => { + const { id } = req.params; + const { steps } = req.body; // array of step objects or command strings + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + if (!Array.isArray(steps) || steps.length === 0) { + return res.status(400).json({ error: 'Invalid or empty automation steps array' }); + } + + const logs: string[] = []; + logs.push(`[Automation Engine] Initialized script execution on VM ${vm.name} (${vm.ipAddress}:${vm.adbPort})`); + + steps.forEach((step: any, index: number) => { + const stepNum = index + 1; + if (typeof step === 'string') { + if (step.startsWith('START_APP') || step.startsWith('am start')) { + const pkg = step.split(/\s+/)[1] || 'com.facebook.katana'; + vm.currentAppPackage = pkg; + logs.push(`Step ${stepNum}: [AM START] Launched target package -> ${pkg}`); + } else if (step.startsWith('TAP') || step.includes('input tap')) { + logs.push(`Step ${stepNum}: [INPUT TAP] Simulated touch tap at ${step.replace(/TAP|input tap/g, '').trim()}`); + } else if (step.startsWith('TEXT') || step.includes('input text')) { + logs.push(`Step ${stepNum}: [INPUT TEXT] Injected IME text: "${step.replace(/TEXT|input text/g, '').trim()}"`); + } else if (step.startsWith('INSTALL') || step.includes('adb install')) { + const pkg = step.split(/\s+/)[1] || 'com.app.newpackage'; + const name = pkg.split('.').pop()?.toUpperCase() || 'NEW APP'; + if (!vm.installedApps.some((a) => a.packageName === pkg)) { + vm.installedApps.push({ + packageName: pkg, + appName: name, + version: '1.0.0', + iconName: 'Smartphone', + isSystem: false, + sizeMb: 32.0, + }); + } + logs.push(`Step ${stepNum}: [PACKAGE MANAGER] Stream installed package -> ${pkg}`); + } else if (step.startsWith('SLEEP')) { + logs.push(`Step ${stepNum}: [SYSTEM DELAY] Paused thread execution for ${step.split(' ')[1] || '1000'}ms`); + } else { + logs.push(`Step ${stepNum}: [ADB COMMAND] Executed: ${step}`); + } + } else if (typeof step === 'object' && step.action) { + if (step.action === 'start_app') { + vm.currentAppPackage = step.package || 'com.facebook.katana'; + logs.push(`Step ${stepNum}: [AM START] Launched ${vm.currentAppPackage}`); + } else if (step.action === 'install') { + const pkg = step.package || 'com.custom.app'; + const name = step.appName || 'Custom App'; + if (!vm.installedApps.some((a) => a.packageName === pkg)) { + vm.installedApps.push({ + packageName: pkg, + appName: name, + version: '1.0.0', + iconName: 'Smartphone', + isSystem: false, + sizeMb: 45.0, + }); + } + logs.push(`Step ${stepNum}: [INSTALL] Package ${pkg} (${name}) installed successfully`); + } else if (step.action === 'tap') { + logs.push(`Step ${stepNum}: [TAP] Coordinates X:${step.x || 150}, Y:${step.y || 300}`); + } else if (step.action === 'text') { + logs.push(`Step ${stepNum}: [TEXT] Typed: "${step.text || 'Hello'}"`); + } else { + logs.push(`Step ${stepNum}: [ACTION] Executed ${step.action}`); + } + } + }); + + logs.push(`[Automation Engine] Script finished successfully with 0 errors. All ${steps.length} steps executed.`); + + res.json({ + status: 'SUCCESS', + executedStepsCount: steps.length, + logs, + currentAppPackage: vm.currentAppPackage, + installedAppsCount: vm.installedApps.length, + }); +}); + +// 9. Fastboot Commands +app.post('/api/vms/:id/fastboot', (req, res) => { + const { id } = req.params; + const { command } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + let output = 'OKAY [ 0.015s]'; + if (command === 'fastboot oem unlock' || command === 'fastboot flashing unlock') { + vm.bootloader.isUnlocked = true; + output = `(...) Unlocking bootloader...\nOKAY [ 0.412s]\nBootloader unlocked successfully.`; + } else if (command === 'fastboot devices') { + output = `${vm.id.toUpperCase()}\tfastboot`; + } else if (command.includes('flash boot')) { + output = `sending 'boot' (32768 KB)... OKAY [ 0.812s]\nwriting 'boot'... OKAY [ 1.120s]\nFinished. Total time: 1.932s`; + } + + res.json({ output, status: 'OKAY' }); +}); + +// 10. Install APK Endpoint +app.post('/api/vms/:id/install-apk', (req, res) => { + const { id } = req.params; + const { appName, packageName, sizeMb } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + const newApp = { + packageName: packageName || `com.example.${appName.toLowerCase().replace(/\s+/g, '')}`, + appName: appName || 'Custom App', + version: '1.0.0', + iconName: 'Smartphone', + isSystem: false, + sizeMb: Number(sizeMb) || 18.5, + }; + + vm.installedApps.push(newApp); + res.json({ message: `Successfully installed ${newApp.appName} on ${vm.name}`, installedApp: newApp }); +}); + +// 11. Launch App on VM Screen +app.post('/api/vms/:id/launch-app', (req, res) => { + const { id } = req.params; + const { packageName } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + vm.currentAppPackage = packageName; + res.json({ message: `Launched ${packageName} on ${vm.name}`, currentAppPackage: vm.currentAppPackage }); +}); + +// 12. Proxifly Proxy Pool Endpoint +app.get('/api/proxies/proxifly', (req, res) => { + const { type, country } = req.query; + let list = [...PROXIFLY_PROXIES]; + + if (type && typeof type === 'string') { + list = list.filter((p) => p.type.toUpperCase() === type.toUpperCase()); + } + if (country && typeof country === 'string') { + list = list.filter( + (p) => + p.country.toLowerCase().includes(country.toLowerCase()) || + p.countryCode.toLowerCase() === country.toLowerCase() + ); + } + + res.json({ + source: 'Proxifly Developer Hub (https://proxifly.dev/tools/proxy-list)', + total: list.length, + proxies: list, + }); +}); + +// 13. Test Proxy Endpoint +app.post('/api/proxies/test', (req, res) => { + const { host, port, type } = req.body; + if (!host || !port) { + return res.status(400).json({ error: 'Host and port required' }); + } + + const simulatedPing = Math.floor(25 + Math.random() * 60); + res.json({ + status: 'ONLINE', + host, + port: Number(port), + type: type || 'SOCKS5', + latencyMs: simulatedPing, + anonymity: 'Elite', + ipExit: host, + message: `Proxy ${host}:${port} (${type || 'SOCKS5'}) connected successfully with ${simulatedPing}ms latency.`, + }); +}); + +// 14. Assign or Update VM Proxy +app.post('/api/vms/:id/proxy', (req, res) => { + const { id } = req.params; + const { type, host, port, username, password, country, countryCode, anonymity, latencyMs } = req.body; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + if (!host || !port) { + return res.status(400).json({ error: 'Proxy host and port are required' }); + } + + vm.proxy = { + id: `px-${Date.now()}`, + enabled: true, + type: type || 'SOCKS5', + host, + port: Number(port), + username, + password, + country: country || 'United States', + countryCode: countryCode || 'US', + anonymity: anonymity || 'Elite', + latencyMs: latencyMs || 42, + externalIp: host, + lastChecked: new Date().toISOString(), + }; + + res.json({ + message: `Proxy ${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port} assigned to ${vm.name}`, + vm, + }); +}); + +// 15. Delete / Remove VM Proxy +app.delete('/api/vms/:id/proxy', (req, res) => { + const { id } = req.params; + + const vm = virtualMachines.find((v) => v.id === id); + if (!vm) return res.status(404).json({ error: 'VM not found' }); + + vm.proxy = undefined; + res.json({ message: `Proxy removed from ${vm.name}`, vm }); +}); + +// 16. Auto-Assign Unique Proxies to All VMs +app.post('/api/vms/assign-proxies-auto', (req, res) => { + if (virtualMachines.length === 0) { + return res.status(400).json({ error: 'No active VMs found to assign proxies' }); + } + + const assignments: { vmName: string; proxy: string; country: string }[] = []; + + virtualMachines.forEach((vm, index) => { + const proxyData = PROXIFLY_PROXIES[index % PROXIFLY_PROXIES.length]; + vm.proxy = { + ...proxyData, + enabled: true, + lastChecked: new Date().toISOString(), + }; + assignments.push({ + vmName: vm.name, + proxy: `${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port}`, + country: `${vm.proxy.country} (${vm.proxy.countryCode})`, + }); + }); + + res.json({ + message: `Successfully assigned unique Proxifly proxies to all ${virtualMachines.length} active VMs.`, + assignments, + virtualMachines, + }); +}); + +// ========================================== +// API KEYS MANAGEMENT +// ========================================== +let apiKeys: { id: string; key: string; name: string; createdAt: string; lastUsedAt?: string; requestCount: number; permissions: 'full_control' | 'read_only' }[] = [ + { + id: 'key-master-01', + key: 'sk_proxifly_live_mcp_master_key_8842', + name: 'Claude Desktop & AI Agent Master Key', + createdAt: new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(), + lastUsedAt: new Date().toISOString(), + requestCount: 142, + permissions: 'full_control', + }, +]; + +app.get('/api/keys', (req, res) => { + res.json({ keys: apiKeys }); +}); + +app.post('/api/keys', (req, res) => { + const { name, permissions } = req.body; + const newKey = { + id: `key-${Date.now()}`, + key: `sk_proxifly_live_${Math.random().toString(36).substring(2, 12)}_${Math.random().toString(36).substring(2, 10)}`, + name: name || 'New AI Agent Key', + createdAt: new Date().toISOString(), + requestCount: 0, + permissions: permissions || 'full_control', + }; + apiKeys.unshift(newKey); + res.json({ message: 'API key created successfully', apiKey: newKey }); +}); + +app.delete('/api/keys/:id', (req, res) => { + const { id } = req.params; + apiKeys = apiKeys.filter((k) => k.id !== id); + res.json({ message: 'API key revoked' }); +}); + +// ========================================== +// OPENAPI 3.0 SPECIFICATION +// ========================================== +app.get('/api/openapi.json', (req, res) => { + res.json({ + openapi: '3.0.3', + info: { + title: 'Proxifly Android VM Cloud & MCP Control API', + version: '1.0.0', + description: 'Programmatic REST API & Model Context Protocol (MCP) Server to provision, manage, automate, and route Android Virtual Machines.', + }, + servers: [{ url: '/api', description: 'Local Hypervisor Server' }], + paths: { + '/vms': { + get: { summary: 'List all active Android Virtual Machines', responses: { '200': { description: 'Success' } } }, + post: { summary: 'Provision new Android VM instance', responses: { '200': { description: 'Success' } } }, + }, + '/vms/{id}/adb': { + post: { summary: 'Execute ADB shell command on VM', responses: { '200': { description: 'Success' } } }, + }, + '/vms/{id}/proxy': { + post: { summary: 'Assign Proxifly residential/datacenter proxy to VM', responses: { '200': { description: 'Success' } } }, + delete: { summary: 'Remove proxy from VM', responses: { '200': { description: 'Success' } } }, + }, + '/mcp': { + post: { summary: 'MCP JSON-RPC 2.0 Server Protocol Endpoint for AI Agents', responses: { '200': { description: 'Success' } } }, + }, + }, + }); +}); + +// ========================================== +// MODEL CONTEXT PROTOCOL (MCP) SERVER ENGINE +// ========================================== +const MCP_TOOLS_DEFINITIONS = [ + { + name: 'list_vms', + description: 'List all active Android Virtual Machines in the hypervisor, including state, IP, ADB ports, hardware profile, and assigned proxy.', + inputSchema: { + type: 'object', + properties: {}, + }, + }, + { + name: 'create_vm', + description: 'Provision and launch a new Android Virtual Machine instance.', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: 'Name label for the VM instance' }, + androidVersion: { type: 'string', description: 'Android OS Version (e.g. "14 (UpsideDownCake)", "13 (Tiramisu)", "11 (RedVelvetCake)")' }, + profileId: { type: 'string', description: 'Hardware profile ID ("pixel-8-pro", "galaxy-s24-ultra", "oneplus-12", "aosp-tablet-10")' }, + ramGb: { type: 'number', description: 'RAM size in GB (e.g. 4, 8, 12)' }, + vcpu: { type: 'number', description: 'vCPU cores count (e.g. 2, 4, 8)' }, + }, + required: ['name'], + }, + }, + { + name: 'power_vm', + description: 'Change the power state of an Android VM (start, stop, reboot, recovery).', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'The ID of target Android VM (e.g. "vm-cloud-001")' }, + action: { type: 'string', enum: ['start', 'stop', 'reboot', 'recovery'], description: 'Power action to execute' }, + }, + required: ['vmId', 'action'], + }, + }, + { + name: 'execute_adb_command', + description: 'Execute an arbitrary ADB shell command or input event on a target VM (e.g., "adb shell input tap 300 500", "adb shell input text hello", "adb shell dumpsys battery").', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + command: { type: 'string', description: 'ADB command to execute (e.g. "input tap 500 800" or "getprop")' }, + }, + required: ['vmId', 'command'], + }, + }, + { + name: 'install_apk', + description: 'Sideload and install an APK application package on a specific Android VM.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + appName: { type: 'string', description: 'Human readable app name' }, + packageName: { type: 'string', description: 'Android package name (e.g. "com.facebook.katana")' }, + }, + required: ['vmId', 'packageName'], + }, + }, + { + name: 'launch_app', + description: 'Launch an installed Android application package on target VM.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + packageName: { type: 'string', description: 'Package name to open (e.g. "com.whatsapp")' }, + }, + required: ['vmId', 'packageName'], + }, + }, + { + name: 'assign_proxy', + description: 'Assign a residential or datacenter HTTP/SOCKS5 proxy from Proxifly to route a target VM network traffic.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + type: { type: 'string', enum: ['HTTP', 'HTTPS', 'SOCKS4', 'SOCKS5'], description: 'Proxy Protocol' }, + host: { type: 'string', description: 'Proxy IP or hostname' }, + port: { type: 'number', description: 'Proxy port number' }, + country: { type: 'string', description: 'Country location' }, + }, + required: ['vmId', 'host', 'port'], + }, + }, + { + name: 'run_automation_script', + description: 'Execute a multi-step macro automation workflow script (tap, swipe, delay, text input) on a VM.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + steps: { + type: 'array', + items: { + type: 'object', + properties: { + type: { type: 'string', enum: ['tap', 'swipe', 'delay', 'typeText', 'launchApp', 'keyEvent'] }, + x: { type: 'number' }, + y: { type: 'number' }, + text: { type: 'string' }, + durationMs: { type: 'number' }, + packageName: { type: 'string' }, + }, + required: ['type'], + }, + }, + }, + required: ['vmId', 'steps'], + }, + }, + { + name: 'get_vm_screenshot', + description: 'Capture current screenshot state and UI logcat output from target VM.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target VM ID' }, + }, + required: ['vmId'], + }, + }, + { + name: 'instagram_orchestration', + description: 'Perform automated social orchestration actions on Instagram (comment on posts, send direct messages, like content, or verify Google account auth) on target VM.', + inputSchema: { + type: 'object', + properties: { + vmId: { type: 'string', description: 'Target Android VM ID' }, + action: { type: 'string', enum: ['comment', 'send_dm', 'like_post', 'verify_google_account'], description: 'Instagram orchestration action' }, + postId: { type: 'string', description: 'Post ID for comments or likes' }, + commentText: { type: 'string', description: 'Comment text to publish' }, + targetUsername: { type: 'string', description: 'Target user handle for direct messages' }, + messageText: { type: 'string', description: 'DM text content' }, + googleEmail: { type: 'string', description: 'Google account email for 2FA verification' }, + }, + required: ['vmId', 'action'], + }, + }, +]; + +// Helper to process MCP Tool Calls +async function handleMcpToolCall(toolName: string, args: any) { + switch (toolName) { + case 'list_vms': + return { + total: virtualMachines.length, + vms: virtualMachines.map((v) => ({ + id: v.id, + name: v.name, + status: v.status, + androidVersion: v.androidVersion, + ipAddress: v.ipAddress, + adbPort: v.adbPort, + currentAppPackage: v.currentAppPackage, + proxy: v.proxy ? `${v.proxy.type}://${v.proxy.host}:${v.proxy.port}` : 'None (Direct)', + batteryLevel: v.batteryLevel, + })), + }; + + case 'create_vm': { + const { name, androidVersion, profileId, ramGb, vcpu } = args; + const profile = (HardwareProfiles as any)[profileId] || HardwareProfiles.PIXEL_8_PRO; + const newVm: AndroidVM = { + id: `vm-cloud-${Math.floor(100 + Math.random() * 900)}`, + name: name || 'New AI Managed VM', + androidVersion: (androidVersion as AndroidVersion) || '14 (UpsideDownCake)', + arch: 'x86_64', + profile, + ramGb: Number(ramGb) || 8, + vcpu: Number(vcpu) || 4, + storageGb: 64, + bootloader: { + isUnlocked: true, + rootMethod: 'magisk', + customRecovery: true, + selinuxMode: 'permissive', + kernelCmdline: 'console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=permissive', + gpuAcceleration: 'swiftshader', + }, + status: 'running', + ipAddress: `192.168.122.${Math.floor(10 + Math.random() * 200)}`, + adbPort: 5555, + vncPort: 5901, + batteryLevel: 100, + isCharging: true, + orientation: 'portrait', + location: { latitude: 37.7749, longitude: -122.4194, addressName: 'San Francisco, CA' }, + metrics: { cpuUsagePct: 12, ramUsageMb: 1840, totalRamMb: 8192, fps: 60, networkRxKbps: 45, networkTxKbps: 18, uptimeSeconds: 10 }, + installedApps: [...DEFAULT_ANDROID_APPS], + currentAppPackage: 'com.android.launcher3', + createdAt: new Date().toISOString(), + snapshotCount: 0, + }; + virtualMachines.push(newVm); + syncActiveVmCount(); + return { message: `VM ${newVm.name} created successfully`, vm: newVm }; + } + + case 'power_vm': { + const { vmId, action } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + if (action === 'stop') vm.status = 'stopped'; + else if (action === 'start') vm.status = 'running'; + else if (action === 'reboot') vm.status = 'booting'; + else if (action === 'recovery') vm.status = 'recovery'; + + return { message: `VM ${vm.name} power action executed: ${action}`, status: vm.status }; + } + + case 'execute_adb_command': { + const { vmId, command } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + const cmd = (command || '').trim(); + let output = `Executed ADB command: ${cmd}\n`; + if (cmd.includes('tap')) { + output += `[Input Event] Injected touch tap event on display layer.`; + } else if (cmd.includes('text')) { + output += `[Input Event] Injected keyboard text buffer into active focus field.`; + } else { + output += `Exit Code: 0 (OKAY)`; + } + return { vmId, command: cmd, output, exitCode: 0 }; + } + + case 'install_apk': { + const { vmId, appName, packageName } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + const cleanPkg = packageName || 'com.example.app'; + const cleanName = appName || cleanPkg.split('.').pop() || 'App'; + + if (!vm.installedApps.find((a) => a.packageName === cleanPkg)) { + vm.installedApps.push({ + packageName: cleanPkg, + appName: cleanName, + version: '1.0.0', + iconName: 'Smartphone', + isSystem: false, + sizeMb: 42, + }); + } + vm.currentAppPackage = cleanPkg; + return { message: `Successfully installed ${cleanName} (${cleanPkg}) on ${vm.name}`, installedAppsCount: vm.installedApps.length }; + } + + case 'launch_app': { + const { vmId, packageName } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + vm.currentAppPackage = packageName; + return { message: `Launched ${packageName} on ${vm.name}`, currentAppPackage: vm.currentAppPackage }; + } + + case 'assign_proxy': { + const { vmId, type, host, port, country } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + vm.proxy = { + id: `px-mcp-${Date.now()}`, + enabled: true, + type: (type as ProxyType) || 'SOCKS5', + host, + port: Number(port), + country: country || 'United States', + countryCode: 'US', + anonymity: 'Elite', + latencyMs: 38, + externalIp: host, + lastChecked: new Date().toISOString(), + }; + return { message: `Assigned proxy ${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port} to ${vm.name}`, vmProxy: vm.proxy }; + } + + case 'run_automation_script': { + const { vmId, steps } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + const logs: string[] = []; + for (let i = 0; i < (steps || []).length; i++) { + const step = steps[i]; + if (step.type === 'tap') logs.push(`Step ${i + 1}: Tap at (${step.x}, ${step.y})`); + else if (step.type === 'typeText') logs.push(`Step ${i + 1}: Typed text "${step.text}"`); + else if (step.type === 'launchApp') { + vm.currentAppPackage = step.packageName || vm.currentAppPackage; + logs.push(`Step ${i + 1}: Launched ${step.packageName}`); + } else logs.push(`Step ${i + 1}: Executed ${step.type}`); + } + + return { message: `Executed automation sequence (${(steps || []).length} steps) on ${vm.name}`, logs }; + } + + case 'get_vm_screenshot': { + const { vmId } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + return { + vmId: vm.id, + vmName: vm.name, + currentAppPackage: vm.currentAppPackage, + status: vm.status, + timestamp: new Date().toISOString(), + screenshotCaptured: true, + resolution: vm.profile.screenResolution, + }; + } + + case 'instagram_orchestration': { + const { vmId, action, postId, commentText, targetUsername, messageText, googleEmail } = args; + const vm = virtualMachines.find((v) => v.id === vmId); + if (!vm) throw new Error(`VM ${vmId} not found`); + + if (action === 'comment') { + return { + status: 'success', + vmId: vm.id, + action: 'comment', + postId: postId || 'ig-1', + commentText, + publishedAt: new Date().toISOString(), + proxyRoute: vm.proxy ? `${vm.proxy.type}://${vm.proxy.host}` : 'Direct', + message: `Successfully posted comment on Instagram post ${postId || 'ig-1'}: "${commentText}"`, + }; + } else if (action === 'send_dm') { + return { + status: 'success', + vmId: vm.id, + action: 'send_dm', + targetUsername: targetUsername || '@android_dev_official', + messageText, + deliveredAt: new Date().toISOString(), + message: `Direct message sent to ${targetUsername || '@android_dev_official'}: "${messageText}"`, + }; + } else if (action === 'like_post') { + return { + status: 'success', + vmId: vm.id, + action: 'like_post', + postId: postId || 'ig-1', + message: `Liked Instagram post ${postId || 'ig-1'}`, + }; + } else if (action === 'verify_google_account') { + return { + status: 'success', + vmId: vm.id, + action: 'verify_google_account', + googleEmail: googleEmail || 'alex.dev.cloud@gmail.com', + verificationStatus: 'verified_2fa_code_passed', + codeReceived: '482910', + message: `Google Account ${googleEmail || 'alex.dev.cloud@gmail.com'} successfully authenticated with 2FA email verification code.`, + }; + } + return { status: 'executed', action }; + } + + default: + throw new Error(`Unknown tool: ${toolName}`); + } +} + +// MCP JSON-RPC 2.0 Handler +app.post('/api/mcp', async (req, res) => { + const { jsonrpc, id, method, params } = req.body || {}; + + try { + if (method === 'initialize') { + return res.json({ + jsonrpc: '2.0', + id: id || 1, + result: { + protocolVersion: '2024-11-05', + capabilities: { + tools: { + listChanged: true, + }, + }, + serverInfo: { + name: 'proxifly-android-mcp-server', + version: '1.0.0', + }, + }, + }); + } + + if (method === 'tools/list') { + return res.json({ + jsonrpc: '2.0', + id: id || 1, + result: { + tools: MCP_TOOLS_DEFINITIONS, + }, + }); + } + + if (method === 'tools/call') { + const { name, arguments: toolArgs } = params || {}; + const resultData = await handleMcpToolCall(name, toolArgs || {}); + + return res.json({ + jsonrpc: '2.0', + id: id || 1, + result: { + content: [ + { + type: 'text', + text: JSON.stringify(resultData, null, 2), + }, + ], + }, + }); + } + + return res.status(400).json({ + jsonrpc: '2.0', + id: id || 1, + error: { + code: -32601, + message: `Method not found: ${method}`, + }, + }); + } catch (err: any) { + return res.json({ + jsonrpc: '2.0', + id: id || 1, + error: { + code: -32603, + message: err?.message || 'Internal MCP tool execution error', + }, + }); + } +}); + +// SSE Stream for MCP Client Agents +app.get('/api/mcp/sse', (req, res) => { + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + res.write(`event: endpoint\ndata: /api/mcp\n\n`); + + const keepAliveInterval = setInterval(() => { + res.write(`: keepalive\n\n`); + }, 15000); + + req.on('close', () => { + clearInterval(keepAliveInterval); + }); +}); + +// Start Express Server with Vite Middleware + +async function startServer() { + if (process.env.NODE_ENV !== 'production') { + const vite = await createViteServer({ + server: { middlewareMode: true }, + appType: 'spa', + }); + app.use(vite.middlewares); + } else { + app.use(express.static(path.resolve(__dirname, 'dist'))); + app.get('*', (req, res) => { + res.sendFile(path.resolve(__dirname, 'dist', 'index.html')); + }); + } + + app.listen(PORT, '0.0.0.0', () => { + console.log(`Android Cloud Hypervisor Server running on http://0.0.0.0:${PORT}`); + }); +} + +startServer(); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..48ea219 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,364 @@ +import React, { useState, useEffect } from 'react'; +import { + AndroidVM, + UserSubscription, + ProxyConfig, +} from './types'; +import { Navbar, MainNavTab } from './components/Navbar'; +import { HypervisorConsole } from './components/HypervisorConsole'; +import { AndroidScreenViewer } from './components/AndroidScreenViewer'; +import { ProxyManagerStudio } from './components/ProxyManagerStudio'; +import { McpApiStudio } from './components/McpApiStudio'; +import { ProgrammaticAutomationStudio } from './components/ProgrammaticAutomationStudio'; +import { AdbConsole } from './components/AdbConsole'; +import { BootloaderStudio } from './components/BootloaderStudio'; +import { PricingModal } from './components/PricingModal'; +import { DeployVmWizardModal } from './components/DeployVmWizardModal'; + +export default function App() { + const [activeTab, setActiveTab] = useState('console'); + const [vms, setVms] = useState([]); + const [selectedVmId, setSelectedVmId] = useState(''); + const [subscription, setSubscription] = useState({ + plan: 'free', + maxVms: 1, + pricePerMonth: 0, + activeVmCount: 1, + renewsAt: new Date().toISOString(), + }); + const [kvmOnline, setKvmOnline] = useState(true); + const [isPricingOpen, setIsPricingOpen] = useState(false); + const [isDeployWizardOpen, setIsDeployWizardOpen] = useState(false); + + // Fetch initial data from server + const fetchAllData = async () => { + try { + const baseUrl = window.location.origin; + const [subRes, vmsRes, healthRes] = await Promise.all([ + fetch(`${baseUrl}/api/user/subscription`).catch(() => null), + fetch(`${baseUrl}/api/vms`).catch(() => null), + fetch(`${baseUrl}/api/health`).catch(() => null), + ]); + + if (subRes && subRes.ok) { + const subData = await subRes.json(); + setSubscription(subData); + } + + if (vmsRes && vmsRes.ok) { + const vmsData = await vmsRes.json(); + setVms(vmsData); + if (vmsData.length > 0 && !selectedVmId) { + setSelectedVmId(vmsData[0].id); + } + } + + if (healthRes && healthRes.ok) { + setKvmOnline(true); + } else { + setKvmOnline(false); + } + } catch { + setKvmOnline(false); + } + }; + + useEffect(() => { + fetchAllData(); + const interval = setInterval(fetchAllData, 3000); + return () => clearInterval(interval); + }, []); + + const activeVm = vms.find((v) => v.id === selectedVmId) || vms[0]; + + // Actions + const handleDeployVm = async (vmData: any) => { + const baseUrl = window.location.origin; + const res = await fetch(`${baseUrl}/api/vms/create`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(vmData), + }); + + if (!res.ok) { + const err = await res.json(); + throw new Error(err.message || 'Failed to deploy VM'); + } + + const createdVm = await res.json(); + setSelectedVmId(createdVm.id); + await fetchAllData(); + }; + + const handlePowerAction = async (vmId: string, action: string) => { + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${vmId}/power`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action }), + }).catch(() => null); + await fetchAllData(); + }; + + const handleDeleteVm = async (vmId: string) => { + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${vmId}`, { method: 'DELETE' }).catch(() => null); + await fetchAllData(); + }; + + const handleExecuteAdb = async (command: string): Promise => { + if (!activeVm) return 'No active VM selected'; + const baseUrl = window.location.origin; + try { + const res = await fetch(`${baseUrl}/api/vms/${activeVm.id}/adb`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ command }), + }); + const data = await res.json(); + return data.output || 'Command executed.'; + } catch { + return 'Error executing ADB command on VM backend.'; + } + }; + + const handleExecuteFastboot = async (command: string): Promise => { + if (!activeVm) return 'No active VM selected'; + const baseUrl = window.location.origin; + try { + const res = await fetch(`${baseUrl}/api/vms/${activeVm.id}/fastboot`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ command }), + }); + const data = await res.json(); + return data.output || 'OKAY'; + } catch { + return 'Error executing Fastboot command on VM backend.'; + } + }; + + const handleLaunchApp = async (packageName: string) => { + if (!activeVm) return; + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${activeVm.id}/launch-app`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ packageName }), + }).catch(() => null); + await fetchAllData(); + }; + + const handleInstallApk = async (appName: string, packageName: string) => { + if (!activeVm) return; + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${activeVm.id}/install-apk`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ appName, packageName }), + }).catch(() => null); + await fetchAllData(); + }; + + const handleUpdateBattery = async (level: number, isCharging: boolean) => { + if (!activeVm) return; + activeVm.batteryLevel = level; + activeVm.isCharging = isCharging; + setVms([...vms]); + }; + + const handleUpdateGps = async (latitude: number, longitude: number, addressName: string) => { + if (!activeVm) return; + activeVm.location = { latitude, longitude, addressName }; + setVms([...vms]); + }; + + const handleAssignProxyToVm = async (vmId: string, proxy: ProxyConfig) => { + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${vmId}/proxy`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(proxy), + }).catch(() => null); + await fetchAllData(); + }; + + const handleRemoveProxyFromVm = async (vmId: string) => { + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/${vmId}/proxy`, { + method: 'DELETE', + }).catch(() => null); + await fetchAllData(); + }; + + const handleAutoAssignProxiesToAllVms = async () => { + const baseUrl = window.location.origin; + await fetch(`${baseUrl}/api/vms/assign-proxies-auto`, { + method: 'POST', + }).catch(() => null); + await fetchAllData(); + }; + + const handleUpgradePlan = async (targetPlan: 'free' | 'pro', paymentMethod?: string) => { + const baseUrl = window.location.origin; + const res = await fetch(`${baseUrl}/api/user/subscription/upgrade`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ targetPlan, paymentMethod }), + }).catch(() => null); + if (res && res.ok) { + await fetchAllData(); + } + }; + + return ( +
+
+ {/* Navigation Bar */} + setIsDeployWizardOpen(true)} + onOpenPricingModal={() => setIsPricingOpen(true)} + kvmOnline={kvmOnline} + activeVmName={activeVm?.name} + /> + + {/* Main Workspace Workspace */} +
+ {activeTab === 'console' && ( + { + setSelectedVmId(id); + setActiveTab('display'); + }} + onOpenDeployWizard={() => setIsDeployWizardOpen(true)} + onOpenPricingModal={() => setIsPricingOpen(true)} + onPowerAction={handlePowerAction} + onDeleteVm={handleDeleteVm} + onOpenProxyManager={(vmId) => { + if (vmId) setSelectedVmId(vmId); + setActiveTab('proxies'); + }} + selectedVmId={selectedVmId} + /> + )} + + {activeTab === 'display' && activeVm && ( + handlePowerAction(activeVm.id, action)} + onUpdateBattery={handleUpdateBattery} + onUpdateGps={handleUpdateGps} + onOpenProxyManager={(vmId) => { + if (vmId) setSelectedVmId(vmId); + setActiveTab('proxies'); + }} + /> + )} + + {activeTab === 'proxies' && ( + + )} + + {activeTab === 'mcp' && ( + + )} + + {activeTab === 'automation' && activeVm && ( + { + const out = await handleExecuteAdb(cmd); + return { output: out, exitCode: 0 }; + }} + onLaunchApp={handleLaunchApp} + onInstallApk={handleInstallApk} + inspectorCoords={null} + /> + )} + + {activeTab === 'adb' && activeVm && ( + + )} + + {activeTab === 'bootloader' && activeVm && ( + { + activeVm.bootloader = { ...activeVm.bootloader, ...cfg }; + setVms([...vms]); + }} + /> + )} + + {activeTab === 'pricing' && ( +
+
+

Android Cloud Hypervisor Rental

+

+ Rent virtualized Android devices on demand. Choose 1 Free instance or unlock 5 instances for $5/mo. +

+ +
+
+ )} +
+
+ + {/* Modals */} + setIsPricingOpen(false)} + subscription={subscription} + onUpgradePlan={handleUpgradePlan} + /> + + setIsDeployWizardOpen(false)} + subscription={subscription} + onDeployVm={handleDeployVm} + onOpenPricing={() => { + setIsDeployWizardOpen(false); + setIsPricingOpen(true); + }} + /> + + {/* Footer */} +
+
+ Android Cloud Hypervisor • Built-in Bootloader & WebRTC Screen Streaming + 1 Free VM • 5 VMs for $5/mo +
+
+
+ ); +} diff --git a/src/components/AdbConsole.tsx b/src/components/AdbConsole.tsx new file mode 100644 index 0000000..db791e0 --- /dev/null +++ b/src/components/AdbConsole.tsx @@ -0,0 +1,224 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { AndroidVM } from '../types'; +import { + Terminal, + Send, + Copy, + Check, + Trash2, + Play, + ShieldAlert, + Cpu, + Layers, + Search, +} from 'lucide-react'; + +interface AdbConsoleProps { + vm: AndroidVM; + vms: AndroidVM[]; + onSelectVm: (vmId: string) => void; + onExecuteAdb: (command: string) => Promise; +} + +export const AdbConsole: React.FC = ({ + vm, + vms, + onSelectVm, + onExecuteAdb, +}) => { + const [commandInput, setCommandInput] = useState(''); + const [terminalHistory, setTerminalHistory] = useState< + { command: string; output: string; timestamp: string }[] + >([ + { + command: 'adb connect 192.168.122.105:5555', + output: `* daemon not running; starting now at tcp:5037\n* daemon started successfully\nconnected to ${vm.ipAddress}:${vm.adbPort}`, + timestamp: new Date().toLocaleTimeString(), + }, + ]); + const [isExecuting, setIsExecuting] = useState(false); + const [copiedIndex, setCopiedIndex] = useState(null); + const terminalEndRef = useRef(null); + + const scrollToBottom = () => { + terminalEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; + + useEffect(() => { + scrollToBottom(); + }, [terminalHistory]); + + const handleRunCommand = async (cmdToRun?: string) => { + const cmd = (cmdToRun || commandInput).trim(); + if (!cmd) return; + + setIsExecuting(true); + const result = await onExecuteAdb(cmd); + + setTerminalHistory((prev) => [ + ...prev, + { + command: cmd, + output: result, + timestamp: new Date().toLocaleTimeString(), + }, + ]); + + setCommandInput(''); + setIsExecuting(false); + }; + + const presetCommands = [ + { label: 'System Build Props', cmd: 'getprop' }, + { label: 'List Packages', cmd: 'pm list packages' }, + { label: 'Check Root Privilege', cmd: 'su' }, + { label: 'CPU Info', cmd: 'cat /proc/cpuinfo' }, + { label: 'Battery Dumpsys', cmd: 'dumpsys battery' }, + { label: 'Live Logcat', cmd: 'logcat -d' }, + ]; + + const handleCopy = (text: string, index: number) => { + navigator.clipboard.writeText(text); + setCopiedIndex(index); + setTimeout(() => setCopiedIndex(null), 2000); + }; + + return ( +
+ {/* Target VM Selector & Network Status Bar */} +
+
+ +
+ Target Instance: + +
+
+ +
+ + ADB TCP: {vm.ipAddress}:{vm.adbPort} + + + SELinux: {vm.bootloader.selinuxMode} + +
+
+ + {/* Preset Quick Commands */} +
+ + Quick ADB Shell Presets: + +
+ {presetCommands.map((preset) => ( + + ))} +
+
+ + {/* Interactive ADB Shell Terminal View */} +
+ {/* Terminal Header */} +
+
+
+
+
+ + adb shell shell@{vm.profile.id}:/$ + +
+ + +
+ + {/* Console Log Area */} +
+ {terminalHistory.map((item, idx) => ( +
+
+
+ $ + {item.command} +
+
+ {item.timestamp} + +
+
+ +
+                {item.output}
+              
+
+ ))} +
+
+ + {/* Terminal Command Input */} +
+
{ + e.preventDefault(); + handleRunCommand(); + }} + className="flex items-center space-x-2" + > + $ + setCommandInput(e.target.value)} + placeholder="Type adb shell command (e.g. getprop, logcat, su)..." + disabled={isExecuting} + className="flex-1 bg-slate-950 border border-slate-800 rounded-xl px-3.5 py-2 text-xs font-mono text-slate-100 placeholder-slate-600 focus:outline-none focus:border-emerald-500" + /> + +
+
+
+
+ ); +}; diff --git a/src/components/AndroidScreenViewer.tsx b/src/components/AndroidScreenViewer.tsx new file mode 100644 index 0000000..b1bdd9d --- /dev/null +++ b/src/components/AndroidScreenViewer.tsx @@ -0,0 +1,1765 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { AndroidVM, AndroidAppPackage } from '../types'; +import { FacebookAppView } from './FacebookAppView'; +import { InstagramAppView } from './InstagramAppView'; +import { GmailAppView } from './GmailAppView'; +import { ProgrammaticAutomationStudio } from './ProgrammaticAutomationStudio'; +import { + Smartphone, + RotateCw, + Share2, + Power, + Volume2, + VolumeX, + Volume1, + Camera, + MapPin, + Battery, + BatteryCharging, + Wifi, + Upload, + ArrowLeft, + Home, + Square, + ShieldAlert, + Terminal, + Settings, + LayoutGrid, + Globe, + ShoppingBag, + Check, + X, + Play, + RotateCcw, + Sliders, + Search, + Sun, + Moon, + Folder, + Bell, + Download, + RefreshCw, + Maximize2, + ChevronDown, + ChevronUp, + Zap, + Bluetooth, + Sparkles, + Layers, + Image, + Cpu, + HardDrive, + MoreVertical, + ExternalLink, + Lock, + Unlock, + FileText, + Mail, +} from 'lucide-react'; + +interface AndroidScreenViewerProps { + vm: AndroidVM; + vms: AndroidVM[]; + onSelectVm: (vmId: string) => void; + onLaunchApp: (packageName: string) => void; + onInstallApk: (appName: string, packageName: string) => void; + onPowerAction: (action: string) => void; + onUpdateBattery: (level: number, isCharging: boolean) => void; + onUpdateGps: (lat: number, lng: number, address: string) => void; + onOpenProxyManager?: (vmId: string) => void; +} + +type WallpaperId = 'oxygen' | 'pixel' | 'galaxy' | 'aosp' | 'cyber'; + +export const AndroidScreenViewer: React.FC = ({ + vm, + vms, + onSelectVm, + onLaunchApp, + onInstallApk, + onPowerAction, + onUpdateBattery, + onUpdateGps, + onOpenProxyManager, +}) => { + const [orientation, setOrientation] = useState<'portrait' | 'landscape'>('portrait'); + const [displayMode, setDisplayMode] = useState<'os' | 'vnc'>('os'); + const [isGpsModalOpen, setIsGpsModalOpen] = useState(false); + const [isApkModalOpen, setIsApkModalOpen] = useState(false); + const [screenshotNotification, setScreenshotNotification] = useState(null); + + // OS Interactivity States + const [isQuickSettingsOpen, setIsQuickSettingsOpen] = useState(false); + const [isAppDrawerOpen, setIsAppDrawerOpen] = useState(false); + const [isRecentsOpen, setIsRecentsOpen] = useState(false); + const [isPowerMenuOpen, setIsPowerMenuOpen] = useState(false); + const [selectedWallpaper, setSelectedWallpaper] = useState('oxygen'); + const [screenBrightness, setScreenBrightness] = useState(90); + const [volumeLevel, setVolumeLevel] = useState(75); + const [showVolumeHud, setShowVolumeHud] = useState(false); + + // Quick Toggles State + const [wifiEnabled, setWifiEnabled] = useState(true); + const [bluetoothEnabled, setBluetoothEnabled] = useState(true); + const [flashlightEnabled, setFlashlightEnabled] = useState(false); + const [darkTheme, setDarkTheme] = useState(true); + const [autoRotate, setAutoRotate] = useState(true); + const [airplaneMode, setAirplaneMode] = useState(false); + + // Email Push Notification Toast + const [incomingEmailToast, setIncomingEmailToast] = useState<{ + sender: string; + subject: string; + code?: string; + } | null>(null); + + useEffect(() => { + const handleEmailReceived = (e: any) => { + if (e.detail) { + setIncomingEmailToast({ + sender: e.detail.senderName || 'Gmail', + subject: e.detail.subject, + code: e.detail.verificationCode, + }); + setTimeout(() => setIncomingEmailToast(null), 6000); + } + }; + window.addEventListener('proxifly-email-received', handleEmailReceived); + return () => window.removeEventListener('proxifly-email-received', handleEmailReceived); + }, []); + + // Apps Internal State + // 1. Chrome + const [browserUrl, setBrowserUrl] = useState('https://www.google.com'); + const [activeBrowserTab, setActiveBrowserTab] = useState('Google'); + // 2. Terminal + const [terminalLogs, setTerminalLogs] = useState([ + 'Android AOSP Linux Kernel 6.1.75-android14-virtio', + 'Root shell initialized (uid=0 root)', + 'Type "help" or select quick commands below.', + ]); + const [terminalInput, setTerminalInput] = useState(''); + // 3. Settings tab + const [settingsTab, setSettingsTab] = useState<'system' | 'display' | 'battery' | 'storage' | 'developer'>('system'); + // 4. Camera + const [cameraPhotoTaken, setCameraPhotoTaken] = useState(null); + const [cameraFilter, setCameraFilter] = useState<'normal' | 'cyber' | 'noir' | 'vintage'>('normal'); + + // GPS Modal inputs + const [inputLat, setInputLat] = useState(vm.location.latitude.toString()); + const [inputLng, setInputLng] = useState(vm.location.longitude.toString()); + const [inputAddress, setInputAddress] = useState(vm.location.addressName); + + // APK Modal inputs & Upload state + const [newAppName, setNewAppName] = useState(''); + const [newPackageName, setNewPackageName] = useState(''); + const [apkUploading, setApkUploading] = useState(false); + const [apkProgress, setApkProgress] = useState(0); + + // Touch Inspector Mode + const [isInspectorMode, setIsInspectorMode] = useState(false); + const [inspectorCoord, setInspectorCoord] = useState<{ x: number; y: number } | null>(null); + const [isAutomationStudioOpen, setIsAutomationStudioOpen] = useState(false); + + // Touch animation ripples on phone screen + const [touchRipples, setTouchRipples] = useState<{ id: number; x: number; y: number }[]>([]); + const phoneScreenRef = useRef(null); + + const activeApp = vm.installedApps.find((a) => a.packageName === vm.currentAppPackage) || vm.installedApps[0]; + + // Volume HUD timer + const volumeTimerRef = useRef(null); + + const triggerVolumeHud = (delta: number) => { + setVolumeLevel((prev) => { + const next = Math.min(100, Math.max(0, prev + delta)); + return next; + }); + setShowVolumeHud(true); + if (volumeTimerRef.current) clearTimeout(volumeTimerRef.current); + volumeTimerRef.current = setTimeout(() => setShowVolumeHud(false), 2000); + }; + + const handleScreenClick = (e: React.MouseEvent) => { + if (!phoneScreenRef.current) return; + const rect = phoneScreenRef.current.getBoundingClientRect(); + const x = Math.round(e.clientX - rect.left); + const y = Math.round(e.clientY - rect.top); + + if (isInspectorMode) { + setInspectorCoord({ x, y }); + } + + const id = Date.now(); + setTouchRipples((prev) => [...prev.slice(-4), { id, x, y }]); + setTimeout(() => { + setTouchRipples((prev) => prev.filter((r) => r.id !== id)); + }, 600); + }; + + const handleApkFileUpload = (file: File) => { + if (!file) return; + setApkUploading(true); + setApkProgress(10); + + const fileNameNoExt = file.name.replace(/\.apk$/i, ''); + const cleanName = fileNameNoExt + .replace(/[-_]/g, ' ') + .replace(/\b\w/g, (l) => l.toUpperCase()); + const pkg = `com.${cleanName.toLowerCase().replace(/[^a-z0-9]/g, '')}.android`; + + setNewAppName(cleanName); + setNewPackageName(pkg); + + const interval = setInterval(() => { + setApkProgress((prev) => { + if (prev >= 100) { + clearInterval(interval); + setTimeout(() => { + setApkUploading(false); + onInstallApk(cleanName, pkg); + onLaunchApp(pkg); + setIsApkModalOpen(false); + setScreenshotNotification(`Successfully installed & launched ${cleanName}!`); + setTimeout(() => setScreenshotNotification(null), 3500); + }, 300); + return 100; + } + return prev + 20; + }); + }, 150); + }; + + const handleTakeScreenshot = () => { + setScreenshotNotification(`Screenshot saved: screenshot_${Date.now()}.png`); + setTimeout(() => setScreenshotNotification(null), 3500); + }; + + const handleSaveGps = (e: React.FormEvent) => { + e.preventDefault(); + onUpdateGps(parseFloat(inputLat) || 0, parseFloat(inputLng) || 0, inputAddress || 'Custom Location'); + setIsGpsModalOpen(false); + }; + + const handleInstallApkSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (!newAppName) return; + onInstallApk(newAppName, newPackageName || `com.app.${newAppName.toLowerCase().replace(/\s+/g, '')}`); + setNewAppName(''); + setNewPackageName(''); + setIsApkModalOpen(false); + }; + + const handleTerminalSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (!terminalInput.trim()) return; + const cmd = terminalInput.trim(); + let res = `adb shell ${cmd}`; + if (cmd === 'help') { + res = 'Available commands: su, getprop, uname -a, ps -A, ifconfig, free -m, clear'; + } else if (cmd === 'su') { + res = 'root@pixel8pro:/ # (Superuser permissions active via Magisk v27.0)'; + } else if (cmd === 'getprop') { + res = `[ro.build.version.release]: [14]\n[ro.product.model]: [${vm.profile.name}]\n[ro.hardware]: [qcom_virtio]\n[ro.sf.lcd_density]: [${vm.profile.densityDpi}]`; + } else if (cmd === 'uname -a') { + res = 'Linux localhost 6.1.75-android14-virtio #1 SMP PREEMPT x86_64 GNU/Linux'; + } else if (cmd === 'ifconfig') { + res = `wlan0: flags=4163 mtu 1500\n inet ${vm.ipAddress} netmask 255.255.255.0 broadcast 192.168.122.255`; + } else if (cmd === 'free -m') { + res = `Total: ${vm.ramGb * 1024}MB | Used: ${vm.metrics.ramUsageMb}MB | Free: ${ + vm.ramGb * 1024 - vm.metrics.ramUsageMb + }MB | Buffers: 420MB`; + } else if (cmd === 'clear') { + setTerminalLogs([]); + setTerminalInput(''); + return; + } + + setTerminalLogs((prev) => [...prev, `$ ${cmd}`, res]); + setTerminalInput(''); + }; + + // Wallpapers background classes + const wallpaperStyles: Record = { + oxygen: 'bg-gradient-to-br from-red-950 via-slate-950 to-slate-900', + pixel: 'bg-gradient-to-br from-cyan-950 via-slate-950 to-emerald-950', + galaxy: 'bg-gradient-to-br from-indigo-950 via-purple-950 to-slate-950', + aosp: 'bg-gradient-to-br from-slate-900 via-zinc-950 to-neutral-900', + cyber: 'bg-gradient-to-br from-fuchsia-950 via-slate-950 to-blue-950', + }; + + return ( +
+ {/* Top Header Bar for Switching VMs & Mode Toggle */} +
+
+ + +
+ + {/* View Mode Toggle: Interactive OS vs Raw Framebuffer Stream */} +
+ + +
+ + {/* Quick Phone Controls Toolbar */} +
+ + + + + + + + + + + + + +
+
+ + {/* Screenshot Toast Notification */} + {screenshotNotification && ( +
+ {screenshotNotification} + +
+ )} + + {/* Main Grid: Phone Shell Container + Side Inspector Controls */} +
+ {/* Left Interactive Phone Canvas (7 cols) */} +
+ {/* Hardware Phone Bezel Shell */} +
+ {/* Physical Volume Keys on Left Bezel */} +
+
+ + {/* Physical Power Key on Right Bezel */} +
+
+ + {/* Phone Screen Display Frame */} +
+ {/* Camera Notch / Speaker Hole */} +
+
+
+
+ + {/* Android Top Status Bar (Interactive Pull-Down Notification Shade) */} +
setIsQuickSettingsOpen(!isQuickSettingsOpen)} + className="bg-slate-950/80 backdrop-blur-md text-slate-200 px-4 pt-3 pb-1 flex items-center justify-between text-[11px] font-mono z-40 shrink-0 cursor-pointer hover:bg-slate-900 transition-colors border-b border-slate-800/50" + > + {new Date().toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })} +
+ {wifiEnabled ? ( + + ) : ( + + )} + {bluetoothEnabled && } + 5G +
+ {vm.batteryLevel}% + {vm.isCharging ? ( + + ) : ( + + )} +
+ +
+
+ + {/* Volume HUD Popup Overlay */} + {showVolumeHud && ( +
+ {volumeLevel === 0 ? ( + + ) : volumeLevel < 50 ? ( + + ) : ( + + )} +
+
+ Volume + {volumeLevel}% +
+
+
+
+
+
+ )} + + {/* Incoming Email Push Notification Banner */} + {incomingEmailToast && ( +
onLaunchApp('com.google.android.gm')} + className="absolute top-10 left-3 right-3 z-50 bg-slate-900/95 border border-rose-500/60 p-3 rounded-2xl backdrop-blur-xl text-slate-100 shadow-2xl flex items-center space-x-2.5 animate-bounce-short cursor-pointer hover:bg-slate-800 transition-all" + > +
+ +
+
+
+ {incomingEmailToast.sender} + + Tap to View + +
+

{incomingEmailToast.subject}

+ {incomingEmailToast.code && ( +

+ Code: {incomingEmailToast.code} +

+ )} +
+
+ )} + + {/* Inspector Touch Coordinates Badge */} + {isInspectorMode && ( +
+
+

+ + + Inspector: {inspectorCoord ? `X: ${inspectorCoord.x}, Y: ${inspectorCoord.y}` : 'Tap phone screen to inspect'} + +

+ {inspectorCoord && ( +

+ adb shell input tap {inspectorCoord.x} {inspectorCoord.y} +

+ )} +
+ {inspectorCoord && ( + + )} +
+ )} + + {/* Android Power Menu Overlay */} + {isPowerMenuOpen && ( +
+
+

Power Options

+
+ + + +
+ +
+
+ )} + + {/* Android Quick Settings Dropdown Panel */} + {isQuickSettingsOpen && ( +
+
+ Quick Settings + +
+ + {/* Toggles Grid */} +
+ + + + + + + + + + + +
+ + {/* Screen Brightness Slider */} +
+
+ + + Display Brightness + + {screenBrightness}% +
+ setScreenBrightness(parseInt(e.target.value))} + className="w-full accent-emerald-500" + /> +
+ + {/* Active Android System Notifications */} +
+ Notifications +
+ +
+

ADB Debugging Connected

+

Listening on port {vm.adbPort}

+
+
+
+ +
+

Magisk Root Active

+

SELinux Permissive mode active

+
+
+
+
+ )} + + {/* MAIN CONTENT AREA inside Phone Screen */} +
+ {/* Touch ripples animation */} + {touchRipples.map((r) => ( +
+ ))} + + {/* Status checks */} + {vm.status === 'stopped' ? ( +
+ +

Android Phone Off

+ +
+ ) : vm.status === 'booting' ? ( +
+
+ +
+

+ Booting OxygenOS / Android AOSP Kernel... +

+
+ ) : vm.status === 'fastboot' ? ( +
+ +

FASTBOOT MODE

+

+ Device: {vm.profile.name}
+ Bootloader: {vm.bootloader.isUnlocked ? 'UNLOCKED' : 'LOCKED'} +

+
+ ) : displayMode === 'vnc' ? ( + /* VNC RAW FRAMEBUFFER VIEW MODE */ +
+
+
+
+
+ +
+

+ VNC Framebuffer Stream +

+

+ Resolution: {vm.profile.screenResolution}
+ Port: :{vm.vncPort} | Codec: RAW H.264 +

+
+
+

+ Direct raw pixel buffer streamed over WebSocket. +

+
+ ) : isRecentsOpen ? ( + /* RECENT APPS WINDOW CAROUSEL */ +
+
+ Recent Applications + +
+ +
+ {vm.installedApps.slice(0, 4).map((app) => ( +
{ + setIsRecentsOpen(false); + onLaunchApp(app.packageName); + }} + className="p-3 bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-xl cursor-pointer transition-all flex items-center justify-between group" + > +
+
+ +
+
+

{app.appName}

+

{app.packageName}

+
+
+ +
+ ))} +
+
+ ) : isAppDrawerOpen ? ( + /* APP DRAWER GRID */ +
+
+ + +
+ +
+ {vm.installedApps.map((app) => ( + + ))} +
+ + +
+ ) : ( + /* RUNNING ACTIVE APP VIEW */ +
+ {activeApp.packageName === 'com.android.launcher3' && ( + /* OXYGENOS / PIXEL DESKTOP HOME SCREEN */ +
+ {/* At-a-Glance Widget */} +
+

+ {new Date().toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })} +

+

+ {new Date().toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })} | {vm.location.addressName.split(',')[0]} (24°C Sunny) +

+
+ + {/* Interactive Google Search Bar */} +
onLaunchApp('com.android.chrome')} + className="bg-slate-900/90 border border-slate-700/80 rounded-2xl px-3 py-2 flex items-center justify-between cursor-pointer hover:border-emerald-500 transition-colors shadow-md" + > +
+ + Search or type URL... +
+ +
+ + {/* Desktop Apps Grid */} +
+ {vm.installedApps.slice(0, 8).map((app) => ( + + ))} +
+ + {/* Swipe-Up App Drawer Handle Button */} +
+ +
+ + {/* Bottom Phone Dock */} +
+ + + + +
+
+ )} + + {/* INTERACTIVE CHROME BROWSER APP */} + {activeApp.packageName === 'com.android.chrome' && ( +
+ {/* Browser Navigation Bar */} +
+ + setBrowserUrl(e.target.value)} + className="flex-1 bg-slate-900 border border-slate-800 rounded-lg px-2 py-1 text-[10px] text-emerald-400 font-mono focus:outline-none" + /> + +
+ + {/* Presets Bookmarks */} +
+ {['Facebook', 'Google', 'Wikipedia', 'Android Dev', 'GitHub'].map((bm) => ( + + ))} +
+ + {/* Browser Window Rendering */} +
+
+ {activeBrowserTab} Web View + 200 OK +
+
+

Welcome to Android Chrome

+

+ Running on virtio network stack ({vm.ipAddress}). High performance V8 JavaScript engine active. +

+
+
User Agent: Mozilla/5.0 (Linux; Android 14; {vm.profile.name})
+
Resolution: {vm.profile.screenResolution}
+
+
+
+
+ )} + + {/* INTERACTIVE TERMINAL APP */} + {activeApp.packageName === 'jackpal.androidterm' && ( +
+
+ + + Termux / ADB Shell + + root@aosp +
+ + {/* Command Output Log */} +
+ {terminalLogs.map((log, idx) => ( +

+ {log} +

+ ))} +
+ + {/* Terminal Input Form */} +
+ $ + setTerminalInput(e.target.value)} + placeholder="e.g. su, getprop, ifconfig, free -m..." + className="flex-1 bg-slate-900 border border-slate-800 rounded-lg px-2 py-1 text-[10px] text-slate-100 focus:outline-none focus:border-emerald-500 font-mono" + /> + +
+
+ )} + + {/* INTERACTIVE SYSTEM SETTINGS APP */} + {activeApp.packageName === 'com.android.settings' && ( +
+
+ + + Android 14 Settings + + v14.0.0 +
+ + {/* Settings Tabs */} +
+ {(['system', 'display', 'battery', 'storage', 'developer'] as const).map((tab) => ( + + ))} +
+ + {/* Settings Tab Content */} +
+ {settingsTab === 'system' && ( +
+
+ Device Name +

{vm.profile.name}

+
+
+ Android Version +

{vm.androidVersion}

+
+
+ IP Address +

{vm.ipAddress}

+
+
+ SELinux Mode +

{vm.bootloader.selinuxMode}

+
+
+ )} + + {settingsTab === 'display' && ( +
+
+ Select Desktop Wallpaper +
+ {(['oxygen', 'pixel', 'galaxy', 'aosp', 'cyber'] as WallpaperId[]).map((wp) => ( + + ))} +
+
+
+ Screen Density + {vm.profile.densityDpi} DPI ({vm.profile.screenResolution}) +
+
+ )} + + {settingsTab === 'battery' && ( +
+
+
+ Battery Level + {vm.batteryLevel}% +
+
+
+
+
+
+ Charging Status + + {vm.isCharging ? 'Plugged In (AC Adapter)' : 'Discharging'} + +
+
+ )} + + {settingsTab === 'storage' && ( +
+
+
+ Internal Storage + 18.4 GB / {vm.storageGb} GB +
+
+
+
+
+
+ )} + + {settingsTab === 'developer' && ( +
+
+ USB Debugging (ADB) + ENABLED +
+
+ Wireless Debugging + ENABLED +
+
+ GPU Acceleration + {vm.bootloader.gpuAcceleration} +
+
+ )} +
+
+ )} + + {/* MAGISK ROOT MANAGER APP */} + {activeApp.packageName === 'com.topjohnwu.magisk' && ( +
+
+ +
+

Magisk v27.0 Root Manager

+

Zygisk Installed & Active

+
+
+ +
+
+ Superuser Access + GRANTED +
+
+ Active Modules +
+
• Systemless Hosts (Adblocking)
+
• LSposed Framework v1.9.2
+
• Play Integrity Fix v15.8
+
+
+
+ + +
+ )} + + {/* INTERACTIVE FACEBOOK APP */} + {(activeApp.packageName.includes('facebook') || activeApp.appName.toLowerCase().includes('facebook')) && ( + onLaunchApp('com.android.launcher3')} userIp={vm.ipAddress} /> + )} + + {/* INTERACTIVE INSTAGRAM APP */} + {(activeApp.packageName.includes('instagram') || activeApp.appName.toLowerCase().includes('instagram')) && ( + onLaunchApp('com.android.launcher3')} + onOpenGmail={() => onLaunchApp('com.google.android.gm')} + activeGoogleAccount="alex.dev.cloud@gmail.com" + userIp={vm.ipAddress} + /> + )} + + {/* INTERACTIVE GMAIL APP */} + {(activeApp.packageName.includes('gm') || activeApp.appName.toLowerCase().includes('gmail')) && ( + onLaunchApp('com.android.launcher3')} + activeGoogleAccount="alex.dev.cloud@gmail.com" + /> + )} + + {/* GOOGLE PLAY STORE APP */} + {activeApp.packageName === 'com.android.vending' && ( +
+
+ + Google Play Store +
+ +
+ Top Featured Apps + {[ + { name: 'Facebook', pkg: 'com.facebook.katana' }, + { name: 'Geekbench 6', pkg: 'com.primatelabs.geekbench6' }, + { name: 'Instagram', pkg: 'com.instagram.android' }, + { name: 'TikTok', pkg: 'com.zhiliaoapp.musically' }, + { name: 'WhatsApp', pkg: 'com.whatsapp' }, + ].map((app) => { + const isInstalled = vm.installedApps.some((a) => a.packageName === app.pkg); + return ( +
+
+

{app.name}

+

{app.pkg}

+
+ +
+ ); + })} +
+
+ )} +
+ )} +
+ + {/* Android Bottom Soft Navigation Bar */} +
+ + + +
+
+
+
+ + {/* Right Info & Live VM Metrics Panel (5 cols) */} +
+ {/* Live VM Performance Metrics Card */} +
+

+
+ + Hypervisor Hardware Status +
+ + KVM/QEMU ACTIVE + +

+ +
+
+ CPU Allocation +

{vm.vcpu} vCPUs ({vm.metrics.cpuUsagePct}% Load)

+
+
+ RAM Provisioned +

{vm.metrics.ramUsageMb} / {vm.ramGb * 1024} MB

+
+
+ Display Stream FPS +

{vm.metrics.fps} FPS

+
+
+ Network I/O +

{vm.metrics.networkRxKbps} KB/s

+
+
+ + {/* Quick Actions */} +
+ + + +
+ + {/* Battery Level Slider */} +
+
+ Battery Level: + + {vm.batteryLevel}% ({vm.isCharging ? 'Charging' : 'Discharging'}) + +
+ onUpdateBattery(parseInt(e.target.value), vm.isCharging)} + className="w-full accent-emerald-500" + /> +
+
+ + {/* Installed Packages Drawer */} +
+
+

+ + Installed Package Drawer +

+ + {vm.installedApps.length} packages + +
+ +
+ {vm.installedApps.map((app) => ( +
+
+ {app.appName} + + {app.packageName} + +
+ + +
+ ))} +
+
+
+
+ + {/* GPS Spoof Modal */} + {isGpsModalOpen && ( +
+
+
+

+ + Spoof Virtual GPS Location +

+ +
+ +
+
+ + setInputAddress(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-slate-200 focus:outline-none focus:border-amber-500" + /> +
+ +
+
+ + setInputLat(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-slate-200 focus:outline-none focus:border-amber-500" + /> +
+
+ + setInputLng(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-slate-200 focus:outline-none focus:border-amber-500" + /> +
+
+ +
+ + +
+
+
+
+ )} + + {/* APK Installer Modal with File Upload */} + {isApkModalOpen && ( +
+
+
+

+ + Sideload & Install Any APK Package +

+ +
+ + {/* Drag & Drop APK File Dropzone */} +
e.preventDefault()} + onDrop={(e) => { + e.preventDefault(); + if (e.dataTransfer.files && e.dataTransfer.files[0]) { + handleApkFileUpload(e.dataTransfer.files[0]); + } + }} + className="border-2 border-dashed border-indigo-500/40 hover:border-indigo-500 bg-slate-950/60 rounded-xl p-5 text-center transition-all cursor-pointer relative group" + > + { + if (e.target.files && e.target.files[0]) { + handleApkFileUpload(e.target.files[0]); + } + }} + className="absolute inset-0 opacity-0 cursor-pointer w-full h-full z-10" + /> +
+
+ +
+
+

+ Drag & Drop any .apk file here +

+

or click to browse local disk storage

+
+
+
+ + {/* Upload / Stream Install Progress Bar */} + {apkUploading && ( +
+
+ Stream Installing APK Package... + {apkProgress}% +
+
+
+
+

+ adb install -r -g /data/local/tmp/{newPackageName || 'app.apk'} +

+
+ )} + +
+
+ +
+ {[ + { name: 'Facebook App', pkg: 'com.facebook.katana' }, + { name: 'Instagram', pkg: 'com.instagram.android' }, + { name: 'WhatsApp Messenger', pkg: 'com.whatsapp' }, + { name: 'TikTok', pkg: 'com.zhiliaoapp.musically' }, + { name: 'Spotify Music', pkg: 'com.spotify.music' }, + { name: 'YouTube', pkg: 'com.google.android.youtube' }, + ].map((preset) => ( + + ))} +
+
+ +
+ + setNewAppName(e.target.value)} + required + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-slate-200 focus:outline-none focus:border-indigo-500" + /> +
+ +
+ + setNewPackageName(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-slate-200 focus:outline-none focus:border-indigo-500" + /> +
+ +
+ + +
+
+
+
+ )} + + {/* Programmatic Automation Studio Drawer Modal */} + {isAutomationStudioOpen && ( +
+
+
+ +
+
+ { + const baseUrl = window.location.origin; + const res = await fetch(`${baseUrl}/api/vms/${vm.id}/adb`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ command: cmd }), + }); + const data = await res.json(); + return { output: data.output || '', exitCode: 0 }; + }} + onLaunchApp={onLaunchApp} + onInstallApk={onInstallApk} + inspectorCoords={inspectorCoord} + /> +
+
+
+ )} +
+ ); +}; diff --git a/src/components/BootloaderStudio.tsx b/src/components/BootloaderStudio.tsx new file mode 100644 index 0000000..d6a1159 --- /dev/null +++ b/src/components/BootloaderStudio.tsx @@ -0,0 +1,224 @@ +import React, { useState } from 'react'; +import { AndroidVM, RootMethod, SELinuxMode } from '../types'; +import { + ShieldAlert, + Unlock, + Lock, + Cpu, + Terminal, + RotateCcw, + Check, + Zap, + Play, + Settings, + HardDrive, + Copy, + Layers, +} from 'lucide-react'; + +interface BootloaderStudioProps { + vm: AndroidVM; + vms: AndroidVM[]; + onSelectVm: (vmId: string) => void; + onExecuteFastboot: (command: string) => Promise; + onUpdateBootloaderConfig: (updatedBootloader: Partial) => void; +} + +export const BootloaderStudio: React.FC = ({ + vm, + vms, + onSelectVm, + onExecuteFastboot, + onUpdateBootloaderConfig, +}) => { + const [fastbootCmd, setFastbootCmd] = useState(''); + const [fastbootOutput, setFastbootOutput] = useState('Fastboot CLI ready.'); + const [kernelCmdlineInput, setKernelCmdlineInput] = useState(vm.bootloader.kernelCmdline); + + const handleRunFastboot = async (cmd?: string) => { + const commandToRun = cmd || fastbootCmd; + if (!commandToRun) return; + const res = await onExecuteFastboot(commandToRun); + setFastbootOutput(`$ ${commandToRun}\n${res}`); + setFastbootCmd(''); + }; + + const handleSaveCmdline = () => { + onUpdateBootloaderConfig({ kernelCmdline: kernelCmdlineInput }); + setFastbootOutput(`Updated kernel commandline: ${kernelCmdlineInput}`); + }; + + return ( +
+ {/* Target Selector & Bootloader Status Bar */} +
+
+ +
+ Selected Device: + +
+
+ +
+ + {vm.bootloader.isUnlocked ? : } + BOOTLOADER {vm.bootloader.isUnlocked ? 'UNLOCKED' : 'LOCKED'} + +
+
+ + {/* Bootloader & Root Configuration Cards */} +
+ {/* Bootloader & Root Controls */} +
+

+ + Bootloader & Root Configuration +

+ + {/* Toggle Bootloader Unlock */} +
+
+ Bootloader Lock State + + Allows flashing unsigned boot/recovery partitions + +
+ + +
+ + {/* Root Privilege Selection */} +
+ +
+ {(['none', 'magisk', 'kernelsu'] as RootMethod[]).map((r) => ( + + ))} +
+
+ + {/* SELinux Enforcement Toggle */} +
+ +
+ {(['enforcing', 'permissive'] as SELinuxMode[]).map((m) => ( + + ))} +
+
+
+ + {/* Kernel Commandline Editor */} +
+

+ + Kernel Boot Arguments & Parameters +

+ +
+ +