diff --git a/.dockerignore b/.dockerignore index 44c3cb5a7a208ea447f9cb4e5955f3f3ed469bd0..8da1d212c3ffaade7295bf47baa2ef0f68a17d97 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,52 +1,103 @@ -# Git -.git -.gitignore - -# Node modules and build artifacts -node_modules -.svelte-kit -demo/build -demo/node_modules -client/js/node_modules -client/js/dist - -# Python cache and virtual environments -__pycache__ -*.pyc -*.pyo -*.pyd -.Python -.venv -.pytest_cache -*.egg-info - -# Development files -*.log -logs/ -.DS_Store -Thumbs.db - -# IDE files -.vscode -.idea -*.swp -*.swo - -# Temporary files -*.tmp -*.temp - -# Documentation -*.md -!README.md +/* # Node.js dependencies and cache */ +**/node_modules/ +**/.npm +**/npm-debug.log* +**/yarn-debug.log* +**/yarn-error.log* +**/.pnpm-debug.log* + +# Bun runtime files +**/.bun + +# Build outputs and generated files +**/dist/ +**/build/ +**/.next/ +**/.svelte-kit/ + +# Environment and development files +**/.env +**/.env.local +**/.env.development.local +**/.env.test.local +**/.env.production.local + +# Python cache and bytecode +**/__pycache__/ +**/*.py[cod] +**/*$py.class +**/*.so +**/.Python +**/develop-eggs/ +**/downloads/ +**/eggs/ +**/.eggs/ +**/lib/ +**/lib64/ +**/parts/ +**/sdist/ +**/var/ +**/wheels/ +**/*.egg-info/ +**/.installed.cfg +**/*.egg +**/MANIFEST + +# Virtual environments +**/.venv/ +**/venv/ +**/ENV/ +**/env/ + +# IDEs and editors +**/.vscode/ +**/.idea/ +**/*.swp +**/*.swo +**/*~ + +# Operating system files +**/.DS_Store +**/Thumbs.db + +# Version control +**/.git/ +**/.gitignore + +# Docker related files +**/Dockerfile* +**/docker-compose* +**/.dockerignore + +# Logs and temporary files +**/logs/ +**/*.log +**/server.log +**/.cache/ +**/tmp/ +**/.tmp/ +**/.pytest_cache/ +**/.mypy_cache/ # Test files -tests/ -test_* - -# Development configs -.eslintrc* -.prettierrc* -*.config.js -!svelte.config.js -!vite.config.ts \ No newline at end of file +**/test*/ +**/tests/ +**/*test.py +**/*_test.py + +# Lock files for other package managers +**/yarn.lock +**/package-lock.json +**/poetry.lock +**/Pipfile.lock + +# Documentation files +**/README.md +**/CHANGELOG.md +**/docs/ + +# CI/CD configuration files +**/.github/ +**/.gitlab-ci.yml +**/azure-pipelines.yml +**/.circleci/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3f86625b11b4db6ea323ed7db6e6f4c5411933e4..96a72b2dd0a48d005b98d517e84e2336dc34da36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,70 +7,114 @@ WORKDIR /app # Install git for dependencies that might need it RUN apk add --no-cache git -# Copy all JavaScript/TypeScript files -COPY client/js/ ./client/js/ -COPY demo/ ./demo/ +# Copy package files for better caching +COPY client/js/package.json client/js/tsconfig.json* ./client/js/ +COPY demo/package.json demo/tsconfig.json* demo/svelte.config.js* ./demo/ -# Build and link client library +# Install client library dependencies first WORKDIR /app/client/js -RUN bun install +RUN bun install --frozen-lockfile + +# Copy client library source code +COPY client/js/src/ ./src/ +COPY client/js/bun.lock* ./ + +# Build and link client library RUN bun run build RUN bun link -# Build demo with linked client library +# Install demo dependencies with linked client library WORKDIR /app/demo -RUN bun link lerobot-arena-client -RUN bun install +RUN bun link @robothub/transport-server-client +RUN bun install --frozen-lockfile + +# Copy demo source code +COPY demo/src/ ./src/ +COPY demo/static/ ./static/ +COPY demo/vite.config.ts* demo/tailwind.config.* demo/.prettierrc* ./ + +# Build demo application RUN bun run build # Stage 2: Python backend with uv FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +# Set environment variables for Python and UV +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + UV_SYSTEM_PYTHON=1 \ + UV_COMPILE_BYTECODE=1 \ + UV_CACHE_DIR=/tmp/uv-cache + # Install system dependencies needed for video processing RUN apt-get update && apt-get install -y \ + # Build tools for compiling Python packages + build-essential \ + gcc \ + g++ \ + # Video processing libraries libavformat-dev \ libavcodec-dev \ libavdevice-dev \ libavutil-dev \ libswscale-dev \ libswresample-dev \ + # Additional system libraries + libgl1-mesa-glx \ + libglib2.0-0 \ + libsm6 \ + libxext6 \ + libxrender-dev \ + libgomp1 \ pkg-config \ + # FFmpeg for video processing + ffmpeg \ + # Git for potential model downloads + git \ + # Clean up + && apt-get clean \ && rm -rf /var/lib/apt/lists/* -# Set up a new user named "user" with user ID 1000 (required for HF Spaces) -RUN useradd -m -u 1000 user - -# Switch to the "user" user -USER user +# Create a non-root user (required for HF Spaces) +RUN groupadd -r appuser && useradd -r -g appuser -m -s /bin/bash -u 1000 appuser -# Set home to the user's home directory -ENV HOME=/home/user \ - PATH=/home/user/.local/bin:$PATH +# Set working directory and ensure it's owned by appuser +WORKDIR /app +RUN chown -R appuser:appuser /app -# Set the working directory to the user's home directory -WORKDIR $HOME/app +# Switch to appuser before installing dependencies +USER appuser -# Copy Python project files for dependency resolution -COPY --chown=user server/pyproject.toml server/uv.lock* ./server/ +# Copy dependency files for better layer caching +COPY --chown=appuser:appuser server/pyproject.toml server/uv.lock* ./server/ # Install dependencies first (better caching) -WORKDIR $HOME/app/server -RUN uv sync --no-install-project +WORKDIR /app/server +RUN --mount=type=cache,target=/tmp/uv-cache,uid=1000,gid=1000 \ + uv sync --locked --no-install-project --no-dev # Copy the rest of the Python backend -COPY --chown=user server/ ./ +COPY --chown=appuser:appuser server/ ./ -# Install the project itself -RUN uv sync +# Install the project in non-editable mode for production +RUN --mount=type=cache,target=/tmp/uv-cache,uid=1000,gid=1000 \ + uv sync --locked --no-editable --no-dev # Copy built frontend from previous stage with proper ownership -COPY --chown=user --from=frontend-builder /app/demo/build $HOME/app/static-frontend +COPY --chown=appuser:appuser --from=frontend-builder /app/demo/build /app/static-frontend # Set working directory back to app root -WORKDIR $HOME/app +WORKDIR /app + +# Add virtual environment to PATH +ENV PATH="/app/server/.venv/bin:$PATH" -# Expose port 7860 (HF Spaces default) +# Expose port 7860 (HuggingFace Spaces default) EXPOSE 7860 +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/health')" || exit 1 + # Start the FastAPI server (serves both frontend and backend) -CMD ["sh", "-c", "cd server && SERVE_FRONTEND=true uv run python launch_with_ui.py"] \ No newline at end of file +CMD ["sh", "-c", "cd server && SERVE_FRONTEND=true uv run python launch_with_ui.py --host 0.0.0.0 --port 7860"] \ No newline at end of file diff --git a/client/js/README.md b/client/js/README.md index dcd0004c42ee235daaf59f0ceab1c6c35794687c..81022a192e8e5a99337f584225ee3ed3fdb4af8a 100644 --- a/client/js/README.md +++ b/client/js/README.md @@ -30,7 +30,7 @@ bun run build ### Producer (Robot Controller) ```typescript -import { RoboticsProducer, createProducerClient } from '@robohub/transport-server-client'; +import { RoboticsProducer, createProducerClient } from '@robothub/transport-server-client'; // Method 1: Manual setup const producer = new RoboticsProducer('http://localhost:8000'); @@ -61,7 +61,7 @@ await producer.sendEmergencyStop('Safety stop triggered'); ### Consumer (Robot Monitor) ```typescript -import { RoboticsConsumer, createConsumerClient } from '@robohub/transport-server-client'; +import { RoboticsConsumer, createConsumerClient } from '@robothub/transport-server-client'; // Connect to existing room const consumer = await createConsumerClient(roomId, 'http://localhost:8000'); @@ -152,7 +152,7 @@ const consumer = await RoboticsConsumer.createAndConnect(roomId, baseUrl, partic ### Factory Functions ```typescript -import { createClient, createProducerClient, createConsumerClient } from '@robohub/transport-server-client'; +import { createClient, createProducerClient, createConsumerClient } from '@robothub/transport-server-client'; // Generic factory const client = createClient('producer', 'http://localhost:8000'); diff --git a/client/js/bun.lock b/client/js/bun.lock index 8bb553bcb6eb1840c6a56bd80e4283165891291c..e35f61c48ccf7e4bde82943d90acda056ece5b93 100644 --- a/client/js/bun.lock +++ b/client/js/bun.lock @@ -4,15 +4,11 @@ "": { "name": "lerobot_arena_client", "dependencies": { - "@hey-api/client-fetch": "^0.2.1", "eventemitter3": "^5.0.1", }, "devDependencies": { - "@hey-api/openapi-ts": "^0.53.8", "@types/bun": "^1.2.15", "typescript": "^5.3.3", - "vite": "6.3.5", - "vite-plugin-dts": "4.5.4", }, "peerDependencies": { "typescript": ">=5.0.0", @@ -20,390 +16,16 @@ }, }, "packages": { - "@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.7.2", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - - "@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], - - "@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], - - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.5", "", { "os": "android", "cpu": "arm64" }, "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.5", "", { "os": "android", "cpu": "x64" }, "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.5", "", { "os": "linux", "cpu": "arm" }, "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.5", "", { "os": "none", "cpu": "x64" }, "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g=="], - - "@hey-api/client-fetch": ["@hey-api/client-fetch@0.2.4", "", {}, "sha512-SGTVAVw3PlKDLw+IyhNhb/jCH3P1P2xJzLxA8Kyz1g95HrkYOJdRpl9F5I7LLwo9aCIB7nwR2NrSeX7QaQD7vQ=="], - - "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.53.12", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "11.7.2", "c12": "2.0.1", "commander": "12.1.0", "handlebars": "4.7.8" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-cOm8AlUqJIWdLXq+Pk4mTXhEApRSc9xEWTVT8MZAyEqrN1Yhiisl2wyZGH9quzKpolq+oqvgcx61txtwHwi8vQ=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], - - "@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="], - - "@microsoft/api-extractor": ["@microsoft/api-extractor@7.52.8", "", { "dependencies": { "@microsoft/api-extractor-model": "7.30.6", "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", "@rushstack/node-core-library": "5.13.1", "@rushstack/rig-package": "0.5.3", "@rushstack/terminal": "0.15.3", "@rushstack/ts-command-line": "5.0.1", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.8.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-cszYIcjiNscDoMB1CIKZ3My61+JOhpERGlGr54i6bocvGLrcL/wo9o+RNXMBrb7XgLtKaizZWUpqRduQuHQLdg=="], - - "@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.30.6", "", { "dependencies": { "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", "@rushstack/node-core-library": "5.13.1" } }, "sha512-znmFn69wf/AIrwHya3fxX6uB5etSIn6vg4Q4RB/tb5VDDs1rqREc+AvMC/p19MUN13CZ7+V/8pkYPTj7q8tftg=="], - - "@microsoft/tsdoc": ["@microsoft/tsdoc@0.15.1", "", {}, "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw=="], - - "@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.17.1", "", { "dependencies": { "@microsoft/tsdoc": "0.15.1", "ajv": "~8.12.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw=="], - - "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], - - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.41.1", "", { "os": "android", "cpu": "arm" }, "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.41.1", "", { "os": "android", "cpu": "arm64" }, "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.41.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.41.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.41.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.41.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.41.1", "", { "os": "linux", "cpu": "arm" }, "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.41.1", "", { "os": "linux", "cpu": "arm" }, "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.41.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA=="], - - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.41.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg=="], - - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.41.1", "", { "os": "linux", "cpu": "none" }, "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw=="], - - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.41.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A=="], - - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.41.1", "", { "os": "linux", "cpu": "none" }, "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw=="], - - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.41.1", "", { "os": "linux", "cpu": "none" }, "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw=="], - - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.41.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g=="], - - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.41.1", "", { "os": "linux", "cpu": "x64" }, "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A=="], - - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.41.1", "", { "os": "linux", "cpu": "x64" }, "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.41.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.41.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.41.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw=="], - - "@rushstack/node-core-library": ["@rushstack/node-core-library@5.13.1", "", { "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-5yXhzPFGEkVc9Fu92wsNJ9jlvdwz4RNb2bMso+/+TH0nMm1jDDDsOIf4l8GAkPxGuwPw5DH24RliWVfSPhlW/Q=="], - - "@rushstack/rig-package": ["@rushstack/rig-package@0.5.3", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow=="], - - "@rushstack/terminal": ["@rushstack/terminal@0.15.3", "", { "dependencies": { "@rushstack/node-core-library": "5.13.1", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-DGJ0B2Vm69468kZCJkPj3AH5nN+nR9SPmC0rFHtzsS4lBQ7/dgOwtwVxYP7W9JPDMuRBkJ4KHmWKr036eJsj9g=="], - - "@rushstack/ts-command-line": ["@rushstack/ts-command-line@5.0.1", "", { "dependencies": { "@rushstack/terminal": "0.15.3", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-bsbUucn41UXrQK7wgM8CNM/jagBytEyJqXw/umtI8d68vFm1Jwxh1OtLrlW7uGZgjCWiiPH6ooUNa1aVsuVr3Q=="], - - "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], - "@types/bun": ["@types/bun@1.2.15", "", { "dependencies": { "bun-types": "1.2.15" } }, "sha512-U1ljPdBEphF0nw1MIk0hI7kPg7dFdPyM7EenHsp6W5loNHl7zqy6JQf/RKCgnUn2KDzUpkBwHPnEJEjII594bA=="], - "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/node": ["@types/node@22.15.30", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA=="], - "@volar/language-core": ["@volar/language-core@2.4.14", "", { "dependencies": { "@volar/source-map": "2.4.14" } }, "sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w=="], - - "@volar/source-map": ["@volar/source-map@2.4.14", "", {}, "sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ=="], - - "@volar/typescript": ["@volar/typescript@2.4.14", "", { "dependencies": { "@volar/language-core": "2.4.14", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw=="], - - "@vue/compiler-core": ["@vue/compiler-core@3.5.16", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/shared": "3.5.16", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ=="], - - "@vue/compiler-dom": ["@vue/compiler-dom@3.5.16", "", { "dependencies": { "@vue/compiler-core": "3.5.16", "@vue/shared": "3.5.16" } }, "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ=="], - - "@vue/compiler-vue2": ["@vue/compiler-vue2@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A=="], - - "@vue/language-core": ["@vue/language-core@2.2.0", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^0.4.9", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw=="], - - "@vue/shared": ["@vue/shared@3.5.16", "", {}, "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg=="], - - "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], - - "ajv": ["ajv@8.12.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA=="], - - "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], - - "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - - "alien-signals": ["alien-signals@0.4.14", "", {}, "sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - "bun-types": ["bun-types@1.2.15", "", { "dependencies": { "@types/node": "*" } }, "sha512-NarRIaS+iOaQU1JPfyKhZm4AsUOrwUOqRNHY0XxI8GI8jYxiLXLcdjYMG9UKS+fwWasc1uw1htV9AX24dD+p4w=="], - "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], - - "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - - "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], - - "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], - - "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], - - "compare-versions": ["compare-versions@6.1.1", "", {}, "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], - - "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], - - "de-indent": ["de-indent@1.0.2", "", {}, "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="], - - "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], - - "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], - - "dotenv": ["dotenv@16.5.0", "", {}, "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="], - - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="], - - "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - "exsolve": ["exsolve@1.0.5", "", {}, "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fdir": ["fdir@6.4.5", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw=="], - - "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], - - "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "giget": ["giget@1.2.5", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.5.4", "pathe": "^2.0.3", "tar": "^6.2.1" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug=="], - - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - - "handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - - "import-lazy": ["import-lazy@4.0.0", "", {}, "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw=="], - - "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], - - "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], - - "jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="], - - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], - - "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], - - "local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="], - - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - - "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], - - "minimatch": ["minimatch@3.0.8", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], - - "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], - - "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], - - "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="], - - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - - "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], - - "node-fetch-native": ["node-fetch-native@1.6.6", "", {}, "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="], - - "nypm": ["nypm@0.5.4", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "tinyexec": "^0.3.2", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA=="], - - "ohash": ["ohash@1.1.6", "", {}, "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg=="], - - "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], - - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - - "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], - - "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], - - "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - - "postcss": ["postcss@8.5.4", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], - - "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], - - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], - - "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], - - "rollup": ["rollup@4.41.1", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.41.1", "@rollup/rollup-android-arm64": "4.41.1", "@rollup/rollup-darwin-arm64": "4.41.1", "@rollup/rollup-darwin-x64": "4.41.1", "@rollup/rollup-freebsd-arm64": "4.41.1", "@rollup/rollup-freebsd-x64": "4.41.1", "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", "@rollup/rollup-linux-arm-musleabihf": "4.41.1", "@rollup/rollup-linux-arm64-gnu": "4.41.1", "@rollup/rollup-linux-arm64-musl": "4.41.1", "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", "@rollup/rollup-linux-riscv64-gnu": "4.41.1", "@rollup/rollup-linux-riscv64-musl": "4.41.1", "@rollup/rollup-linux-s390x-gnu": "4.41.1", "@rollup/rollup-linux-x64-gnu": "4.41.1", "@rollup/rollup-linux-x64-musl": "4.41.1", "@rollup/rollup-win32-arm64-msvc": "4.41.1", "@rollup/rollup-win32-ia32-msvc": "4.41.1", "@rollup/rollup-win32-x64-msvc": "4.41.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw=="], - - "semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="], - - "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - - "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], - - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - - "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - - "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], - - "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - - "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], - "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], - - "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], - "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - - "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "vite": ["vite@6.3.5", "", { "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" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], - - "vite-plugin-dts": ["vite-plugin-dts@4.5.4", "", { "dependencies": { "@microsoft/api-extractor": "^7.50.1", "@rollup/pluginutils": "^5.1.4", "@volar/typescript": "^2.4.11", "@vue/language-core": "2.2.0", "compare-versions": "^6.1.1", "debug": "^4.4.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "magic-string": "^0.30.17" }, "peerDependencies": { "typescript": "*", "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg=="], - - "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], - - "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], - - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "@microsoft/api-extractor/typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - - "@rushstack/node-core-library/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], - - "@rushstack/ts-command-line/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - - "@vue/language-core/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="], - - "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "local-pkg/pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="], - - "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - - "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - - "@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "local-pkg/pkg-types/confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], - - "local-pkg/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], } } diff --git a/client/js/package.json b/client/js/package.json index 6ada2be93819ebc008790bc3fc7e3f1c39f9d80c..f26ca1f0d536a308726927884052fcdfd361f39b 100644 --- a/client/js/package.json +++ b/client/js/package.json @@ -1,5 +1,5 @@ { - "name": "@robohub/transport-server-client", + "name": "@robothub/transport-server-client", "version": "1.0.0", "description": "Modular TypeScript client library for LeRobot Arena - video streaming, robotics control, and sensor data", "type": "module", @@ -11,16 +11,12 @@ "types": "./dist/index.d.ts" }, "./video": { - "import": "./dist/video.js", - "types": "./dist/video.d.ts" + "import": "./dist/video/index.js", + "types": "./dist/video/index.d.ts" }, "./robotics": { - "import": "./dist/robotics.js", - "types": "./dist/robotics.d.ts" - }, - "./audio": { - "import": "./dist/audio.js", - "types": "./dist/audio.d.ts" + "import": "./dist/robotics/index.js", + "types": "./dist/robotics/index.d.ts" } }, "files": [ @@ -28,11 +24,9 @@ "README.md" ], "scripts": { - "build": "bun build src/index.ts --outdir dist --target bun --format esm --sourcemap && bun build src/video.ts --outdir dist --target bun --format esm --sourcemap && bun build src/robotics.ts --outdir dist --target bun --format esm --sourcemap && bun build src/audio.ts --outdir dist --target bun --format esm --sourcemap && bunx tsc --emitDeclarationOnly --declaration --outDir dist", + "build": "bun build src/index.ts --outdir dist --target bun --format esm --sourcemap && bunx tsc --emitDeclarationOnly --declaration --outDir dist", "dev": "bun --watch src/index.ts", "test": "bun test", - "lint": "bun run eslint src --ext ts,tsx", - "lint:fix": "bun run eslint src --ext ts,tsx --fix", "typecheck": "bun run tsc --noEmit", "clean": "rm -rf dist", "prebuild": "bun run clean" @@ -61,13 +55,13 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/julien-blanchon/RoboHub.git#main:services/transport-server/client/js", + "url": "git+https://github.com/julien-blanchon/robothub.git#main:services/transport-server/client/js", "directory": "services/transport-server/client/js" }, "bugs": { - "url": "https://github.com/julien-blanchon/RoboHub.git#main:services/transport-server/client/js" + "url": "https://github.com/julien-blanchon/robothub.git#main:services/transport-server/client/js" }, - "homepage": "https://github.com/julien-blanchon/RoboHub.git#main:services/transport-server/client/js", + "homepage": "https://github.com/julien-blanchon/robothub.git#main:services/transport-server/client/js", "engines": { "bun": ">=1.0.0" }, diff --git a/client/js/src/video/producer.ts b/client/js/src/video/producer.ts index a9880df124da5ebe5228b3c2cf1d942984d14173..b318c0d69b945f77ef98f36fd4343fee02bb514c 100644 --- a/client/js/src/video/producer.ts +++ b/client/js/src/video/producer.ts @@ -124,7 +124,7 @@ export class VideoProducer extends VideoClientCore { } private async restartConnectionsWithNewStream(stream: MediaStream): Promise { - console.info('šŸ”„ Restarting connections with new stream...'); + console.info('šŸ”„ Restarting connections with new stream...', { streamId: stream.id }); // Close all existing connections for (const [consumerId, peerConnection] of this.consumerConnections) { diff --git a/client/js/tsconfig.json b/client/js/tsconfig.json index ae7885a0fbdd372b0ed040057f1bb124a13616c2..3001e40a5b7d3fcd649b8615c5468966799d32ac 100644 --- a/client/js/tsconfig.json +++ b/client/js/tsconfig.json @@ -1,32 +1,35 @@ { "compilerOptions": { - // Environment setup & latest features - "lib": ["ESNext", "DOM"], - "target": "ESNext", - "module": "Preserve", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, - - // Enable Bun types - "types": ["bun-types"], - - // Bundler mode (for Vite) + "target": "ES2022", + "lib": ["ES2022", "DOM"], + "module": "ESNext", "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "noEmit": true, - - // Best practices + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "dist", "strict": true, - "skipLibCheck": true, + "noUnusedLocals": true, + "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } + "skipLibCheck": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "types": ["bun-types"] + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist", + "**/*.config.*", + "**/vite.config.ts" + ] } diff --git a/client/js/vite.config.ts b/client/js/vite.config.ts deleted file mode 100644 index 15df02c8c7fa65300c4f4e6d9cd8cc94a5ca64fe..0000000000000000000000000000000000000000 --- a/client/js/vite.config.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { defineConfig } from 'vite'; -import { resolve } from 'path'; -import dts from 'vite-plugin-dts'; - -export default defineConfig({ - plugins: [ - dts({ - insertTypesEntry: true, - rollupTypes: true, - }), - ], - build: { - lib: { - entry: { - index: resolve('src/index.ts'), - video: resolve('src/video/index.ts'), - robotics: resolve('src/robotics/index.ts'), - }, - formats: ['es'], - }, - rollupOptions: { - external: ['eventemitter3'], - output: { - preserveModules: false, - exports: 'named', - }, - }, - target: 'esnext', - minify: false, - }, - resolve: { - alias: { - '@': resolve('src'), - '@/video': resolve('src/video'), - '@/robotics': resolve('src/robotics'), - }, - }, -}); \ No newline at end of file diff --git a/client/python/README.md b/client/python/README.md index d5a1862aba28b8eb899b9207752ea28ea4cfdd9d..d335ee3b7c2a671311f11a52de82650d2d26c58d 100644 --- a/client/python/README.md +++ b/client/python/README.md @@ -20,7 +20,7 @@ pip install -e ".[dev]" ```python import asyncio -from lerobot_arena_client import RoboticsProducer +from transport_server_client import RoboticsProducer async def main(): # Create producer client @@ -60,7 +60,7 @@ if __name__ == "__main__": ```python import asyncio -from lerobot_arena_client import RoboticsConsumer +from transport_server_client import RoboticsConsumer async def main(): consumer = RoboticsConsumer('http://localhost:8000') @@ -105,7 +105,7 @@ if __name__ == "__main__": ```python import asyncio -from lerobot_arena_client import create_client +from transport_server_client import create_client async def main(): # Create clients using factory function @@ -113,7 +113,7 @@ async def main(): consumer = create_client("consumer", "http://localhost:8000") # Or use convenience functions - from lerobot_arena_client import create_producer_client, create_consumer_client + from transport_server_client import create_producer_client, create_consumer_client # Quick producer setup (auto-creates room and connects) producer = await create_producer_client('http://localhost:8000') @@ -136,7 +136,7 @@ if __name__ == "__main__": ```python import asyncio -from lerobot_arena_client import RoboticsProducer, RoboticsConsumer +from transport_server_client import RoboticsProducer, RoboticsConsumer async def run_producer(room_id: str): async with RoboticsProducer() as producer: diff --git a/client/python/examples/basic_consumer.py b/client/python/examples/basic_consumer.py index f4d41d4c2961a82517d23b6eb14940e13bf30584..77f4a18a1b79fb3850bbbdbb949331fdc6f70417 100644 --- a/client/python/examples/basic_consumer.py +++ b/client/python/examples/basic_consumer.py @@ -12,7 +12,7 @@ This example demonstrates: import asyncio import logging -from lerobot_arena_client import RoboticsConsumer +from transport_server_client import RoboticsConsumer # Setup logging logging.basicConfig(level=logging.INFO) @@ -81,7 +81,7 @@ async def main(): logger.info(f"Received {len(received_states)} state syncs") except Exception as e: - logger.error(f"Error: {e}") + logger.exception(f"Error: {e}") finally: # Always disconnect if consumer.is_connected(): diff --git a/client/python/examples/basic_producer.py b/client/python/examples/basic_producer.py index 2d32d4322aab166cad840f722747f1097af44d80..169621eb922b4f52c7740768acee175849e61862 100644 --- a/client/python/examples/basic_producer.py +++ b/client/python/examples/basic_producer.py @@ -12,7 +12,7 @@ This example demonstrates: import asyncio import logging -from lerobot_arena_client import RoboticsProducer +from transport_server_client import RoboticsProducer # Setup logging logging.basicConfig(level=logging.INFO) @@ -65,7 +65,7 @@ async def main(): logger.info("Example completed successfully!") except Exception as e: - logger.error(f"Error: {e}") + logger.exception(f"Error: {e}") finally: # Always disconnect if producer.is_connected(): diff --git a/client/python/examples/consumer_first_recorder.py b/client/python/examples/consumer_first_recorder.py index 7732435b9b7481d124ff9522efb4501d1f3a809b..494f1d4aa83521734764b24c3413b3f217a03fdd 100644 --- a/client/python/examples/consumer_first_recorder.py +++ b/client/python/examples/consumer_first_recorder.py @@ -18,7 +18,7 @@ from pathlib import Path import cv2 import numpy as np -from lerobot_arena_client.video import VideoConsumer +from transport_server_client.video import VideoConsumer # Setup logging logging.basicConfig( @@ -123,7 +123,7 @@ class VideoRecorder: ) except Exception as e: - logger.error(f"āŒ Error adding frame to recording: {e}") + logger.exception(f"āŒ Error adding frame to recording: {e}") return False @@ -290,7 +290,7 @@ async def main(): logger.warning("āš ļø No recording was made - producer may not have joined") except Exception as e: - logger.error(f"āŒ Consumer-first recorder failed: {e}") + logger.exception(f"āŒ Consumer-first recorder failed: {e}") import traceback traceback.print_exc() @@ -303,7 +303,7 @@ async def main(): await consumer.disconnect() logger.info("šŸ‘‹ Consumer disconnected successfully") except Exception as e: - logger.error(f"Error during cleanup: {e}") + logger.exception(f"Error during cleanup: {e}") if __name__ == "__main__": @@ -313,7 +313,7 @@ if __name__ == "__main__": logger.info("šŸ›‘ Stopped by user") logger.info("šŸ‘‹ Goodbye!") except Exception as e: - logger.error(f"šŸ’„ Fatal error: {e}") + logger.exception(f"šŸ’„ Fatal error: {e}") import traceback traceback.print_exc() diff --git a/client/python/examples/context_manager_example.py b/client/python/examples/context_manager_example.py index 3402b6db05be2b81e5fb63ad8e15098cc86f25a2..0b2ce4aacdd988d39caf07524c570f4d616f1a09 100644 --- a/client/python/examples/context_manager_example.py +++ b/client/python/examples/context_manager_example.py @@ -12,7 +12,7 @@ This example demonstrates: import asyncio import logging -from lerobot_arena_client import ( +from transport_server_client import ( RoboticsConsumer, RoboticsProducer, create_consumer_client, @@ -67,7 +67,7 @@ async def factory_function_example(): # Set up callback received_updates = [] - consumer.on_joint_update(lambda joints: received_updates.append(joints)) + consumer.on_joint_update(received_updates.append) # Send some updates await producer.send_joint_update([ @@ -99,14 +99,15 @@ async def exception_handling_example(): for i in range(5): if i == 3: # Simulate an error - raise ValueError("Simulated error during operation") + msg = "Simulated error during operation" + raise ValueError(msg) await producer.send_state_sync({f"joint_{i}": float(i * 10)}) logger.info(f"Sent update {i}") await asyncio.sleep(0.1) except ValueError as e: - logger.error(f"Caught expected error: {e}") + logger.exception(f"Caught expected error: {e}") logger.info("Context manager still ensures cleanup") logger.info("Exception handling example completed") @@ -170,7 +171,7 @@ async def main(): logger.info("\nāœ… All context manager examples completed successfully!") except Exception as e: - logger.error(f"āŒ Example failed: {e}") + logger.exception(f"āŒ Example failed: {e}") if __name__ == "__main__": diff --git a/client/python/examples/producer_consumer_demo.py b/client/python/examples/producer_consumer_demo.py index 4cce160c181747f0f3724c214b7fcc20e2cc0f2c..5d47f2be81cc48013f420d859f217d9ace6762cf 100644 --- a/client/python/examples/producer_consumer_demo.py +++ b/client/python/examples/producer_consumer_demo.py @@ -14,7 +14,7 @@ import asyncio import logging import random -from lerobot_arena_client import RoboticsConsumer, RoboticsProducer +from transport_server_client import RoboticsConsumer, RoboticsProducer # Setup logging logging.basicConfig(level=logging.INFO) @@ -200,7 +200,7 @@ async def main(): logger.info("Demo completed successfully!") except Exception as e: - logger.error(f"Demo error: {e}") + logger.exception(f"Demo error: {e}") finally: # Cleanup logger.info("Cleaning up...") diff --git a/client/python/examples/room_management.py b/client/python/examples/room_management.py index 3d70de44917d40680e9d843e321a6330b27acb03..8b6737e36014d3aab3ca587b72bf275fda1118a7 100644 --- a/client/python/examples/room_management.py +++ b/client/python/examples/room_management.py @@ -13,7 +13,7 @@ This example demonstrates: import asyncio import logging -from lerobot_arena_client import RoboticsClientCore +from transport_server_client import RoboticsClientCore # Setup logging logging.basicConfig(level=logging.INFO) @@ -86,7 +86,7 @@ async def main(): logger.info("\nRoom management example completed!") except Exception as e: - logger.error(f"Error: {e}") + logger.exception(f"Error: {e}") if __name__ == "__main__": diff --git a/client/python/examples/test_consumer_fix.py b/client/python/examples/test_consumer_fix.py index 1099fce5f7c16c9f16f6afcb7dd43578db4facc4..aabc9c6a87a8539f2f6850ac4498e459f1ebef7a 100644 --- a/client/python/examples/test_consumer_fix.py +++ b/client/python/examples/test_consumer_fix.py @@ -13,7 +13,7 @@ from pathlib import Path import cv2 import numpy as np -from lerobot_arena_client.video import VideoConsumer +from transport_server_client.video import VideoConsumer # Setup logging logging.basicConfig( @@ -83,7 +83,7 @@ class FrameProcessor: logger.info(f" Data received: {mb_received:.2f} MB") except Exception as e: - logger.error(f"āŒ Error processing frame {self.frame_count}: {e}") + logger.exception(f"āŒ Error processing frame {self.frame_count}: {e}") async def test_consumer_fix(): @@ -177,7 +177,7 @@ async def test_consumer_fix(): return False except Exception as e: - logger.error(f"āŒ Test failed with error: {e}") + logger.exception(f"āŒ Test failed with error: {e}") import traceback traceback.print_exc() @@ -203,7 +203,7 @@ async def main(): logger.info("šŸ›‘ Test interrupted by user") return 1 except Exception as e: - logger.error(f"šŸ’„ Unexpected error: {e}") + logger.exception(f"šŸ’„ Unexpected error: {e}") return 1 diff --git a/client/python/examples/video_consumer_example.py b/client/python/examples/video_consumer_example.py index b35cf0d351c7f8c2d26f164e268b68e47c2f5860..7fd4248a86ac3a3706a240669a5e007db22568bb 100644 --- a/client/python/examples/video_consumer_example.py +++ b/client/python/examples/video_consumer_example.py @@ -13,7 +13,7 @@ from pathlib import Path import cv2 import numpy as np -from lerobot_arena_client.video import VideoConsumer +from transport_server_client.video import VideoConsumer # Setup logging logging.basicConfig( @@ -81,7 +81,7 @@ class VideoFrameHandler: self.last_log_time = current_time except Exception as e: - logger.error(f"āŒ Error handling frame {self.frame_count}: {e}") + logger.exception(f"āŒ Error handling frame {self.frame_count}: {e}") async def main(): @@ -171,7 +171,7 @@ async def main(): logger.warning("āš ļø No frames received - check if producer is active") except Exception as e: - logger.error(f"āŒ Consumer example failed: {e}") + logger.exception(f"āŒ Consumer example failed: {e}") import traceback traceback.print_exc() @@ -183,7 +183,7 @@ async def main(): await consumer.stop_receiving() logger.info("šŸ‘‹ Consumer stopped successfully") except Exception as e: - logger.error(f"Error during cleanup: {e}") + logger.exception(f"Error during cleanup: {e}") if __name__ == "__main__": @@ -192,7 +192,7 @@ if __name__ == "__main__": except KeyboardInterrupt: logger.info("šŸ‘‹ Goodbye!") except Exception as e: - logger.error(f"šŸ’„ Fatal error: {e}") + logger.exception(f"šŸ’„ Fatal error: {e}") import traceback traceback.print_exc() diff --git a/client/python/examples/video_producer_example.py b/client/python/examples/video_producer_example.py index 70478171428a2ace1a59b3e46babc960a6f69721..ff61088c7a1ff31d8494e75480e51f04c38664b0 100644 --- a/client/python/examples/video_producer_example.py +++ b/client/python/examples/video_producer_example.py @@ -13,7 +13,7 @@ import time import numpy as np # Import the video client -from lerobot_arena_client.video import ( +from transport_server_client.video import ( VideoProducer, create_producer_client, ) @@ -134,7 +134,7 @@ async def main(): await producer.stop_streaming() except Exception as e: - logger.error(f"āŒ Unexpected error: {e}") + logger.exception(f"āŒ Unexpected error: {e}") import traceback traceback.print_exc() @@ -184,7 +184,7 @@ async def camera_example(): logger.warning("āš ļø No cameras found") except Exception as e: - logger.error(f"āŒ Camera error: {e}") + logger.exception(f"āŒ Camera error: {e}") logger.info("šŸ’” Make sure your camera is available and not used by other apps") finally: if "producer" in locals(): @@ -211,7 +211,7 @@ async def screen_share_example(): await asyncio.sleep(20) except Exception as e: - logger.error(f"āŒ Screen share error: {e}") + logger.exception(f"āŒ Screen share error: {e}") finally: if "producer" in locals(): await producer.disconnect() diff --git a/client/python/pyproject.toml b/client/python/pyproject.toml index 8b444d70c1c700e3e334024eaeb715f0d39e563f..9bca5ffe7f30486e056e4dd777c2aefc5438823b 100644 --- a/client/python/pyproject.toml +++ b/client/python/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "robohub-transport-server-client" +name = "robothub_transport_server_client" version = "1.0.0" -description = "Python client for RoboHub transport server" +description = "Python client for robothub transport server" readme = "README.md" requires-python = ">=3.12" dependencies = [ diff --git a/client/python/src/transport_server_client/__init__.py b/client/python/src/transport_server_client/__init__.py index 34da538ff734036ee13edf19440897644cbf9835..bcfb5cf148efa374cd436a53d69de6fd701b8dc7 100644 --- a/client/python/src/transport_server_client/__init__.py +++ b/client/python/src/transport_server_client/__init__.py @@ -1,6 +1,6 @@ # Import video module -from lerobot_arena_client import video -from lerobot_arena_client.client import ( +from transport_server_client import video +from transport_server_client.client import ( RoboticsClientCore, RoboticsConsumer, RoboticsProducer, diff --git a/client/python/src/transport_server_client/__pycache__/__init__.cpython-312.pyc b/client/python/src/transport_server_client/__pycache__/__init__.cpython-312.pyc index 915868df11da239137fe764172d289df40145d46..ba73d70b5a770ecbd62a0a5439027b8e55d2544f 100644 Binary files a/client/python/src/transport_server_client/__pycache__/__init__.cpython-312.pyc and b/client/python/src/transport_server_client/__pycache__/__init__.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/__pycache__/client.cpython-312.pyc b/client/python/src/transport_server_client/__pycache__/client.cpython-312.pyc index 1bc74469f4ecfbfe32f029160dd745e11bc64642..86b9747b39e82fbfdffd09656d3ece3b56cc5aed 100644 Binary files a/client/python/src/transport_server_client/__pycache__/client.cpython-312.pyc and b/client/python/src/transport_server_client/__pycache__/client.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/__init__.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/__init__.cpython-312.pyc index 925592a3e07317e2cb2f7aa15034bee972c93514..4b9ae57e8cc485d465dea7fd74f9c79ef1712506 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/__init__.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/__init__.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/consumer.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/consumer.cpython-312.pyc index 5b4a007e05c660b5d0148558374aaf2738b8a450..906fe32193e9213ec73b30ed2fab5c0b804509f5 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/consumer.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/consumer.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/core.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/core.cpython-312.pyc index 54e792e45334e3eba0d8fb5967043d23eda5cf24..1356816dae703e122dfadc4f188f20b43e73707b 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/core.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/core.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/factory.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/factory.cpython-312.pyc index 4ec4dbf2ea7e512bd2b74e3b41c44674004b9fc2..cb19a0abc767a28dfe501e0c4f0366efba10d83b 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/factory.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/factory.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/producer.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/producer.cpython-312.pyc index 3c1c99e437defaa0b7285f4c4f2008f5e307d592..2c5747c2c673903d7752a699f264b3073287c8d7 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/producer.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/producer.cpython-312.pyc differ diff --git a/client/python/src/transport_server_client/video/__pycache__/types.cpython-312.pyc b/client/python/src/transport_server_client/video/__pycache__/types.cpython-312.pyc index 41a4824dc2059c7b699cf57626b8b50ee80e2145..7758744e1d8f351893a3a00d83c579e8557ee250 100644 Binary files a/client/python/src/transport_server_client/video/__pycache__/types.cpython-312.pyc and b/client/python/src/transport_server_client/video/__pycache__/types.cpython-312.pyc differ diff --git a/client/python/tests/conftest.py b/client/python/tests/conftest.py index ec15d0333fab7d3a4cbd3b2b633a55b7f21e4fdd..9e61d2bc0e7346faaa14862b4077a2d208accb2d 100644 --- a/client/python/tests/conftest.py +++ b/client/python/tests/conftest.py @@ -2,7 +2,7 @@ import asyncio import pytest import pytest_asyncio -from lerobot_arena_client import RoboticsConsumer, RoboticsProducer +from transport_server_client import RoboticsConsumer, RoboticsProducer # Default server URL for tests TEST_SERVER_URL = "http://localhost:8000" diff --git a/client/python/tests/test_consumer.py b/client/python/tests/test_consumer.py index bc9f1212cd5db3b9b31df625f1842d686bc01e42..a98ad70fbee75bad6405957d6a4d80fd3e22e116 100644 --- a/client/python/tests/test_consumer.py +++ b/client/python/tests/test_consumer.py @@ -1,7 +1,7 @@ import asyncio import pytest -from lerobot_arena_client import RoboticsConsumer +from transport_server_client import RoboticsConsumer class TestRoboticsConsumer: @@ -36,7 +36,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_get_state_sync(self, connected_consumer): """Test getting current state synchronously.""" - consumer, room_id = connected_consumer + consumer, _room_id = connected_consumer state = await consumer.get_state_sync() assert isinstance(state, dict) @@ -113,7 +113,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_consumer_receive_state_sync(self, producer_consumer_pair): """Test consumer receiving state sync from producer.""" - producer, consumer, room_id = producer_consumer_pair + producer, consumer, _room_id = producer_consumer_pair received_states = [] received_updates = [] @@ -143,7 +143,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_consumer_receive_joint_updates(self, producer_consumer_pair): """Test consumer receiving joint updates from producer.""" - producer, consumer, room_id = producer_consumer_pair + producer, consumer, _room_id = producer_consumer_pair received_updates = [] @@ -175,7 +175,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_consumer_multiple_updates(self, producer_consumer_pair): """Test consumer receiving multiple updates.""" - producer, consumer, room_id = producer_consumer_pair + producer, consumer, _room_id = producer_consumer_pair received_updates = [] @@ -204,7 +204,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_consumer_emergency_stop(self, producer_consumer_pair): """Test consumer receiving emergency stop.""" - producer, consumer, room_id = producer_consumer_pair + producer, consumer, _room_id = producer_consumer_pair received_errors = [] @@ -276,7 +276,7 @@ class TestRoboticsConsumer: @pytest.mark.asyncio async def test_consumer_state_after_producer_updates(self, producer_consumer_pair): """Test that consumer can get updated state after producer sends updates.""" - producer, consumer, room_id = producer_consumer_pair + producer, consumer, _room_id = producer_consumer_pair # Give some time for connection to stabilize await asyncio.sleep(0.1) diff --git a/client/python/tests/test_factory_functions.py b/client/python/tests/test_factory_functions.py index 2752e27af6ea1f40009e76249ffa12506be521e2..730c99d292b00af1e5edc79bb6a97833449a3717 100644 --- a/client/python/tests/test_factory_functions.py +++ b/client/python/tests/test_factory_functions.py @@ -1,7 +1,7 @@ import asyncio import pytest -from lerobot_arena_client import ( +from transport_server_client import ( RoboticsConsumer, RoboticsProducer, create_client, diff --git a/client/python/tests/test_integration.py b/client/python/tests/test_integration.py index 326b0b5e6b97c5eeabe933dca0020a48ccf6f19b..851257ac05834de22e5a5428b9cb91cf00385a6d 100644 --- a/client/python/tests/test_integration.py +++ b/client/python/tests/test_integration.py @@ -1,7 +1,7 @@ import asyncio import pytest -from lerobot_arena_client import ( +from transport_server_client import ( RoboticsProducer, create_consumer_client, create_producer_client, @@ -98,12 +98,8 @@ class TestIntegration: consumer1_updates = [] consumer2_updates = [] - consumer1.on_joint_update( - lambda joints: consumer1_updates.append(joints) - ) - consumer2.on_joint_update( - lambda joints: consumer2_updates.append(joints) - ) + consumer1.on_joint_update(consumer1_updates.append) + consumer2.on_joint_update(consumer2_updates.append) # Wait for connections await asyncio.sleep(0.2) @@ -150,8 +146,8 @@ class TestIntegration: consumer1_errors = [] consumer2_errors = [] - consumer1.on_error(lambda error: consumer1_errors.append(error)) - consumer2.on_error(lambda error: consumer2_errors.append(error)) + consumer1.on_error(consumer1_errors.append) + consumer2.on_error(consumer2_errors.append) # Wait for connections await asyncio.sleep(0.2) @@ -193,7 +189,7 @@ class TestIntegration: try: received_updates = [] - consumer.on_joint_update(lambda joints: received_updates.append(joints)) + consumer.on_joint_update(received_updates.append) # Create producer and connect producer = RoboticsProducer("http://localhost:8000") @@ -301,7 +297,7 @@ class TestIntegration: try: received_updates = [] - consumer.on_joint_update(lambda joints: received_updates.append(joints)) + consumer.on_joint_update(received_updates.append) # Wait for connection await asyncio.sleep(0.1) diff --git a/client/python/tests/test_producer.py b/client/python/tests/test_producer.py index 435912d82b137db8e6e05007810c03fc0aaa0766..bf976a1f48085ba55e9de896c12aea57ef6504a9 100644 --- a/client/python/tests/test_producer.py +++ b/client/python/tests/test_producer.py @@ -1,7 +1,7 @@ import asyncio import pytest -from lerobot_arena_client import RoboticsProducer +from transport_server_client import RoboticsProducer class TestRoboticsProducer: @@ -36,7 +36,7 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_send_joint_update(self, connected_producer): """Test sending joint updates.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer joints = [ {"name": "shoulder", "value": 45.0}, @@ -50,7 +50,7 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_send_state_sync(self, connected_producer): """Test sending state synchronization.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer state = {"shoulder": 45.0, "elbow": -20.0, "wrist": 10.0} @@ -60,7 +60,7 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_send_emergency_stop(self, connected_producer): """Test sending emergency stop.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer # Should not raise an exception await producer.send_emergency_stop("Test emergency stop") @@ -69,7 +69,7 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_send_heartbeat(self, connected_producer): """Test sending heartbeat.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer # Should not raise an exception await producer.send_heartbeat() @@ -185,12 +185,10 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_large_joint_update(self, connected_producer): """Test sending large joint update.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer # Create a large joint update - joints = [] - for i in range(100): - joints.append({"name": f"joint_{i}", "value": float(i)}) + joints = [{"name": f"joint_{i}", "value": float(i)} for i in range(100)] # Should handle large updates without issue await producer.send_joint_update(joints) @@ -198,7 +196,7 @@ class TestRoboticsProducer: @pytest.mark.asyncio async def test_rapid_updates(self, connected_producer): """Test sending rapid joint updates.""" - producer, room_id = connected_producer + producer, _room_id = connected_producer # Send multiple rapid updates for i in range(10): diff --git a/client/python/tests/test_rest_api.py b/client/python/tests/test_rest_api.py index b523e669a20dc57b567ca1dfe3e46d64fc9ed2ee..ac4452ccddac6733e4e143a3109bd2f76d216d8d 100644 --- a/client/python/tests/test_rest_api.py +++ b/client/python/tests/test_rest_api.py @@ -1,6 +1,6 @@ import pytest import pytest_asyncio -from lerobot_arena_client import RoboticsProducer +from transport_server_client import RoboticsProducer @pytest_asyncio.fixture diff --git a/client/python/tests/test_video_client.py b/client/python/tests/test_video_client.py index 782149cea6d4ed8fcb13154cff81a9d87086c290..9062afe65d6994d017faf68f124efef2d73c9e23 100644 --- a/client/python/tests/test_video_client.py +++ b/client/python/tests/test_video_client.py @@ -10,7 +10,7 @@ import logging import numpy as np import pytest -from lerobot_arena_client.video import ( +from transport_server_client.video import ( CustomVideoTrack, ParticipantRole, Resolution, @@ -162,15 +162,13 @@ class TestVideoClientIntegration: # (We can't actually connect without a server) try: - producer = await create_producer_client("http://localhost:8000") + await create_producer_client("http://localhost:8000") except Exception: # Expected to fail without server pass try: - consumer = await create_consumer_client( - "test-room", "http://localhost:8000" - ) + await create_consumer_client("test-room", "http://localhost:8000") except Exception: # Expected to fail without server pass diff --git a/demo/README.md b/demo/README.md index c11b8709e2be0d35717651394b50d8edce77e607..d5338e3813e1b027503d93eb170aa6f47c6014d8 100644 --- a/demo/README.md +++ b/demo/README.md @@ -153,7 +153,7 @@ bun run format The demo uses the local `lerobot-arena-client` package: ```typescript -import { robotics } from '@robohub/transport-server-client'; +import { robotics } from '@robothub/transport-server-client'; // Create clients const producer = new robotics.RoboticsProducer('http://localhost:8000'); diff --git a/demo/bun.lock b/demo/bun.lock index a854aa4a65ae21ee2b4469361c82210903007b75..ea7be8f8d2b0568e9ad308ad48d1eab23789d61f 100644 --- a/demo/bun.lock +++ b/demo/bun.lock @@ -4,7 +4,7 @@ "": { "name": "demo", "dependencies": { - "@robohub/transport-server-client": "https://gitpkg.now.sh/julien-blanchon/RoboHub/services/transport-server/client/js?main", + "@robothub/transport-server-client": "https://gitpkg.now.sh/julien-blanchon/robothub/services/transport-server/client/js?main", }, "devDependencies": { "@eslint/compat": "^1.2.5", @@ -130,7 +130,7 @@ "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], - "@robohub/transport-server-client": ["@robohub/transport-server-client@https://gitpkg.now.sh/julien-blanchon/RoboHub/services/transport-server/client/js?main", { "dependencies": { "eventemitter3": "^5.0.1" }, "peerDependencies": { "typescript": ">=5.0.0" } }], + "@robothub/transport-server-client": ["@robothub/transport-server-client@https://gitpkg.now.sh/julien-blanchon/robothub/services/transport-server/client/js?main", { "dependencies": { "eventemitter3": "^5.0.1" }, "peerDependencies": { "typescript": ">=5.0.0" } }], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.41.1", "", { "os": "android", "cpu": "arm" }, "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw=="], diff --git a/demo/package.json b/demo/package.json index d0a8fb6e90a988d8e730b917a985d83d7b686f81..bb3b5fbe711f2d615b1ba6af03f00a4ad4ca9e0a 100644 --- a/demo/package.json +++ b/demo/package.json @@ -35,6 +35,6 @@ "vite": "^6.2.6" }, "dependencies": { - "@robohub/transport-server-client": "file:../client/js" + "@robothub/transport-server-client": "file:../client/js" } } diff --git a/demo/src/routes/+page.svelte b/demo/src/routes/+page.svelte index b9d46c45d70c59ecbc768b62b1489fab18ecb2aa..db1286596ca044fd6a95526602f6f76df565ff52 100644 --- a/demo/src/routes/+page.svelte +++ b/demo/src/routes/+page.svelte @@ -1,7 +1,7 @@