diff --git a/.github/wordlist.txt b/.github/wordlist.txt
index 36525168..e693bf58 100644
--- a/.github/wordlist.txt
+++ b/.github/wordlist.txt
@@ -46,6 +46,7 @@ npm
deps
backend
Backend
+Vite
dropdown
cryptographically
SHA
@@ -89,3 +90,8 @@ socio
sexualized
www
faq
+sanitization
+Sanitization
+JOINs
+subqueries
+subquery
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index dae0e66e..f7961925 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -10,7 +10,7 @@
name: 'Dependency review'
on:
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "staging" ]
# If using a dependency submission action in this workflow this permission will need to be set to:
#
diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
deleted file mode 100644
index 898d7284..00000000
--- a/.github/workflows/e2e-tests.yml
+++ /dev/null
@@ -1,90 +0,0 @@
-name: E2E Tests
-
-on:
- push:
- branches: [ main, staging ]
- pull_request:
- branches: [ main, staging ]
-
-permissions:
- contents: read
-
-jobs:
- e2e-tests:
- runs-on: ubuntu-latest
-
- services:
- falkordb:
- image: falkordb/falkordb:latest
- ports:
- - 6379:6379
- options: >-
- --health-cmd "redis-cli ping"
- --health-interval 10s
- --health-timeout 5s
- --health-retries 5
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.12'
-
- - name: Install pipenv
- run: |
- python -m pip install --upgrade pip
- pip install pipenv
-
- - name: Set up Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '22'
-
- - name: Install dependencies
- run: |
- make install
-
- - name: Setup development environment
- run: |
- make setup-dev
-
- - name: Create test environment file
- run: |
- cp .env.example .env
- echo "FALKORDB_HOST=localhost" >> .env
- echo "FALKORDB_PORT=6379" >> .env
- echo "FLASK_SECRET_KEY=test-secret-key-for-ci" >> .env
- echo "FLASK_DEBUG=False" >> .env
-
- - name: Wait for FalkorDB
- run: |
- until docker exec "$(docker ps -q --filter ancestor=falkordb/falkordb:latest)" redis-cli ping; do
- echo "Waiting for FalkorDB..."
- sleep 2
- done
-
- - name: Run E2E tests
- run: |
- make test-e2e
- env:
- CI: true
-
- - name: Upload test artifacts
- uses: actions/upload-artifact@v4
- if: failure()
- with:
- name: playwright-report
- path: |
- test-results/
- playwright-report/
- retention-days: 30
-
- - name: Upload screenshots
- uses: actions/upload-artifact@v4
- if: failure()
- with:
- name: screenshots
- path: tests/e2e/screenshots/
- retention-days: 30
diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml
new file mode 100644
index 00000000..856b003e
--- /dev/null
+++ b/.github/workflows/playwright.yml
@@ -0,0 +1,168 @@
+name: Playwright Tests
+on:
+ push:
+ branches: [ main, staging ]
+ pull_request:
+ branches: [ main, staging ]
+
+permissions:
+ contents: read
+
+env:
+ PYTHON_VERSION: '3.12'
+ NODE_VERSION: 'lts/*'
+
+
+jobs:
+ test:
+ timeout-minutes: 60
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ # Setup Python
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+
+ # Setup Node.js
+ - uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ # Install pipenv
+ - name: Install pipenv
+ run: pip install pipenv
+
+ # Install Python dependencies
+ - name: Install Python dependencies
+ run: pipenv sync --dev
+
+ # Install Node dependencies (root - for Playwright)
+ - name: Install root dependencies
+ run: npm ci
+
+ # Install Node dependencies (frontend)
+ - name: Install frontend dependencies
+ run: npm ci
+ working-directory: ./app
+
+ # Build frontend
+ - name: Build frontend
+ run: npm run build
+ working-directory: ./app
+
+ # Start Docker Compose services (test databases)
+ - name: Start test databases
+ run: |
+ docker compose -f e2e/docker-compose.test.yml up -d
+ # Wait for databases to be healthy
+ echo "Waiting for databases to be ready..."
+ sleep 20
+ docker ps -a
+ # Verify all containers are running
+ docker compose -f e2e/docker-compose.test.yml ps
+
+ # Start FalkorDB (Redis graph database)
+ - name: Start FalkorDB
+ run: |
+ docker run -d --name falkordb-test -p 6379:6379 falkordb/falkordb:latest
+ echo "Waiting for FalkorDB to be ready..."
+ # Wait for FalkorDB to accept connections and be fully initialized
+ for i in {1..30}; do
+ if docker exec falkordb-test redis-cli PING > /dev/null 2>&1; then
+ # Test that FalkorDB graph commands work
+ if docker exec falkordb-test redis-cli GRAPH.LIST > /dev/null 2>&1; then
+ echo "FalkorDB graph module loaded, testing vector index creation..."
+ # Test creating a graph with vector index (the actual operation that fails)
+ if docker exec falkordb-test redis-cli GRAPH.QUERY test_graph "CREATE VECTOR INDEX FOR (n:Test) ON (n.embedding)" > /dev/null 2>&1; then
+ # Clean up test graph
+ docker exec falkordb-test redis-cli GRAPH.DELETE test_graph > /dev/null 2>&1 || true
+ echo "FalkorDB is fully ready with vector index support!"
+ # Extra wait to ensure complete initialization
+ sleep 5
+ break
+ fi
+ fi
+ fi
+ echo "Waiting for FalkorDB initialization... attempt $i/30"
+ sleep 1
+ done
+ # Verify FalkorDB is accessible from host
+ echo "Testing FalkorDB connectivity from host..."
+ docker ps -a
+
+ # Start the FastAPI application
+ - name: Start FastAPI application
+ run: |
+ # Start server in background directly with pipenv
+ pipenv run uvicorn api.index:app --host localhost --port 5000 > /tmp/uvicorn.log 2>&1 &
+ UVICORN_PID=$!
+ echo "Started server with PID: $UVICORN_PID"
+ # Wait for app to start
+ echo "Waiting for application to start..."
+ for i in {1..30}; do
+ if curl -f http://localhost:5000/ 2>/dev/null; then
+ echo "Application started successfully!"
+ break
+ fi
+ echo "Waiting... attempt $i/30"
+ sleep 1
+ if [ $i -eq 30 ]; then
+ echo "Failed to start application after 30 seconds"
+ echo "=== Server logs ==="
+ cat /tmp/uvicorn.log
+ exit 1
+ fi
+ done
+ env:
+ PYTHONUNBUFFERED: 1
+ FASTAPI_SECRET_KEY: test-secret-key-for-ci
+ APP_ENV: development
+ FASTAPI_DEBUG: False
+ FALKORDB_URL: redis://localhost:6379
+ DISABLE_MCP: true
+ # Azure OpenAI API keys - required for database schema analysis
+ AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }}
+ AZURE_API_BASE: ${{ secrets.AZURE_API_BASE }}
+ AZURE_API_VERSION: ${{ secrets.AZURE_API_VERSION }}
+
+ # Install Playwright browsers
+ - name: Install Playwright Browsers
+ run: npx playwright install --with-deps chromium firefox
+
+ # Create auth directory for storage state
+ - name: Create auth directory
+ run: mkdir -p e2e/.auth
+
+ # Run Playwright tests
+ - name: Run Playwright tests
+ run: npx playwright test --reporter=list
+ env:
+ CI: true
+
+ # Upload test results on failure
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
+
+ # Upload test screenshots on failure
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: test-results
+ path: test-results/
+ retention-days: 30
+
+ # Cleanup - Stop all containers
+ - name: Cleanup Docker containers
+ if: always()
+ run: |
+ docker compose -f e2e/docker-compose.test.yml down -v || true
+ docker stop falkordb-test || true
+ docker rm falkordb-test || true
diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml
index 779cb836..f20d5aa3 100644
--- a/.github/workflows/spellcheck.yml
+++ b/.github/workflows/spellcheck.yml
@@ -3,9 +3,9 @@ permissions:
contents: read
on:
push:
- branches: [main]
+ branches: [main, staging]
pull_request:
- branches: [main]
+ branches: [main, staging]
jobs:
spellcheck:
runs-on: ubuntu-latest
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 0b769636..5d4b8b01 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -47,6 +47,10 @@ jobs:
npm --version || true
(cd app && npm ci)
+ - name: Build frontend
+ run: |
+ cd app && npm run build
+
- name: Create test environment file
run: |
cp .env.example .env
@@ -60,67 +64,3 @@ jobs:
- name: Run lint
run: |
make lint
-
- e2e-tests:
- runs-on: ubuntu-latest
-
- services:
- falkordb:
- image: falkordb/falkordb:latest
- ports:
- - 6379:6379
- options: >-
- --health-cmd "redis-cli ping"
- --health-interval 10s
- --health-timeout 5s
- --health-retries 5
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.12'
-
- - name: Install pipenv
- run: |
- python -m pip install --upgrade pip
- pip install pipenv
-
- - name: Install dependencies
- run: |
- pipenv sync --dev
-
- - name: Install Playwright browsers
- run: |
- pipenv run playwright install chromium
- pipenv run playwright install-deps
-
- - name: Create test environment file
- run: |
- cp .env.example .env
- echo "FALKORDB_HOST=localhost" >> .env
- echo "FALKORDB_PORT=6379" >> .env
- echo "FASTAPI_SECRET_KEY=test-secret-key-for-ci" >> .env
- echo "FASTAPI_DEBUG=False" >> .env
-
- - name: Wait for FalkorDB
- run: |
- timeout 60 bash -c 'until docker exec "$(docker ps -q --filter ancestor=falkordb/falkordb:latest)" redis-cli ping; do sleep 2; done'
-
- - name: Run E2E tests
- run: |
- pipenv run pytest tests/e2e/ --browser chromium
- env:
- CI: true
-
- - name: Upload test artifacts
- uses: actions/upload-artifact@v4
- if: failure()
- with:
- name: playwright-report
- path: |
- test-results/
- playwright-report/
- retention-days: 30
diff --git a/.gitignore b/.gitignore
index 68e22653..a9e199cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,18 @@ tests/e2e/screenshots/*.png
tmp_*
*.d.ts
node_modules/
+
+# Frontend build outputs
/app/public/js/*
+/app/dist/
+
.jinja_cache/
demo_tokens.py
+.DS_Store
+
+# Playwright
+/playwright-report/
+/blob-report/
+/playwright/.cache/
+/playwright/.auth/
+e2e/.auth/
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
index 4c425c56..fbf6eddf 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,11 +4,11 @@ verify_ssl = true
name = "pypi"
[packages]
-fastapi = "~=0.118.0"
-uvicorn = "~=0.37.0"
-litellm = "~=1.77.3"
-falkordb = "~=1.2.0"
-psycopg2-binary = "~=2.9.9"
+fastapi = "~=0.124.0"
+uvicorn = "~=0.38.0"
+litellm = "~=1.80.9"
+falkordb = "~=1.2.2"
+psycopg2-binary = "~=2.9.11"
pymysql = "~=1.1.0"
authlib = "~=1.6.4"
itsdangerous = "~=2.2.0"
@@ -17,12 +17,12 @@ tqdm = "~=4.67.1"
python-multipart = "~=0.0.10"
jinja2 = "~=3.1.4"
graphiti-core = {ref = "staging", git = "git+https://github.com/FalkorDB/graphiti.git"}
-fastmcp = "~=2.12.4"
+fastmcp = ">=2.13.1"
[dev-packages]
pytest = "~=8.4.2"
-pylint = "~=3.3.4"
-playwright = "~=1.55.0"
+pylint = "~=4.0.3"
+playwright = "~=1.56.0"
pytest-playwright = "~=0.7.1"
pytest-asyncio = "~=1.2.0"
diff --git a/Pipfile.lock b/Pipfile.lock
index b74b2fbb..a4af8f76 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "068fba0bf4eb3284bbc72a94e3afe6f34ecb3a8419621fef65c2e40ba9ae157b"
+ "sha256": "7c4039301ea5ce3f6417f744fff34c2fff96953ea26ffe25675357157b33fbdd"
},
"pipfile-spec": 6,
"requires": {
@@ -26,129 +26,129 @@
},
"aiohttp": {
"hashes": [
- "sha256:00243e51f16f6ec0fb021659d4af92f675f3cf9f9b39efd142aa3ad641d8d1e6",
- "sha256:00fdfe370cffede3163ba9d3f190b32c0cfc8c774f6f67395683d7b0e48cdb8a",
- "sha256:019dbef24fe28ce2301419dd63a2b97250d9760ca63ee2976c2da2e3f182f82e",
- "sha256:052bcdd80c1c54b8a18a9ea0cd5e36f473dc8e38d51b804cea34841f677a9971",
- "sha256:059978d2fddc462e9211362cbc8446747ecd930537fa559d3d25c256f032ff54",
- "sha256:0a2be20eb23888df130214b91c262a90e2de1553d6fb7de9e9010cec994c0ff2",
- "sha256:0f1338b61ea66f4757a0544ed8a02ccbf60e38d9cfb3225888888dd4475ebb96",
- "sha256:0f19f7798996d4458c669bd770504f710014926e9970f4729cf55853ae200469",
- "sha256:0f735e680c323ee7e9ef8e2ea26425c7dbc2ede0086fa83ce9d7ccab8a089f26",
- "sha256:10b3f01d5aeb632adaaf39c5e93f040a550464a768d54c514050c635adcbb9d0",
- "sha256:12f5d820fadc5848d4559ea838aef733cf37ed2a1103bba148ac2f5547c14c29",
- "sha256:19ba8625fa69523627b67f7e9901b587a4952470f68814d79cdc5bc460e9b885",
- "sha256:19bb08e56f57c215e9572cd65cb6f8097804412c54081d933997ddde3e5ac579",
- "sha256:1c272a9a18a5ecc48a7101882230046b83023bb2a662050ecb9bfcb28d9ab53a",
- "sha256:1ccedfe280e804d9a9d7fe8b8c4309d28e364b77f40309c86596baa754af50b1",
- "sha256:1f164699a060c0b3616459d13c1464a981fddf36f892f0a5027cbd45121fb14b",
- "sha256:2117be9883501eaf95503bd313eb4c7a23d567edd44014ba15835a1e9ec6d852",
- "sha256:222c828243b4789d79a706a876910f656fad4381661691220ba57b2ab4547865",
- "sha256:23ca762140159417a6bbc959ca1927f6949711851e56f2181ddfe8d63512b5ad",
- "sha256:240f99f88a9a6beb53ebadac79a2e3417247aa756202ed234b1dbae13d248092",
- "sha256:2c4aeaedd20771b7b4bcdf0ae791904445df6d856c02fc51d809d12d17cffdc7",
- "sha256:2d71ca30257ce756e37a6078b1dff2d9475fee13609ad831eac9a6531bea903b",
- "sha256:2e66c57416352f36bf98f6641ddadd47c93740a22af7150d3e9a1ef6e983f9a8",
- "sha256:2f9d9ea547618d907f2ee6670c9a951f059c5994e4b6de8dcf7d9747b420c820",
- "sha256:2fd35177dc483ae702f07b86c782f4f4b100a8ce4e7c5778cea016979023d9fd",
- "sha256:3194b8cab8dbc882f37c13ef1262e0a3d62064fa97533d3aa124771f7bf1ecee",
- "sha256:34d8af6391c5f2e69749d7f037b614b8c5c42093c251f336bdbfa4b03c57d6c4",
- "sha256:378dbc57dd8cf341ce243f13fa1fa5394d68e2e02c15cd5f28eae35a70ec7f67",
- "sha256:3b1eb9871cbe43b6ca6fac3544682971539d8a1d229e6babe43446279679609d",
- "sha256:3b3bdc89413117b40cc39baae08fd09cbdeb839d421c4e7dce6a34f6b54b3ac1",
- "sha256:3b64f22fbb6dcd5663de5ef2d847a5638646ef99112503e6f7704bdecb0d1c4d",
- "sha256:3c11fa5dd2ef773a8a5a6daa40243d83b450915992eab021789498dc87acc114",
- "sha256:3e6a38366f7f0d0f6ed7a1198055150c52fda552b107dad4785c0852ad7685d1",
- "sha256:3e77a729df23be2116acc4e9de2767d8e92445fbca68886dd991dc912f473755",
- "sha256:469167d5372f5bb3aedff4fc53035d593884fff2617a75317740e885acd48b04",
- "sha256:4696665b2713021c6eba3e2b882a86013763b442577fe5d2056a42111e732eca",
- "sha256:474cade59a447cb4019c0dce9f0434bf835fb558ea932f62c686fe07fe6db6a1",
- "sha256:475bd56492ce5f4cffe32b5533c6533ee0c406d1d0e6924879f83adcf51da0ae",
- "sha256:48fcdd5bc771cbbab8ccc9588b8b6447f6a30f9fe00898b1a5107098e00d6793",
- "sha256:49ce7525853a981fc35d380aa2353536a01a9ec1b30979ea4e35966316cace7e",
- "sha256:4aa995b9156ae499393d949a456a7ab0b994a8241a96db73a3b73c7a090eff6a",
- "sha256:4af1f8877ca46ecdd0bc0d4a6b66d4b2bddc84a79e2e8366bc0d5308e76bceb8",
- "sha256:4b14bfae90598d331b5061fd15a7c290ea0c15b34aeb1cf620464bb5ec02a602",
- "sha256:4df1984c8804ed336089e88ac81a9417b1fd0db7c6f867c50a9264488797e778",
- "sha256:5004d727499ecb95f7c9147dd0bfc5b5670f71d355f0bd26d7af2d3af8e07d2f",
- "sha256:55ca0e95a3905f62f00900255ed807c580775174252999286f283e646d675a49",
- "sha256:564b36512a7da3b386143c611867e3f7cfb249300a1bf60889bd9985da67ab77",
- "sha256:564be41e85318403fdb176e9e5b3e852d528392f42f2c1d1efcbeeed481126d7",
- "sha256:56f7d230ec66e799fbfd8350e9544f8a45a4353f1cf40c1fea74c1780f555b8f",
- "sha256:582770f82513419512da096e8df21ca44f86a2e56e25dc93c5ab4df0fe065bf0",
- "sha256:5ae3a19949a27982c7425a7a5a963c1268fdbabf0be15ab59448cbcf0f992519",
- "sha256:5b8a5557d5af3f4e3add52a58c4cf2b8e6e59fc56b261768866f5337872d596d",
- "sha256:5bf635c3476f4119b940cc8d94ad454cbe0c377e61b4527f0192aabeac1e9370",
- "sha256:62a3cddf8d9a2eae1f79585fa81d32e13d0c509bb9e7ad47d33c83b45a944df7",
- "sha256:62d8a0adcdaf62ee56bfb37737153251ac8e4b27845b3ca065862fb01d99e247",
- "sha256:62fd54f3e6f17976962ba67f911d62723c760a69d54f5d7b74c3ceb1a4e9ef8d",
- "sha256:6475e42ef92717a678bfbf50885a682bb360a6f9c8819fb1a388d98198fdcb80",
- "sha256:682d2e434ff2f1108314ff7f056ce44e457f12dbed0249b24e106e385cf154b9",
- "sha256:6a51839f778b0e283b43cd82bb17f1835ee2cc1bf1101765e90ae886e53e751c",
- "sha256:6b4174fcec98601f0cfdf308ee29a6ae53c55f14359e848dab4e94009112ee7d",
- "sha256:6b9697d15231aeaed4786f090c9c8bc3ab5f0e0a6da1e76c135a310def271020",
- "sha256:6c333a2385d2a6298265f4b3e960590f787311b87f6b5e6e21bb8375914ef504",
- "sha256:703ad3f742fc81e543638a7bebddd35acadaa0004a5e00535e795f4b6f2c25ca",
- "sha256:72714919ed9b90f030f761c20670e529c4af96c31bd000917dd0c9afd1afb731",
- "sha256:76484ba17b2832776581b7ab466d094e48eba74cb65a60aea20154dae485e8bd",
- "sha256:77da5305a410910218b99f2a963092f4277d8a9c1f429c1ff1b026d1826bd0b6",
- "sha256:7897298b3eedc790257fef8a6ec582ca04e9dbe568ba4a9a890913b925b8ea21",
- "sha256:7972c82bed87d7bd8e374b60a6b6e816d75ba4f7c2627c2d14eed216e62738e1",
- "sha256:7c20db99da682f9180fa5195c90b80b159632fb611e8dbccdd99ba0be0970620",
- "sha256:7c2c4c9ce834801651f81d6760d0a51035b8b239f58f298de25162fcf6f8bb64",
- "sha256:7ddedba3d0043349edc79df3dc2da49c72b06d59a45a42c1c8d987e6b8d175b8",
- "sha256:84912962071087286333f70569362e10793f73f45c48854e6859df11001eb2d3",
- "sha256:90b570f1a146181c3d6ae8f755de66227ded49d30d050479b5ae07710f7894c5",
- "sha256:97891a23d7fd4e1afe9c2f4473e04595e4acb18e4733b910b6577b74e7e21985",
- "sha256:990a53b9d6a30b2878789e490758e568b12b4a7fb2527d0c89deb9650b0e5813",
- "sha256:99a303ad960747c33b65b1cb65d01a62ac73fa39b72f08a2e1efa832529b01ed",
- "sha256:99eb94e97a42367fef5fc11e28cb2362809d3e70837f6e60557816c7106e2e20",
- "sha256:a1c20c26af48aea984f63f96e5d7af7567c32cb527e33b60a0ef0a6313cf8b03",
- "sha256:a4676b978a9711531e7cea499d4cdc0794c617a1c0579310ab46c9fdf5877702",
- "sha256:a4dc0b83e25267f42ef065ea57653de4365b56d7bc4e4cfc94fabe56998f8ee6",
- "sha256:a533873a7a4ec2270fb362ee5a0d3b98752e4e1dc9042b257cd54545a96bd8ed",
- "sha256:a6d9487b9471ec36b0faedf52228cd732e89be0a2bbd649af890b5e2ce422353",
- "sha256:a921edbe971aade1bf45bcbb3494e30ba6863a5c78f28be992c42de980fd9108",
- "sha256:a9f3546b503975a69b547c9fd1582cad10ede1ce6f3e313a2f547c73a3d7814f",
- "sha256:aab715b1a0c37f7f11f9f1f579c6fbaa51ef569e47e3c0a4644fba46077a9409",
- "sha256:ac90cfab65bc281d6752f22db5fa90419e33220af4b4fa53b51f5948f414c0e7",
- "sha256:b3a8e6a2058a0240cfde542b641d0e78b594311bc1a710cbcb2e1841417d5cb3",
- "sha256:bb34001fc1f05f6b323e02c278090c07a47645caae3aa77ed7ed8a3ce6abcce9",
- "sha256:bc95c49853cd29613e4fe4ff96d73068ff89b89d61e53988442e127e8da8e7ba",
- "sha256:bfe824d6707a5dc3c5676685f624bc0c63c40d79dc0239a7fd6c034b98c25ebe",
- "sha256:c32ada0abb4bc94c30be2b681c42f058ab104d048da6f0148280a51ce98add8c",
- "sha256:c417f8c2e1137775569297c584a8a7144e5d1237789eae56af4faf1894a0b861",
- "sha256:c811612711e01b901e18964b3e5dec0d35525150f5f3f85d0aee2935f059910a",
- "sha256:ca69ec38adf5cadcc21d0b25e2144f6a25b7db7bea7e730bac25075bc305eff0",
- "sha256:ca8313cb852af788c78d5afdea24c40172cbfff8b35e58b407467732fde20390",
- "sha256:cc6d5fc5edbfb8041d9607f6a417997fa4d02de78284d386bea7ab767b5ea4f3",
- "sha256:cd45eb70eca63f41bb156b7dffbe1a7760153b69892d923bdb79a74099e2ed90",
- "sha256:ce887c5e54411d607ee0959cac15bb31d506d86a9bcaddf0b7e9d63325a7a802",
- "sha256:cf2b60b65df05b6b2fa0d887f2189991a0dbf44a0dd18359001dc8fcdb7f1163",
- "sha256:cf7a4b976da219e726d0043fc94ae8169c0dba1d3a059b3c1e2c964bafc5a77d",
- "sha256:cf8b0870047900eb1f17f453b4b3953b8ffbf203ef56c2f346780ff930a4d430",
- "sha256:cfe6285ef99e7ee51cef20609be2bc1dd0e8446462b71c9db8bb296ba632810a",
- "sha256:d169c47e40c911f728439da853b6fd06da83761012e6e76f11cb62cddae7282b",
- "sha256:d812838c109757a11354a161c95708ae4199c4fd4d82b90959b20914c1d097f6",
- "sha256:d871f6a30d43e32fc9252dc7b9febe1a042b3ff3908aa83868d7cf7c9579a59b",
- "sha256:dea698b64235d053def7d2f08af9302a69fcd760d1c7bd9988fd5d3b6157e657",
- "sha256:df46d9a3d78ec19b495b1107bf26e4fcf97c900279901f4f4819ac5bb2a02a4c",
- "sha256:e04ab827ec4f775817736b20cdc8350f40327f9b598dec4e18c9ffdcbea88a93",
- "sha256:e68c0076052dd911a81d3acc4ef2911cc4ef65bf7cadbfbc8ae762da24da858f",
- "sha256:e88ab34826d6eeb6c67e6e92400b9ec653faf5092a35f07465f44c9f1c429f82",
- "sha256:ea01ffbe23df53ece0c8732d1585b3d6079bb8c9ee14f3745daf000051415a31",
- "sha256:ea6df292013c9f050cbf3f93eee9953d6e5acd9e64a0bf4ca16404bfd7aa9bcc",
- "sha256:ee433e594d7948e760b5c2a78cc06ac219df33b0848793cf9513d486a9f90a52",
- "sha256:eeea0cdd2f687e210c8f605f322d7b0300ba55145014a5dbe98bd4be6fff1f6c",
- "sha256:f27b7488144eb5dd9151cf839b195edd1569629d90ace4c5b6b18e4e75d1e63a",
- "sha256:f84b53326abf8e56ebc28a35cebf4a0f396a13a76300f500ab11fe0573bf0b52",
- "sha256:f8d877aa60d80715b2afc565f0f1aea66565824c229a2d065b31670e09fed6d7",
- "sha256:f8e38d55ca36c15f36d814ea414ecb2401d860de177c49f84a327a25b3ee752b",
- "sha256:f91e8f9053a07177868e813656ec57599cd2a63238844393cd01bd69c2e40147",
- "sha256:fcc425fb6fd2a00c6d91c85d084c6b75a61bc8bc12159d08e17c5711df6c5ba4"
+ "sha256:04c3971421576ed24c191f610052bcb2f059e395bc2489dd99e397f9bc466329",
+ "sha256:05c4dd3c48fb5f15db31f57eb35374cb0c09afdde532e7fb70a75aede0ed30f6",
+ "sha256:070599407f4954021509193404c4ac53153525a19531051661440644728ba9a7",
+ "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254",
+ "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742",
+ "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad",
+ "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906",
+ "sha256:0e87dff73f46e969af38ab3f7cb75316a7c944e2e574ff7c933bc01b10def7f5",
+ "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811",
+ "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded",
+ "sha256:1f9b2c2d4b9d958b1f9ae0c984ec1dd6b6689e15c75045be8ccb4011426268ca",
+ "sha256:204ffff2426c25dfda401ba08da85f9c59525cdc42bda26660463dd1cbcfec6f",
+ "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98",
+ "sha256:20db2d67985d71ca033443a1ba2001c4b5693fe09b0e29f6d9358a99d4d62a8a",
+ "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a",
+ "sha256:2372b15a5f62ed37789a6b383ff7344fc5b9f243999b0cd9b629d8bc5f5b4155",
+ "sha256:23ad365e30108c422d0b4428cf271156dd56790f6dd50d770b8e360e6c5ab2e6",
+ "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e",
+ "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b",
+ "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e",
+ "sha256:29562998ec66f988d49fb83c9b01694fa927186b781463f376c5845c121e4e0b",
+ "sha256:2adebd4577724dcae085665f294cc57c8701ddd4d26140504db622b8d566d7aa",
+ "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf",
+ "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5",
+ "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc",
+ "sha256:364f55663085d658b8462a1c3f17b2b84a5c2e1ba858e1b79bff7b2e24ad1514",
+ "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f",
+ "sha256:3a92cf4b9bea33e15ecbaa5c59921be0f23222608143d025c989924f7e3e0c07",
+ "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca",
+ "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e",
+ "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9",
+ "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0",
+ "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782",
+ "sha256:4dd3db9d0f4ebca1d887d76f7cdbcd1116ac0d05a9221b9dad82c64a62578c4d",
+ "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213",
+ "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293",
+ "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead",
+ "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04",
+ "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61",
+ "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3",
+ "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4",
+ "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b",
+ "sha256:6315fb6977f1d0dd41a107c527fee2ed5ab0550b7d885bc15fee20ccb17891da",
+ "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6",
+ "sha256:6c00dbcf5f0d88796151e264a8eab23de2997c9303dd7c0bf622e23b24d3ce22",
+ "sha256:6e7352512f763f760baaed2637055c49134fd1d35b37c2dedfac35bfe5cf8725",
+ "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be",
+ "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661",
+ "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e",
+ "sha256:7c3a50345635a02db61792c85bb86daffac05330f6473d524f1a4e3ef9d0046d",
+ "sha256:7fbdf5ad6084f1940ce88933de34b62358d0f4a0b6ec097362dcd3e5a65a4989",
+ "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c",
+ "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec",
+ "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45",
+ "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a",
+ "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8",
+ "sha256:8b2f1414f6a1e0683f212ec80e813f4abef94c739fd090b66c9adf9d2a05feac",
+ "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694",
+ "sha256:939ced4a7add92296b0ad38892ce62b98c619288a081170695c6babe4f50e636",
+ "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169",
+ "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a",
+ "sha256:960c2fc686ba27b535f9fd2b52d87ecd7e4fd1cf877f6a5cba8afb5b4a8bd204",
+ "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a",
+ "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab",
+ "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae",
+ "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948",
+ "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8",
+ "sha256:9c705601e16c03466cb72011bd1af55d68fa65b045356d8f96c216e5f6db0fa5",
+ "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30",
+ "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16",
+ "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693",
+ "sha256:9f377d0a924e5cc94dc620bc6366fc3e889586a7f18b748901cf016c916e2084",
+ "sha256:a09a6d073fb5789456545bdee2474d14395792faa0527887f2f4ec1a486a59d3",
+ "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4",
+ "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592",
+ "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49",
+ "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a",
+ "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e",
+ "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4",
+ "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9",
+ "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b",
+ "sha256:b395bbca716c38bef3c764f187860e88c724b342c26275bc03e906142fc5964f",
+ "sha256:b59d13c443f8e049d9e94099c7e412e34610f1f49be0f230ec656a10692a5802",
+ "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb",
+ "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b",
+ "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011",
+ "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3",
+ "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7",
+ "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c",
+ "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734",
+ "sha256:d7bc4b7f9c4921eba72677cd9fedd2308f4a4ca3e12fab58935295ad9ea98700",
+ "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d",
+ "sha256:dacd50501cd017f8cccb328da0c90823511d70d24a323196826d923aad865901",
+ "sha256:e036a3a645fe92309ec34b918394bb377950cbb43039a97edae6c08db64b23e2",
+ "sha256:e09a0a06348a2dd73e7213353c90d709502d9786219f69b731f6caa0efeb46f5",
+ "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23",
+ "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8",
+ "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613",
+ "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb",
+ "sha256:e574a7d61cf10351d734bcddabbe15ede0eaa8a02070d85446875dc11189a251",
+ "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6",
+ "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780",
+ "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd",
+ "sha256:e7f8659a48995edee7229522984bd1009c1213929c769c2daa80b40fe49a180c",
+ "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf",
+ "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa",
+ "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40",
+ "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7",
+ "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673",
+ "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb",
+ "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61",
+ "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940",
+ "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be",
+ "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b",
+ "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4",
+ "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476",
+ "sha256:fed38a5edb7945f4d1bcabe2fcd05db4f6ec7e0e82560088b754f7e08d93772d",
+ "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f",
+ "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248",
+ "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a"
],
"markers": "python_version >= '3.9'",
- "version": "==3.13.0"
+ "version": "==3.13.2"
},
"aiosignal": {
"hashes": [
@@ -158,6 +158,14 @@
"markers": "python_version >= '3.9'",
"version": "==1.4.0"
},
+ "annotated-doc": {
+ "hashes": [
+ "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320",
+ "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==0.0.4"
+ },
"annotated-types": {
"hashes": [
"sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53",
@@ -168,11 +176,11 @@
},
"anyio": {
"hashes": [
- "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc",
- "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4"
+ "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0",
+ "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb"
],
"markers": "python_version >= '3.9'",
- "version": "==4.11.0"
+ "version": "==4.12.0"
},
"attrs": {
"hashes": [
@@ -184,12 +192,12 @@
},
"authlib": {
"hashes": [
- "sha256:3e0e0507807f842b02175507bdee8957a1d5707fd4afb17c32fb43fee90b6e3a",
- "sha256:6aaf9c79b7cc96c900f0b284061691c5d4e61221640a948fe690b556a6d6d10b"
+ "sha256:45770e8e056d0f283451d9996fbb59b70d45722b45d854d58f32878d0a40c38e",
+ "sha256:7d9e9bc535c13974313a87f53e8430eb6ea3d1cf6ae4f6efcd793f2e949143fd"
],
"index": "pypi",
"markers": "python_version >= '3.9'",
- "version": "==1.6.5"
+ "version": "==1.6.6"
},
"backoff": {
"hashes": [
@@ -199,13 +207,29 @@
"markers": "python_version >= '3.7' and python_version < '4.0'",
"version": "==2.2.1"
},
+ "beartype": {
+ "hashes": [
+ "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f",
+ "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==0.22.9"
+ },
+ "cachetools": {
+ "hashes": [
+ "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51",
+ "sha256:82c5c05585e70b6ba2d3ae09ea60b79548872185d2f24ae1f2709d37299fd607"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==6.2.4"
+ },
"certifi": {
"hashes": [
- "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de",
- "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"
+ "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b",
+ "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"
],
"markers": "python_version >= '3.7'",
- "version": "==2025.10.5"
+ "version": "==2025.11.12"
},
"cffi": {
"hashes": [
@@ -299,164 +323,206 @@
},
"charset-normalizer": {
"hashes": [
- "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91",
- "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0",
- "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154",
- "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601",
- "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884",
- "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07",
- "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c",
- "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64",
- "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe",
- "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f",
- "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432",
- "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc",
- "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa",
- "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9",
- "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae",
- "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19",
- "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d",
- "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e",
- "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4",
- "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7",
- "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312",
- "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92",
- "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31",
- "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c",
- "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f",
- "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99",
- "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b",
- "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15",
- "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392",
- "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f",
- "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8",
- "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491",
- "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0",
- "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc",
- "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0",
- "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f",
- "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a",
- "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40",
- "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927",
- "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849",
- "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce",
- "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14",
- "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05",
- "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c",
- "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c",
- "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a",
- "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc",
- "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34",
- "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9",
- "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096",
- "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14",
- "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30",
- "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b",
- "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b",
- "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942",
- "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db",
- "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5",
- "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b",
- "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce",
- "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669",
- "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0",
- "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018",
- "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93",
- "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe",
- "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049",
- "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a",
- "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef",
- "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2",
- "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca",
- "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16",
- "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f",
- "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb",
- "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1",
- "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557",
- "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37",
- "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7",
- "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72",
- "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c",
- "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"
+ "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad",
+ "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93",
+ "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394",
+ "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89",
+ "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc",
+ "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86",
+ "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63",
+ "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d",
+ "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f",
+ "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8",
+ "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0",
+ "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505",
+ "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161",
+ "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af",
+ "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152",
+ "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318",
+ "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72",
+ "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4",
+ "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e",
+ "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3",
+ "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576",
+ "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c",
+ "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1",
+ "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8",
+ "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1",
+ "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2",
+ "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44",
+ "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26",
+ "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88",
+ "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016",
+ "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede",
+ "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf",
+ "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a",
+ "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc",
+ "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0",
+ "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84",
+ "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db",
+ "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1",
+ "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7",
+ "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed",
+ "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8",
+ "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133",
+ "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e",
+ "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef",
+ "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14",
+ "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2",
+ "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0",
+ "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d",
+ "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828",
+ "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f",
+ "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf",
+ "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6",
+ "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328",
+ "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090",
+ "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa",
+ "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381",
+ "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c",
+ "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb",
+ "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc",
+ "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a",
+ "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec",
+ "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc",
+ "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac",
+ "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e",
+ "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313",
+ "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569",
+ "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3",
+ "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d",
+ "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525",
+ "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894",
+ "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3",
+ "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9",
+ "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a",
+ "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9",
+ "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14",
+ "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25",
+ "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50",
+ "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf",
+ "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1",
+ "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3",
+ "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac",
+ "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e",
+ "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815",
+ "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c",
+ "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6",
+ "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6",
+ "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e",
+ "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4",
+ "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84",
+ "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69",
+ "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15",
+ "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191",
+ "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0",
+ "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897",
+ "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd",
+ "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2",
+ "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794",
+ "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d",
+ "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074",
+ "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3",
+ "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224",
+ "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838",
+ "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a",
+ "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d",
+ "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d",
+ "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f",
+ "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8",
+ "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490",
+ "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966",
+ "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9",
+ "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3",
+ "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e",
+ "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"
],
"markers": "python_version >= '3.7'",
- "version": "==3.4.3"
+ "version": "==3.4.4"
},
"click": {
"hashes": [
- "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc",
- "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"
+ "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a",
+ "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"
],
"markers": "python_version >= '3.10'",
- "version": "==8.3.0"
+ "version": "==8.3.1"
+ },
+ "cloudpickle": {
+ "hashes": [
+ "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414",
+ "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==3.1.2"
},
"cryptography": {
"hashes": [
- "sha256:04911b149eae142ccd8c9a68892a70c21613864afb47aba92d8c7ed9cc001023",
- "sha256:07c0eb6657c0e9cca5891f4e35081dbf985c8131825e21d99b4f440a8f496f36",
- "sha256:0b507c8e033307e37af61cb9f7159b416173bdf5b41d11c4df2e499a1d8e007c",
- "sha256:0c7ffe8c9b1fcbb07a26d7c9fa5e857c2fe80d72d7b9e0353dcf1d2180ae60ee",
- "sha256:1a88634851d9b8de8bb53726f4300ab191d3b2f42595e2581a54b26aba71b7cc",
- "sha256:1d3b3edd145953832e09607986f2bd86f85d1dc9c48ced41808b18009d9f30e5",
- "sha256:1e3b6428a3d56043bff0bb85b41c535734204e599c1c0977e1d0f261b02f3ad5",
- "sha256:1fd1a69086926b623ef8126b4c33d5399ce9e2f3fac07c9c734c2a4ec38b6d02",
- "sha256:218abd64a2e72f8472c2102febb596793347a3e65fafbb4ad50519969da44470",
- "sha256:21b6fc8c71a3f9a604f028a329e5560009cc4a3a828bfea5fcba8eb7647d88fe",
- "sha256:27c53b4f6a682a1b645fbf1cd5058c72cf2f5aeba7d74314c36838c7cbc06e0f",
- "sha256:2b9cad9cf71d0c45566624ff76654e9bae5f8a25970c250a26ccfc73f8553e2d",
- "sha256:2fafb6aa24e702bbf74de4cb23bfa2c3beb7ab7683a299062b69724c92e0fa73",
- "sha256:3f37aa12b2d91e157827d90ce78f6180f0c02319468a0aea86ab5a9566da644b",
- "sha256:48b983089378f50cba258f7f7aa28198c3f6e13e607eaf10472c26320332ca9a",
- "sha256:48c01988ecbb32979bb98731f5c2b2f79042a6c58cc9a319c8c2f9987c7f68f9",
- "sha256:4a766d2a5d8127364fd936572c6e6757682fc5dfcbdba1632d4554943199f2fa",
- "sha256:512c0250065e0a6b286b2db4bbcc2e67d810acd53eb81733e71314340366279e",
- "sha256:5840f05518caa86b09d23f8b9405a7b6d5400085aa14a72a98fdf5cf1568c0d2",
- "sha256:5e38f203160a48b93010b07493c15f2babb4e0f2319bbd001885adb3f3696d21",
- "sha256:6b275e398ab3a7905e168c036aad54b5969d63d3d9099a0a66cc147a3cc983be",
- "sha256:7282d8f092b5be7172d6472f29b0631f39f18512a3642aefe52c3c0e0ccfad5a",
- "sha256:747b6f4a4a23d5a215aadd1d0b12233b4119c4313df83ab4137631d43672cc90",
- "sha256:758cfc7f4c38c5c5274b55a57ef1910107436f4ae842478c4989abbd24bd5acb",
- "sha256:8b16c1ede6a937c291d41176934268e4ccac2c6521c69d3f5961c5a1e11e039e",
- "sha256:8b9bf67b11ef9e28f4d78ff88b04ed0929fcd0e4f70bb0f704cfc32a5c6311ee",
- "sha256:8e2ad4d1a5899b7caa3a450e33ee2734be7cc0689010964703a7c4bcc8dd4fd0",
- "sha256:9066cfd7f146f291869a9898b01df1c9b0e314bfa182cef432043f13fc462c92",
- "sha256:91447f2b17e83c9e0c89f133119d83f94ce6e0fb55dd47da0a959316e6e9cfa1",
- "sha256:97e83bf4f2f2c084d8dd792d13841d0a9b241643151686010866bbd076b19659",
- "sha256:9bd26f2f75a925fdf5e0a446c0de2714f17819bf560b44b7480e4dd632ad6c46",
- "sha256:9bdc25e4e01b261a8fda4e98618f1c9515febcecebc9566ddf4a70c63967043b",
- "sha256:9ec3f2e2173f36a9679d3b06d3d01121ab9b57c979de1e6a244b98d51fea1b20",
- "sha256:9f13b040649bc18e7eb37936009b24fd31ca095a5c647be8bb6aaf1761142bd1",
- "sha256:a08e7401a94c002e79dc3bc5231b6558cd4b2280ee525c4673f650a37e2c7685",
- "sha256:a61c154cc5488272a6c4b86e8d5beff4639cdb173d75325ce464d723cda0052b",
- "sha256:bb7fb9cd44c2582aa5990cf61a4183e6f54eea3172e54963787ba47287edd135",
- "sha256:bca3f0ce67e5a2a2cf524e86f44697c4323a86e0fd7ba857de1c30d52c11ede1",
- "sha256:bda55e8dbe8533937956c996beaa20266a8eca3570402e52ae52ed60de1faca8",
- "sha256:be939b99d4e091eec9a2bcf41aaf8f351f312cd19ff74b5c83480f08a8a43e0b",
- "sha256:c4b93af7920cdf80f71650769464ccf1fb49a4b56ae0024173c24c48eb6b1612",
- "sha256:cb5e8daac840e8879407acbe689a174f5ebaf344a062f8918e526824eb5d97af",
- "sha256:d19f5f48883752b5ab34cff9e2f7e4a7f216296f33714e77d1beb03d108632b6",
- "sha256:d30bc11d35743bf4ddf76674a0a369ec8a21f87aaa09b0661b04c5f6c46e8d7b",
- "sha256:e12b61e0b86611e3f4c1756686d9086c1d36e6fd15326f5658112ad1f1cc8807",
- "sha256:e6f6775eaaa08c0eec73e301f7592f4367ccde5e4e4df8e58320f2ebf161ea2c",
- "sha256:e7155c0b004e936d381b15425273aee1cebc94f879c0ce82b0d7fecbf755d53a",
- "sha256:e8633996579961f9b5a3008683344c2558d38420029d3c0bc7ff77c17949a4e1",
- "sha256:f25a41f5b34b371a06dad3f01799706631331adc7d6c05253f5bca22068c7a34",
- "sha256:f3e32ab7dd1b1ef67b9232c4cf5e2ee4cd517d4316ea910acaaa9c5712a1c663",
- "sha256:f9b2dc7668418fb6f221e4bf701f716e05e8eadb4f1988a2487b11aedf8abe62",
- "sha256:fab8f805e9675e61ed8538f192aad70500fa6afb33a8803932999b1049363a08",
- "sha256:fe245cf4a73c20592f0f48da39748b3513db114465be78f0a36da847221bd1b4",
- "sha256:ff798ad7a957a5021dcbab78dfff681f0cf15744d0e6af62bd6746984d9c9e9c"
+ "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217",
+ "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d",
+ "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc",
+ "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71",
+ "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971",
+ "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a",
+ "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926",
+ "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc",
+ "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d",
+ "sha256:191bb60a7be5e6f54e30ba16fdfae78ad3a342a0599eb4193ba88e3f3d6e185b",
+ "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20",
+ "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044",
+ "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3",
+ "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715",
+ "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4",
+ "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506",
+ "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f",
+ "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0",
+ "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683",
+ "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3",
+ "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21",
+ "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91",
+ "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c",
+ "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8",
+ "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df",
+ "sha256:6b5063083824e5509fdba180721d55909ffacccc8adbec85268b48439423d78c",
+ "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb",
+ "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7",
+ "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04",
+ "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db",
+ "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459",
+ "sha256:7ce938a99998ed3c8aa7e7272dca1a610401ede816d36d0693907d863b10d9ea",
+ "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914",
+ "sha256:9394673a9f4de09e28b5356e7fff97d778f8abad85c9d5ac4a4b7e25a0de7717",
+ "sha256:94cd0549accc38d1494e1f8de71eca837d0509d0d44bf11d158524b0e12cebf9",
+ "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac",
+ "sha256:a23582810fedb8c0bc47524558fb6c56aac3fc252cb306072fd2815da2a47c32",
+ "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec",
+ "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1",
+ "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb",
+ "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac",
+ "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665",
+ "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e",
+ "sha256:c70cc23f12726be8f8bc72e41d5065d77e4515efae3690326764ea1b07845cfb",
+ "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5",
+ "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936",
+ "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de",
+ "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372",
+ "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54",
+ "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422",
+ "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849",
+ "sha256:e7aec276d68421f9574040c26e2a7c3771060bc0cff408bae1dcb19d3ab1e63c",
+ "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963",
+ "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018"
],
"markers": "python_version >= '3.8' and python_full_version not in '3.9.0, 3.9.1'",
- "version": "==46.0.2"
+ "version": "==46.0.3"
},
"cyclopts": {
"hashes": [
- "sha256:809d04cde9108617106091140c3964ee6fceb33cecdd537f7ffa360bde13ed71",
- "sha256:de6964a041dfb3c57bf043b41e68c43548227a17de1bad246e3a0bfc5c4b7417"
+ "sha256:16764f5a807696b61da7d19626f34d261cdffe33345e87a194cf3286db2bd9cc",
+ "sha256:78ff95a5e52e738a1d0f01e5a3af48049c47748fa2c255f2629a4cef54dcf2b3"
],
- "markers": "python_version >= '3.9'",
- "version": "==3.24.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==4.4.0"
},
"diskcache": {
"hashes": [
@@ -492,11 +558,11 @@
},
"docutils": {
"hashes": [
- "sha256:9fdb771707c8784c8f2728b67cb2c691305933d68137ef95a75db5f4dfbc213d",
- "sha256:b0e98d679283fc3bb0ead8a5da7f501baa632654e7056e9c5846842213d674d8"
+ "sha256:21486ae730e4ca9f622677b1412b879af1791efcfba517e4c6f60be543fc8cdd",
+ "sha256:bd772e4aca73aff037958d44f2be5229ded4c09927fcf8690c577b66234d6ceb"
],
"markers": "python_version >= '3.9'",
- "version": "==0.22.2"
+ "version": "==0.22.3"
},
"email-validator": {
"hashes": [
@@ -508,119 +574,141 @@
},
"exceptiongroup": {
"hashes": [
- "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10",
- "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"
+ "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219",
+ "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"
],
"markers": "python_version >= '3.7'",
- "version": "==1.3.0"
+ "version": "==1.3.1"
+ },
+ "fakeredis": {
+ "extras": [
+ "lua"
+ ],
+ "hashes": [
+ "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770",
+ "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.33.0"
},
"falkordb": {
"hashes": [
- "sha256:7572d9cc377735d22efc52fe6fe73c7a435422c827b6ea3ca223a850a77be12e",
- "sha256:ce57365b86722d538e75aa5d438de67ecd8eb9478da612506d9812cd7f182d0b"
+ "sha256:3fc150d3262b971916a0f2c15f419f7fe521a94fe3a672b6f174288d885fd239",
+ "sha256:cc1fcccaa1148be9e3d22d85af03d027f19b398e0f38d04424f3757a02744976"
],
"index": "pypi",
"markers": "python_version >= '3.8' and python_version < '4.0'",
- "version": "==1.2.0"
+ "version": "==1.2.2"
},
"fastapi": {
"hashes": [
- "sha256:5e81654d98c4d2f53790a7d32d25a7353b30c81441be7d0958a26b5d761fa1c8",
- "sha256:705137a61e2ef71019d2445b123aa8845bd97273c395b744d5a7dfe559056855"
+ "sha256:0e9422e8d6b797515f33f500309f6e1c98ee4e85563ba0f2debb282df6343763",
+ "sha256:6d1e703698443ccb89e50abe4893f3c84d9d6689c0cf1ca4fad6d3c15cf69f15"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
- "version": "==0.118.0"
+ "version": "==0.124.4"
},
"fastmcp": {
"hashes": [
- "sha256:56188fbbc1a9df58c537063f25958c57b5c4d715f73e395c41b51550b247d140",
- "sha256:b55fe89537038f19d0f4476544f9ca5ac171033f61811cc8f12bdeadcbea5016"
+ "sha256:132725cbf77b68fa3c3d165eff0cfa47e40c1479457419e6a2cfda65bd84c8d6",
+ "sha256:fb3e365cc1d52573ab89caeba9944dd4b056149097be169bce428e011f0a57e5"
],
"index": "pypi",
"markers": "python_version >= '3.10'",
- "version": "==2.12.4"
+ "version": "==2.14.1"
},
"fastuuid": {
"hashes": [
- "sha256:0225f8bc78071a191cb458b3b0e23b04a7f03013575b8a3083da2a84c450e200",
- "sha256:02a460333f52d731a006d18a52ef6fcb2d295a1f5b1a5938d30744191b2f77b7",
- "sha256:191ff6192fe53c5fc9d4d241ee1156b30a7ed6f1677b1cc2423e7ecdbc26222b",
- "sha256:22da0f66041e1c10c7d465b495cc6cd8e17e080dda34b4bd5ff5240b860fbb82",
- "sha256:2354c1996d3cf12dc2ba3752e2c4d6edc46e1a38c63893146777b1939f3062d4",
- "sha256:241fdd362fd96e6b337db62a65dd7cb3dfac20adf854573247a47510e192db6f",
- "sha256:25e82c4a1734da168b36f7308e397afbe9c9b353799a9c69563a605f11dd4641",
- "sha256:2705cf7c2d6f7c03053404b75a4c44f872a73f6f9d5ea34f1dc6bba400c4a97c",
- "sha256:2f29f93b5a0c5f5579f97f77d5319e9bfefd61d8678ec59d850201544faf33bf",
- "sha256:348ce9f296dda701ba46d8dceeff309f90dbc75dd85080bbed2b299aa908890a",
- "sha256:35fe8045e866bc6846f8de6fa05acb1de0c32478048484a995e96d31e21dff2a",
- "sha256:399d86623fb806151b1feb9fdd818ebfc1d50387199a35f7264f98dfc1540af5",
- "sha256:3e6b548f06c1ed7bad951a17a09eef69d6f24eb2b874cb4833e26b886d82990f",
- "sha256:46954fb644995d7fc8bbd710fbd4c65cedaa48c921c86fdbafef0229168a8c96",
- "sha256:4a32306982bd031cb20d5d1a726b7b958a55babebd2300ce6c8e352d3496e931",
- "sha256:4e362a3d66874d3d11a1ee9a8e717e32c2817cdb5d7a4e913290bf6e0f2a7fd8",
- "sha256:57d0768afcad0eab8770c9b8cf904716bd3c547e8b9a4e755ee8a673b060a3a3",
- "sha256:5d220a056fcbad25932c1f25304261198612f271f4d150b2a84e81adb877daf7",
- "sha256:5d753bc9ba8de6dd9caa8bbac045578c2fbe1c6ae40c2026b614676776fbe9dc",
- "sha256:68227f2230381b89fb1ad362ca6e433de85c6c11c36312b41757cad47b8a8e32",
- "sha256:689e8795a1edd573b2c9a455024e4edf605a9690339bba29709857f7180894ea",
- "sha256:6955a99ef455c2986f3851f4e0ccc35dec56ac1a7720f2b92e88a75d6684512e",
- "sha256:69b34363752d06e9bb0dbdf02ae391ec56ac948c6f2eb00be90dad68e80774b9",
- "sha256:6ca01f5e614530a1a858bf185dd5556805a4c11b6eba0a2536890b68ed954922",
- "sha256:6d3b6b10d78b9f7056445ac377612443980349da7221a3dd3e3f382f7c437be3",
- "sha256:74b0e4f8c307b9f477a5d7284db4431ce53a3c1e3f4173db7a97db18564a6202",
- "sha256:880f0d03ad2518b96757ca422cba6ff76cea5464db2b3ad75c32acf1890e058f",
- "sha256:8ac6c6f5129d52eaa6ef9ea4b6e2f7c69468a053f3ab8e439661186b9c06bb85",
- "sha256:904ac3eb37f4742e23f6a51be0d0451d1d3aceb50df8dac7afc6bf5209793650",
- "sha256:92ba539170097b9047551375f1ca09d8d2b4aefcc79eeae3e1c43fe49b42072e",
- "sha256:9ae95e4dcf94775d948ebb843f4443d33cd224bb31174030e106ee3cab66527c",
- "sha256:9ff3fc87e1f19603dd53c38f42c2ea8d5d5462554deab69e9cf1800574e4756c",
- "sha256:a1c430a332ead0b2674f1ef71b17f43b8139ec5a4201182766a21f131a31e021",
- "sha256:a3f3f8f10b962cf2e11d3affc0cf2697ac5c9accc0d282dce981ed555a44ce15",
- "sha256:a41257ea172b5de199c3cfa71cc6c574dcf22367fe51e26cba0d359107f11f30",
- "sha256:a5becc646a3eeafb76ce0a6783ba190cd182e3790a8b2c78ca9db2b5e87af952",
- "sha256:a67e18c2d7fba8be6ea4aed8ca5a20fcf273f003efa01c1f33a096b72537e69e",
- "sha256:a6cf9b7469fc26d1f9b1c43ac4b192e219e85b88fdf81d71aa755a6c08c8a817",
- "sha256:a6e5337fa7698dc52bc724da7e9239e93c5b24a09f6904b8660dfb8c41ce3dee",
- "sha256:ad630e97715beefef07ec37c9c162336e500400774e2c1cbe1a0df6f80d15b9a",
- "sha256:b3ec6dab282162c19ec2172f33bafd467cffe26b92345789278adcbec19428d1",
- "sha256:b9baa9c33848ec0926231e7ecfef9e02faa0f6d24265b64108ea41f7a0bb3f48",
- "sha256:b9edf8ee30718aee787cdd2e9e1ff3d4a3ec6ddb32fba0a23fa04956df69ab07",
- "sha256:bb25dccbeb249d16d5e664f65f17ebec05136821d5ef462c4110e3f76b86fb86",
- "sha256:be6ad91e5fefbcc2a4b478858a2715e386d405834ea3ae337c3b6b95cc0e47d6",
- "sha256:c122558ca4b5487e2bd0863467e4ccfe636afd1274803741487d48f2e32ea0e1",
- "sha256:c1ae87968614fe6d3029a8198671b5893341aac9459289e93d201027be9ea7e8",
- "sha256:c6b070e0dc1965d53b9e07c291537095ececf7d7e36e60aed9b22400fa6c5c7f",
- "sha256:c82838e52189d16b1307631179cb2cd37778dd8f4ddc00e9ce3c26f920b3b2f7",
- "sha256:cade5f3b8023dbba5a006e5685a7baf0d7a30c43cea17113768aa9ef9582d799",
- "sha256:d2424a90688dbc44f119686fa452ff21aa106c9da258214f577816462ad606d5",
- "sha256:d4976821ab424d41542e1ea39bc828a9d454c3f8a04067c06fca123c5b95a1a1",
- "sha256:d7abd42a03a17a681abddd19aa4d44ca2747138cf8a48373b395cf1341a10de2",
- "sha256:d973bd6bf9d754d3cca874714ac0a6b22a47f239fb3d3c8687569db05aac3471",
- "sha256:dbb81d05617bc2970765c1ad82db7e8716f6a2b7a361a14b83de5b9240ade448",
- "sha256:e353c0a0d978a5ecd97171ac4fb7f55a6bd6cbae90f1ec4e828e5317f11b995e",
- "sha256:e725ceef79486423f05ee657634d4b4c1ca5fb2c8a94e0708f5d6356a83f2a83",
- "sha256:ea17dfd35e0e91920a35d91e65e5f9c9d1985db55ac4ff2f1667a0f61189cefa",
- "sha256:ea6df13a306aab3e0439d58c312ff1e6f4f07f09f667579679239b4a6121f64a",
- "sha256:ebe95b730f81808eabc90247ac3d412b96d9fae1c406760b163bb9f134b7af69",
- "sha256:ed78153c589e5efb34faaa216836a5bf8a0b9d34e82183203166011238d9ed13",
- "sha256:f10c77b826738c1a27dcdaa92ea4dc1ec9d869748a99e1fde54f1379553d4854",
- "sha256:f62299e3cca69aad6a6fb37e26e45055587954d498ad98903fea24382377ea0e",
- "sha256:f67ea1e25c5e782f7fb5aaa5208f157d950401dd9321ce56bcc6d4dc3d72ed60",
- "sha256:f8f2cc6972941ab030f3776961ed8454772c3acad88781fc262d71514df89973",
- "sha256:f9530f1328b05b80c6fa111e7f2a5d55fa30fbbd72d708326d0c7b55b67ed772",
- "sha256:f9db596023c10dabb12489a88c51b75297c3a2478cb2be645e06905934e7b9fc"
+ "sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1",
+ "sha256:0737606764b29785566f968bd8005eace73d3666bd0862f33a760796e26d1ede",
+ "sha256:089c18018fdbdda88a6dafd7d139f8703a1e7c799618e33ea25eb52503d28a11",
+ "sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995",
+ "sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc",
+ "sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796",
+ "sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed",
+ "sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7",
+ "sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab",
+ "sha256:139d7ff12bb400b4a0c76be64c28cbe2e2edf60b09826cbfd85f33ed3d0bbe8b",
+ "sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00",
+ "sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26",
+ "sha256:193ca10ff553cf3cc461572da83b5780fc0e3eea28659c16f89ae5202f3958d4",
+ "sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219",
+ "sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75",
+ "sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714",
+ "sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b",
+ "sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94",
+ "sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36",
+ "sha256:2dce5d0756f046fa792a40763f36accd7e466525c5710d2195a038f93ff96346",
+ "sha256:2ec3d94e13712a133137b2805073b65ecef4a47217d5bac15d8ac62376cefdb4",
+ "sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8",
+ "sha256:2fc37479517d4d70c08696960fad85494a8a7a0af4e93e9a00af04d74c59f9e3",
+ "sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87",
+ "sha256:3964bab460c528692c70ab6b2e469dd7a7b152fbe8c18616c58d34c93a6cf8d4",
+ "sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8",
+ "sha256:448aa6833f7a84bfe37dd47e33df83250f404d591eb83527fa2cac8d1e57d7f3",
+ "sha256:47c821f2dfe95909ead0085d4cb18d5149bca704a2b03e03fb3f81a5202d8cea",
+ "sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6",
+ "sha256:5816d41f81782b209843e52fdef757a361b448d782452d96abedc53d545da722",
+ "sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a",
+ "sha256:6fbc49a86173e7f074b1a9ec8cf12ca0d54d8070a85a06ebf0e76c309b84f0d0",
+ "sha256:73657c9f778aba530bc96a943d30e1a7c80edb8278df77894fe9457540df4f85",
+ "sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34",
+ "sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021",
+ "sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a",
+ "sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d",
+ "sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a",
+ "sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09",
+ "sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8",
+ "sha256:84b0779c5abbdec2a9511d5ffbfcd2e53079bf889824b32be170c0d8ef5fc74c",
+ "sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176",
+ "sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4",
+ "sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc",
+ "sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad",
+ "sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24",
+ "sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f",
+ "sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f",
+ "sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f",
+ "sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741",
+ "sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5",
+ "sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4",
+ "sha256:af5967c666b7d6a377098849b07f83462c4fedbafcf8eb8bc8ff05dcbe8aa209",
+ "sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470",
+ "sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad",
+ "sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057",
+ "sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8",
+ "sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe",
+ "sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73",
+ "sha256:c0eb25f0fd935e376ac4334927a59e7c823b36062080e2e13acbaf2af15db836",
+ "sha256:c3091e63acf42f56a6f74dc65cfdb6f99bfc79b5913c8a9ac498eb7ca09770a8",
+ "sha256:c501561e025b7aea3508719c5801c360c711d5218fc4ad5d77bf1c37c1a75779",
+ "sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b",
+ "sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d",
+ "sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022",
+ "sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7",
+ "sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070",
+ "sha256:d31f8c257046b5617fc6af9c69be066d2412bdef1edaa4bdf6a214cf57806105",
+ "sha256:d55b7e96531216fc4f071909e33e35e5bfa47962ae67d9e84b00a04d6e8b7173",
+ "sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397",
+ "sha256:de01280eabcd82f7542828ecd67ebf1551d37203ecdfd7ab1f2e534edb78d505",
+ "sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a",
+ "sha256:e0976c0dff7e222513d206e06341503f07423aceb1db0b83ff6851c008ceee06",
+ "sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa",
+ "sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06",
+ "sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8",
+ "sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad",
+ "sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d"
],
"markers": "python_version >= '3.8'",
- "version": "==0.13.5"
+ "version": "==0.14.0"
},
"filelock": {
"hashes": [
- "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58",
- "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"
+ "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a",
+ "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c"
],
- "markers": "python_version >= '3.9'",
- "version": "==3.19.1"
+ "markers": "python_version >= '3.10'",
+ "version": "==3.20.1"
},
"frozenlist": {
"hashes": [
@@ -760,17 +848,78 @@
},
"fsspec": {
"hashes": [
- "sha256:19fd429483d25d28b65ec68f9f4adc16c17ea2c7c7bf54ec61360d478fb19c19",
- "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7"
+ "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b",
+ "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973"
],
- "markers": "python_version >= '3.9'",
- "version": "==2025.9.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==2025.12.0"
},
"graphiti-core": {
"git": "git+https://github.com/FalkorDB/graphiti.git",
"markers": "python_version >= '3.10' and python_version < '4'",
"ref": "6e3c54ae2891e10a24d698a2f0733d65d148edf4"
},
+ "grpcio": {
+ "hashes": [
+ "sha256:01f616a964e540638af5130469451cf580ba8c7329f45ca998ab66e0c7dcdb04",
+ "sha256:0489063974d1452436139501bf6b180f63d4977223ee87488fe36858c5725292",
+ "sha256:0e6f255980afef598a9e64a24efce87b625e3e3c80a45162d111a461a9f92955",
+ "sha256:0f3e49c738396e93b7ba9016e153eb09e0778e776df6090c1b8c91877cc1c426",
+ "sha256:178f5db771c4f9a9facb2ab37a434c46cb9be1a75e820f187ee3d1e7805c4f65",
+ "sha256:1a65b503d008f066e994f34f456e0647e5ceb34cfcec5ad180b1b44020ad4970",
+ "sha256:1d7616d2ded471231c701489190379e0c311ee0a6c756f3c03e6a62b95a7146e",
+ "sha256:24e8a26dbfc5274d7474c27759b54486b8de23c709d76695237515bc8b5baeab",
+ "sha256:267d1745894200e4c604958da5f856da6293f063327cb049a51fe67348e4f953",
+ "sha256:299b3d8c4f790c6bcca485f9963b4846dd92cf6f1b65d3697145d005c80f9fe8",
+ "sha256:3b6c16489326d79ead41689c4b84bc40d522c9a7617219f4ad94bc7f448c5085",
+ "sha256:3dc2ed4cabea4dc14d5e708c2b426205956077cc5de419b4d4079315017e9732",
+ "sha256:43112046864317498a33bdc4797ae6a268c36345a910de9b9c17159d8346602f",
+ "sha256:4422581cdc628f77302270ff839a44f4c24fdc57887dc2a45b7e53d8fc2376af",
+ "sha256:4e7b904484a634a0fff132958dabdb10d63e0927398273917da3ee103e8d1f78",
+ "sha256:5721e66a594a6c4204458004852719b38f3d5522082be9061d6510b455c90afc",
+ "sha256:5db70d32d6703b89912af16d6d45d78406374a8b8ef0d28140351dd0ec610e98",
+ "sha256:5ed601c4c6008429e3d247ddb367fe8c7259c355757448d7c1ef7bd4a6739e8e",
+ "sha256:60336bff760fbb47d7e86165408126f1dded184448e9a4c892189eb7c9d3f90f",
+ "sha256:608d87d1bdabf9e2868b12338cd38a79969eaf920c89d698ead08f48de9c0f9e",
+ "sha256:60e6a4dcf5af7bbc36fd9f81c9f372e8ae580870a9e4b6eafe948cd334b81cf3",
+ "sha256:638354e698fd0c6c76b04540a850bf1db27b4d2515a19fcd5cf645c48d3eb1ed",
+ "sha256:699e964923b70f3101393710793289e42845791ea07565654ada0969522d0a38",
+ "sha256:7818c0454027ae3384235a65210bbf5464bd715450e30a3d40385453a85a70cb",
+ "sha256:786a5b18544622bfb1e25cc08402bd44ea83edfb04b93798d85dca4d1a0b5be5",
+ "sha256:804c6457c3cd3ec04fe6006c739579b8d35c86ae3298ffca8de57b493524b771",
+ "sha256:80b866f73224b0634f4312a4674c1be21b2b4afa73cb20953cbbb73a6b36c3cc",
+ "sha256:85f69fdc1d28ce7cff8de3f9c67db2b0ca9ba4449644488c1e0303c146135ddb",
+ "sha256:85f862069b86a305497e74d0dc43c02de3d1d184fc2c180993aa8aa86fbd19b8",
+ "sha256:8a00efecde9d6fcc3ab00c13f816313c040a28450e5e25739c24f432fc6d3c75",
+ "sha256:8a23cbcc5bb11ea7dc6163078be36c065db68d915c24f5faa4f872c573bb400f",
+ "sha256:8b0341d66a57f8a3119b77ab32207072be60c9bf79760fa609c5609f2deb1f3f",
+ "sha256:917e8d8994eed1d86b907ba2a61b9f0aef27a2155bca6cbb322430fc7135b7bb",
+ "sha256:95b5f2b857856ed78d72da93cd7d09b6db8ef30102e5e7fe0961fe4d9f7d48e8",
+ "sha256:9e838cad2176ebd5d4a8bb03955138d6589ce9e2ce5d51c3ada34396dbd2dba8",
+ "sha256:9fd042de4a82e3e7aca44008ee2fb5da01b3e5adb316348c21980f7f58adc311",
+ "sha256:a25bdea92b13ff4d7790962190bf6bf5c4639876e01c0f3dda70fc2769616335",
+ "sha256:a6703916c43b1d468d0756c8077b12017a9fcb6a1ef13faf49e67d20d7ebda62",
+ "sha256:a93deda571a1bf94ec1f6fcda2872dad3ae538700d94dc283c672a3b508ba3af",
+ "sha256:aa0162e56fd10a5547fac8774c4899fc3e18c1aa4a4759d0ce2cd00d3696ea6b",
+ "sha256:b49359977c6ec9f5d0573ea4e0071ad278ef905aa74e420acc73fd28ce39e9ce",
+ "sha256:beee96c8c0b1a75d556fe57b92b58b4347c77a65781ee2ac749d550f2a365dc1",
+ "sha256:c7a01337407dd89005527623a4a72c5c8e2894d22bead0895306b23c6695698f",
+ "sha256:c9b929f13677b10f63124c1a410994a401cdd85214ad83ab67cc077fc7e480f0",
+ "sha256:cdc491ae35a13535fd9196acb5afe1af37c8237df2e54427be3eecda3653127e",
+ "sha256:e279330bef1744040db8fc432becc8a727b84f456ab62b744d3fdb83f327e121",
+ "sha256:e29ca27bec8e163dca0c98084040edec3bc49afd10f18b412f483cc68c712744",
+ "sha256:e7d1797a8a3845437d327145959a2c0c47c05947c9eef5ff1a4c80e499dcc6fa",
+ "sha256:ea33986b70f83844cd00814cee4451055cd8cab36f00ac64a31f5bb09b31919e",
+ "sha256:ec74ef02010186185de82cc594058a3ccd8d86821842bbac9873fd4a2cf8be8d",
+ "sha256:f26b0b547eb8d00e195274cdfc63ce64c8fc2d3e2d00b12bf468ece41a0423a0",
+ "sha256:f5a27dddefe0e2357d3e617b9079b4bfdc91341a91565111a21ed6ebbc51b22d",
+ "sha256:f5b76ff64aaac53fede0cc93abf57894ab2a7362986ba22243d06218b93efe46",
+ "sha256:f9fff78ba10d4250bfc07a01bd6254a6d87dc67f9627adece85c0b2ed754fa96",
+ "sha256:fa0c739ad8b1996bd24823950e3cb5152ae91fca1c09cc791190bf1627ffefba"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.67.1"
+ },
"h11": {
"hashes": [
"sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1",
@@ -781,17 +930,31 @@
},
"hf-xet": {
"hashes": [
- "sha256:0a0005fd08f002180f7a12d4e13b22be277725bc23ed0529f8add5c7a6309c06",
- "sha256:408aef343800a2102374a883f283ff29068055c111f003ff840733d3b715bb97",
- "sha256:5f54b19cc347c13235ae7ee98b330c26dd65ef1df47e5316ffb1e87713ca7045",
- "sha256:686083aca1a6669bc85c21c0563551cbcdaa5cf7876a91f3d074a030b577231d",
- "sha256:6b6bceb6361c80c1cc42b5a7b4e3efd90e64630bcf11224dcac50ef30a47e435",
- "sha256:71081925383b66b24eedff3013f8e6bbd41215c3338be4b94ba75fd75b21513b",
- "sha256:eae7c1fc8a664e54753ffc235e11427ca61f4b0477d757cc4eb9ae374b69f09c",
- "sha256:f900481cf6e362a6c549c61ff77468bd59d6dd082f3170a36acfef2eb6a6793f"
+ "sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e",
+ "sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc",
+ "sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4",
+ "sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382",
+ "sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090",
+ "sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8",
+ "sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0",
+ "sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd",
+ "sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848",
+ "sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737",
+ "sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a",
+ "sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f",
+ "sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc",
+ "sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f",
+ "sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865",
+ "sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f",
+ "sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813",
+ "sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5",
+ "sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649",
+ "sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c",
+ "sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69",
+ "sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832"
],
"markers": "python_version >= '3.8'",
- "version": "==1.1.10"
+ "version": "==1.2.0"
},
"httpcore": {
"hashes": [
@@ -811,27 +974,27 @@
},
"httpx-sse": {
"hashes": [
- "sha256:5bb6a2771a51e6c7a5f5c645e40b8a5f57d8de708f46cb5f3868043c3c18124e",
- "sha256:a9fa4afacb293fa50ef9bacb6cae8287ba5fd1f4b1c2d10a35bb981c41da31ab"
+ "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc",
+ "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d"
],
"markers": "python_version >= '3.9'",
- "version": "==0.4.2"
+ "version": "==0.4.3"
},
"huggingface-hub": {
"hashes": [
- "sha256:0e3a01829c19d86d03793e4577816fe3bdfc1602ac62c7fb220d593d351224ba",
- "sha256:350932eaa5cc6a4747efae85126ee220e4ef1b54e29d31c3b45c5612ddf0b32a"
+ "sha256:4ba57f17004fd27bb176a6b7107df579865d4cde015112db59184c51f5602ba7",
+ "sha256:c9b7a91a9eedaa2149cdc12bdd8f5a11780e10de1f1024718becf9e41e5a4642"
],
- "markers": "python_full_version >= '3.8.0'",
- "version": "==0.35.3"
+ "markers": "python_full_version >= '3.9.0'",
+ "version": "==1.2.3"
},
"idna": {
"hashes": [
- "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
- "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
+ "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea",
+ "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"
],
- "markers": "python_version >= '3.6'",
- "version": "==3.10"
+ "markers": "python_version >= '3.8'",
+ "version": "==3.11"
},
"importlib-metadata": {
"hashes": [
@@ -841,14 +1004,6 @@
"markers": "python_version >= '3.9'",
"version": "==8.7.0"
},
- "isodate": {
- "hashes": [
- "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15",
- "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==0.7.2"
- },
"itsdangerous": {
"hashes": [
"sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
@@ -858,6 +1013,30 @@
"markers": "python_version >= '3.8'",
"version": "==2.2.0"
},
+ "jaraco.classes": {
+ "hashes": [
+ "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd",
+ "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==3.4.0"
+ },
+ "jaraco.context": {
+ "hashes": [
+ "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3",
+ "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==6.0.1"
+ },
+ "jaraco.functools": {
+ "hashes": [
+ "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8",
+ "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==4.3.0"
+ },
"jinja2": {
"hashes": [
"sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
@@ -869,87 +1048,111 @@
},
"jiter": {
"hashes": [
- "sha256:07630bb46ea2a6b9c6ed986c6e17e35b26148cce2c535454b26ee3f0e8dcaba1",
- "sha256:089f9df9f69532d1339e83142438668f52c97cd22ee2d1195551c2b1a9e6cf33",
- "sha256:09858f8d230f031c7b8e557429102bf050eea29c77ad9c34c8fe253c5329acb7",
- "sha256:11840d2324c9ab5162fc1abba23bc922124fedcff0d7b7f85fffa291e2f69206",
- "sha256:11df2bf99fb4754abddd7f5d940a48e51f9d11624d6313ca4314145fcad347f0",
- "sha256:144fc21337d21b1d048f7f44bf70881e1586401d405ed3a98c95a114a9994982",
- "sha256:1d4a6c4a737d486f77f842aeb22807edecb4a9417e6700c7b981e16d34ba7c72",
- "sha256:1d9637eaf8c1d6a63d6562f2a6e5ab3af946c66037eb1b894e8fad75422266e4",
- "sha256:1dc6a123f3471c4730db7ca8ba75f1bb3dcb6faeb8d46dd781083e7dee88b32d",
- "sha256:25a5b1110cca7329fd0daf5060faa1234be5c11e988948e4f1a1923b6a457fe1",
- "sha256:25c625b9b61b5a8725267fdf867ef2e51b429687f6a4eef211f4612e95607179",
- "sha256:29ed1fe69a8c69bf0f2a962d8d706c7b89b50f1332cd6b9fbda014f60bd03a03",
- "sha256:29fff31190ab3a26de026da2f187814f4b9c6695361e20a9ac2123e4d4378a4c",
- "sha256:2fb7b377688cc3850bbe5c192a6bd493562a0bc50cbc8b047316428fbae00ada",
- "sha256:3893ce831e1c0094a83eeaf56c635a167d6fa8cc14393cc14298fd6fdc2a2449",
- "sha256:4441a91b80a80249f9a6452c14b2c24708f139f64de959943dfeaa6cb915e8eb",
- "sha256:452d13e4fd59698408087235259cebe67d9d49173b4dacb3e8d35ce4acf385d6",
- "sha256:452d80a1c86c095a242007bd9fc5d21b8a8442307193378f891cb8727e469648",
- "sha256:494ba627c7f550ad3dabb21862864b8f2216098dc18ff62f37b37796f2f7c325",
- "sha256:4ad8bd82165961867a10f52010590ce0b7a8c53da5ddd8bbb62fef68c181b921",
- "sha256:4ee5821e3d66606b29ae5b497230b304f1376f38137d69e35f8d2bd5f310ff73",
- "sha256:4f01a744d24a5f2bb4a11657a1b27b61dc038ae2e674621a74020406e08f749b",
- "sha256:53933a38ef7b551dd9c7f1064f9d7bb235bb3168d0fa5f14f0798d1b7ea0d9c5",
- "sha256:5661469a7b2be25ade3a4bb6c21ffd1e142e13351a0759f264dfdd3ad99af1ab",
- "sha256:572208127034725e79c28437b82414028c3562335f2b4f451d98136d0fc5f9cd",
- "sha256:5a7092b699646a1ddc03a7b112622d9c066172627c7382659befb0d2996f1659",
- "sha256:5beb56d22b63647bafd0b74979216fdee80c580c0c63410be8c11053860ffd09",
- "sha256:63782a1350917a27817030716566ed3d5b3c731500fd42d483cbd7094e2c5b25",
- "sha256:6e2bbf24f16ba5ad4441a9845e40e4ea0cb9eed00e76ba94050664ef53ef4406",
- "sha256:719891c2fb7628a41adff4f2f54c19380a27e6fdfdb743c24680ef1a54c67bd0",
- "sha256:76c15ef0d3d02f8b389066fa4c410a0b89e9cc6468a1f0674c5925d2f3c3e890",
- "sha256:7764f27d28cd4a9cbc61704dfcd80c903ce3aad106a37902d3270cd6673d17f4",
- "sha256:7b13a431dba4b059e9e43019d3022346d009baf5066c24dcdea321a303cde9f0",
- "sha256:8e36924dad32c48d3c5e188d169e71dc6e84d6cb8dedefea089de5739d1d2f80",
- "sha256:8fe6530aa738a4f7d4e4702aa8f9581425d04036a5f9e25af65ebe1f708f23be",
- "sha256:902b43386c04739229076bd1c4c69de5d115553d982ab442a8ae82947c72ede7",
- "sha256:97025d09ef549795d8dc720a824312cee3253c890ac73c621721ddfc75066789",
- "sha256:9a6dff27eca70930bdbe4cbb7c1a4ba8526e13b63dc808c0670083d2d51a4a72",
- "sha256:a1b7cbe3f25bd0d8abb468ba4302a5d45617ee61b2a7a638f63fee1dc086be99",
- "sha256:a4d71d7ea6ea8786291423fe209acf6f8d398a0759d03e7f24094acb8ab686ba",
- "sha256:a624d87719e1b5d09c15286eaee7e1532a40c692a096ea7ca791121365f548c1",
- "sha256:a9d0146d8d9b3995821bb586fc8256636258947c2f39da5bab709f3a28fb1a0b",
- "sha256:adcab442f4a099a358a7f562eaa54ed6456fb866e922c6545a717be51dbed7d7",
- "sha256:af62e84ca3889604ebb645df3b0a3f3bcf6b92babbff642bd214616f57abb93a",
- "sha256:b0f32e644d241293b892b1a6dd8f0b9cc029bfd94c97376b2681c36548aabab7",
- "sha256:b1ae2a7593a62132c7d4c2abbee80bbbb94fdc6d157e2c6cc966250c564ef774",
- "sha256:b42c2cd74273455ce439fd9528db0c6e84b5623cb74572305bdd9f2f2961d3df",
- "sha256:b7b0178417b0dcfc5f259edbc6db2b1f5896093ed9035ee7bab0f2be8854726d",
- "sha256:b8da18a99f58bca3ecc2d2bba99cac000a924e115b6c4f0a2b98f752b6fbf39a",
- "sha256:bb948402821bc76d1f6ef0f9e19b816f9b09f8577844ba7140f0b6afe994bc64",
- "sha256:bf11807e802a214daf6c485037778843fadd3e2ec29377ae17e0706ec1a25758",
- "sha256:c0a7f0ec81d5b7588c5cade1eb1925b91436ae6726dc2df2348524aeabad5de6",
- "sha256:c2d13ba7567ca8799f17c76ed56b1d49be30df996eb7fa33e46b62800562a5e2",
- "sha256:c59459beca2fbc9718b6f1acb7bfb59ebc3eb4294fa4d40e9cb679dafdcc6c60",
- "sha256:c5e86126d64706fd28dfc46f910d496923c6f95b395138c02d0e252947f452bd",
- "sha256:c6f3b32bb723246e6b351aecace52aba78adb8eeb4b2391630322dc30ff6c773",
- "sha256:c9967c2ab338ee2b2c0102fd379ec2693c496abf71ffd47e4d791d1f593b68e2",
- "sha256:cb5d9db02979c3f49071fce51a48f4b4e4cf574175fb2b11c7a535fa4867b222",
- "sha256:cdef53eda7d18e799625023e1e250dbc18fbc275153039b873ec74d7e8883e09",
- "sha256:cf408d2a0abd919b60de8c2e7bc5eeab72d4dafd18784152acc7c9adc3291591",
- "sha256:d067655a7cf0831eb8ec3e39cbd752995e9b69a2206df3535b3a067fac23b032",
- "sha256:d50880a6da65d8c23a2cf53c412847d9757e74cc9a3b95c5704a1d1a24667347",
- "sha256:dbb57da40631c267861dd0090461222060960012d70fd6e4c799b0f62d0ba166",
- "sha256:dbe2196c4a0ce760925a74ab4456bf644748ab0979762139626ad138f6dac72d",
- "sha256:dd4ca85fb6a62cf72e1c7f5e34ddef1b660ce4ed0886ec94a1ef9777d35eaa1f",
- "sha256:df64edcfc5dd5279a791eea52aa113d432c933119a025b0b5739f90d2e4e75f1",
- "sha256:df7f1927cbdf34cb91262a5418ca06920fd42f1cf733936d863aeb29b45a14ef",
- "sha256:e35d66681c133a03d7e974e7eedae89720fe8ca3bd09f01a4909b86a8adf31f5",
- "sha256:e4ffd3b0fff3fabbb02cc09910c08144db6bb5697a98d227a074401e01ee63dd",
- "sha256:e71ae6d969d0c9bab336c5e9e2fabad31e74d823f19e3604eaf96d9a97f463df",
- "sha256:e7d0bed3b187af8b47a981d9742ddfc1d9b252a7235471ad6078e7e4e5fe75c2",
- "sha256:e84e58198d4894668eec2da660ffff60e0f3e60afa790ecc50cb12b0e02ca1d4",
- "sha256:f0062dab98172dd0599fcdbf90214d0dcde070b1ff38a00cc1b90e111f071982",
- "sha256:f05d03775a11aaf132c447436983169958439f1219069abf24662a672851f94e",
- "sha256:f637b8e818f6d75540f350a6011ce21252573c0998ea1b4365ee54b7672c23c5",
- "sha256:f6fe0283e903ebc55f1a6cc569b8c1f3bf4abd026fed85e3ff8598a9e6f982f0",
- "sha256:fb4790497369d134a07fc763cc88888c46f734abdd66f9fdf7865038bf3a8f40",
- "sha256:ff85fc6d2a431251ad82dbd1ea953affb5a60376b62e7d6809c5cd058bb39471"
+ "sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45",
+ "sha256:06cb970936c65de926d648af0ed3d21857f026b1cf5525cb2947aa5e01e05789",
+ "sha256:0a51bad79f8cc9cac2b4b705039f814049142e0050f30d91695a2d9a6611f126",
+ "sha256:122046f3b3710b85de99d9aa2f3f0492a8233a2f54a64902b096efc27ea747b5",
+ "sha256:15d7fafb81af8a9e3039fc305529a61cd933eecee33b4251878a1c89859552a3",
+ "sha256:1b135ebe757a82d67ed2821526e72d0acf87dd61f6013e20d3c45b8048af927b",
+ "sha256:1eb5db8d9c65b112aacf14fcd0faae9913d07a8afea5ed06ccdd12b724e966a1",
+ "sha256:2218228a077e784c6c8f1a8e5d6b8cb1dea62ce25811c356364848554b2056cd",
+ "sha256:26b9e155ddc132225a39b1995b3b9f0fe0f79a6d5cbbeacf103271e7d309b404",
+ "sha256:27ec39225e03c32c6b863ba879deb427882f243ae46f0d82d68b695fa5b48b40",
+ "sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7",
+ "sha256:2a67b678f6a5f1dd6c36d642d7db83e456bc8b104788262aaefc11a22339f5a9",
+ "sha256:2fa940963bf02e1d8226027ef461e36af472dea85d36054ff835aeed944dd873",
+ "sha256:305e061fa82f4680607a775b2e8e0bcb071cd2205ac38e6ef48c8dd5ebe1cf37",
+ "sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb",
+ "sha256:35506cb71f47dba416694e67af996bbdefb8e3608f1f78799c2e1f9058b01ceb",
+ "sha256:364f1a7294c91281260364222f535bc427f56d4de1d8ffd718162d21fbbd602e",
+ "sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1",
+ "sha256:3985aea37d40a908f887b34d05111e0aae822943796ebf8338877fee2ab67725",
+ "sha256:3a585a5e42d25f2e71db5f10b171f5e5ea641d3aa44f7df745aa965606111cc2",
+ "sha256:3a64a48d7c917b8f32f25c176df8749ecf08cec17c466114727efe7441e17f6d",
+ "sha256:3f9b1cda8fcb736250d7e8711d4580ebf004a46771432be0ae4796944b5dfa5d",
+ "sha256:41da8def934bf7bec16cb24bd33c0ca62126d2d45d81d17b864bd5ad721393c3",
+ "sha256:4321e8a3d868919bcb1abb1db550d41f2b5b326f72df29e53b2df8b006eb9403",
+ "sha256:453b6035672fecce8007465896a25b28a6b59cfe8fbc974b2563a92f5a92a67c",
+ "sha256:4739a4657179ebf08f85914ce50332495811004cc1747852e8b2041ed2aab9b8",
+ "sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de",
+ "sha256:4a612534770470686cd5431478dc5a1b660eceb410abade6b1b74e320ca98de6",
+ "sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed",
+ "sha256:506c9708dd29b27288f9f8f1140c3cb0e3d8ddb045956d7757b1fa0e0f39a473",
+ "sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6",
+ "sha256:59f9f9df87ed499136db1c2b6c9efb902f964bed42a582ab7af413b6a293e7b0",
+ "sha256:5ab4c823b216a4aeab3fdbf579c5843165756bd9ad87cc6b1c65919c4715f783",
+ "sha256:5c1860627048e302a528333c9307c818c547f214d8659b0705d2195e1a94b274",
+ "sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87",
+ "sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b",
+ "sha256:65f04a9d0b4406f7e51279710b27484af411896246200e461d80d3ba0caa901a",
+ "sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e",
+ "sha256:726c764a90c9218ec9e4f99a33d6bf5ec169163f2ca0fc21b654e88c2abc0abc",
+ "sha256:73c568cc27c473f82480abc15d1301adf333a7ea4f2e813d6a2c7d8b6ba8d0df",
+ "sha256:75fdd787356c1c13a4f40b43c2156276ef7a71eb487d98472476476d803fb2cf",
+ "sha256:774ff60b27a84a85b27b88cd5583899c59940bcc126caca97eb2a9df6aa00c49",
+ "sha256:79307d74ea83465b0152fa23e5e297149506435535282f979f18b9033c0bb025",
+ "sha256:796f466b7942107eb889c08433b6e31b9a7ed31daceaecf8af1be26fb26c0ca8",
+ "sha256:798e46eed9eb10c3adbbacbd3bdb5ecd4cf7064e453d00dbef08802dae6937ff",
+ "sha256:85ee4d25805d4fb23f0a5167a962ef8e002dbfb29c0989378488e32cf2744b62",
+ "sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3",
+ "sha256:89163163c0934854a668ed783a2546a0617f71706a2551a4a0666d91ab365d6b",
+ "sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9",
+ "sha256:8bbcfe2791dfdb7c5e48baf646d37a6a3dcb5a97a032017741dea9f817dca183",
+ "sha256:8f2607185ea89b4af9a604d4c7ec40e45d3ad03ee66998b031134bc510232bb7",
+ "sha256:90d32894d4c6877a87ae00c6b915b609406819dce8bc0d4e962e4de2784e567e",
+ "sha256:92d1f41211d8a8fe412faad962d424d334764c01dac6691c44691c2e4d3eedaf",
+ "sha256:9354ccaa2982bf2188fd5f57f79f800ef622ec67beb8329903abf6b10da7d423",
+ "sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4",
+ "sha256:9ab05b7c58e29bb9e60b70c2e0094c98df79a1e42e397b9bb6eaa989b7a66dd0",
+ "sha256:9c44ee814f499c082e69872d426b624987dbc5943ab06e9bbaa4f81989fdb79e",
+ "sha256:a78befb9cc0a45b5a5a0d537b06f8544c2ebb60d19d02c41ff15da28a9e22d42",
+ "sha256:a947920902420a6ada6ad51892082521978e9dd44a802663b001436e4b771684",
+ "sha256:add5e227e0554d3a52cf390a7635edaffdf4f8fce4fdbcef3cc2055bb396a30c",
+ "sha256:b111b0e9152fa7df870ecaebb0bd30240d9f7fff1f2003bcb4ed0f519941820b",
+ "sha256:b1207af186495f48f72529f8d86671903c8c10127cac6381b11dddc4aaa52df6",
+ "sha256:b3f1368f0a6719ea80013a4eb90ba72e75d7ea67cfc7846db2ca504f3df0169a",
+ "sha256:b6ae2aec8217327d872cbfb2c1694489057b9433afce447955763e6ab015b4c4",
+ "sha256:baa47810c5565274810b726b0dc86d18dce5fd17b190ebdc3890851d7b2a0e74",
+ "sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf",
+ "sha256:bd9e21d34edff5a663c631f850edcb786719c960ce887a5661e9c828a53a95d9",
+ "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c",
+ "sha256:c46d927acd09c67a9fb1416df45c5a04c27e83aae969267e98fba35b74e99525",
+ "sha256:c5433fab222fb072237df3f637d01b81f040a07dcac1cb4a5c75c7aa9ed0bef1",
+ "sha256:c596cc0f4cb574877550ce4ecd51f8037469146addd676d7c1a30ebe6391923f",
+ "sha256:c7f49ce90a71e44f7e1aa9e7ec415b9686bbc6a5961e57eab511015e6759bc11",
+ "sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60",
+ "sha256:c9d28b218d5f9e5f69a0787a196322a5056540cb378cac8ff542b4fa7219966c",
+ "sha256:ca264b9603973c2ad9435c71a8ec8b49f8f715ab5ba421c85a51cde9887e421f",
+ "sha256:cb00ef392e7d684f2754598c02c409f376ddcef857aae796d559e6cacc2d78a5",
+ "sha256:cd2097de91cf03eaa27b3cbdb969addf83f0179c6afc41bbc4513705e013c65d",
+ "sha256:cf6e6dd18927121fec86739f1a8906944703941d000f0639f3eb6281cc601dca",
+ "sha256:d0ee12028daf8cfcf880dd492349a122a64f42c059b6c62a2b0c96a83a8da820",
+ "sha256:d3719596a1ebe7a48a498e8d5d0c4bf7553321d4c3eee1d620628d51351a3928",
+ "sha256:d72f3b5a432a4c546ea4bedc84cce0c3404874f1d1676260b9c7f048a9855451",
+ "sha256:d779d97c834b4278276ec703dc3fc1735fca50af63eb7262f05bdb4e62203d44",
+ "sha256:d8f8a7e317190b2c2d60eb2e8aa835270b008139562d70fe732e1c0020ec53c9",
+ "sha256:d96b264ab7d34bbb2312dedc47ce07cd53f06835eacbc16dde3761f47c3a9e7f",
+ "sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44",
+ "sha256:deeb12a2223fe0135c7ff1356a143d57f95bbf1f4a66584f1fc74df21d86b993",
+ "sha256:df37577a4f8408f7e0ec3205d2a8f87672af8f17008358063a4d6425b6081ce3",
+ "sha256:e1fe01c082f6aafbe5c8faf0ff074f38dfb911d53f07ec333ca03f8f6226debf",
+ "sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a",
+ "sha256:e427eee51149edf962203ff8db75a7514ab89be5cb623fb9cea1f20b54f1107b",
+ "sha256:e6ded41aeba3603f9728ed2b6196e4df875348ab97b28fc8afff115ed42ba7a7",
+ "sha256:e7acbaba9703d5de82a2c98ae6a0f59ab9770ab5af5fa35e43a303aee962cf65",
+ "sha256:e8269062060212b373316fe69236096aaf4c49022d267c6736eebd66bbbc60bb",
+ "sha256:e8547883d7b96ef2e5fe22b88f8a4c8725a56e7f4abafff20fd5272d634c7ecb",
+ "sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c",
+ "sha256:edb868841f84c111255ba5e80339d386d937ec1fdce419518ce1bd9370fac5b6",
+ "sha256:ef2fb241de583934c9915a33120ecc06d94aa3381a134570f59eed784e87001e",
+ "sha256:efe1a211fe1fd14762adea941e3cfd6c611a136e28da6c39272dbb7a1bbe6a86",
+ "sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626",
+ "sha256:f8c593c6e71c07866ec6bfb790e202a833eeec885022296aff6b9e0b92d6a70e",
+ "sha256:f8ec0259d3f26c62aed4d73b198c53e316ae11f0f69c8fbe6682c6dcfa0fcce2",
+ "sha256:fd990541982a24281d12b67a335e44f117e4c6cbad3c3b75c7dea68bf4ce3a67"
],
"markers": "python_version >= '3.9'",
- "version": "==0.11.0"
+ "version": "==0.12.0"
},
"jsonschema": {
"hashes": [
@@ -976,64 +1179,115 @@
"markers": "python_version >= '3.9'",
"version": "==2025.9.1"
},
- "lazy-object-proxy": {
- "hashes": [
- "sha256:029d2b355076710505c9545aef5ab3f750d89779310e26ddf2b7b23f6ea03cd8",
- "sha256:08c465fb5cd23527512f9bd7b4c7ba6cec33e28aad36fbbe46bf7b858f9f3f7f",
- "sha256:0a83c6f7a6b2bfc11ef3ed67f8cbe99f8ff500b05655d8e7df9aab993a6abc95",
- "sha256:1192e8c2f1031a6ff453ee40213afa01ba765b3dc861302cd91dbdb2e2660b00",
- "sha256:14e348185adbd03ec17d051e169ec45686dcd840a3779c9d4c10aabe2ca6e1c0",
- "sha256:15400b18893f345857b9e18b9bd87bd06aba84af6ed086187add70aeaa3f93f1",
- "sha256:1cf69cd1a6c7fe2dbcc3edaa017cf010f4192e53796538cc7d5e1fedbfa4bcff",
- "sha256:1f5a462d92fd0cfb82f1fab28b51bfb209fabbe6aabf7f0d51472c0c124c0c61",
- "sha256:256262384ebd2a77b023ad02fbcc9326282bcfd16484d5531154b02bc304f4c5",
- "sha256:31020c84005d3daa4cc0fa5a310af2066efe6b0d82aeebf9ab199292652ff036",
- "sha256:338ab2f132276203e404951205fe80c3fd59429b3a724e7b662b2eb539bb1be9",
- "sha256:3605b632e82a1cbc32a1e5034278a64db555b3496e0795723ee697006b980508",
- "sha256:3d3964fbd326578bcdfffd017ef101b6fb0484f34e731fe060ba9b8816498c36",
- "sha256:424a8ab6695400845c39f13c685050eab69fa0bbac5790b201cd27375e5e41d7",
- "sha256:4a79b909aa16bde8ae606f06e6bbc9d3219d2e57fb3e0076e17879072b742c65",
- "sha256:4ab2c584e3cc8be0dfca422e05ad30a9abe3555ce63e9ab7a559f62f8dbc6ff9",
- "sha256:53c7fd99eb156bbb82cbc5d5188891d8fdd805ba6c1e3b92b90092da2a837073",
- "sha256:563d2ec8e4d4b68ee7848c5ab4d6057a6d703cb7963b342968bb8758dda33a23",
- "sha256:61d5e3310a4aa5792c2b599a7a78ccf8687292c8eb09cf187cca8f09cf6a7519",
- "sha256:6763941dbf97eea6b90f5b06eb4da9418cc088fce0e3883f5816090f9afcde4a",
- "sha256:67f07ab742f1adfb3966c40f630baaa7902be4222a17941f3d85fd1dae5565ff",
- "sha256:717484c309df78cedf48396e420fa57fc8a2b1f06ea889df7248fdd156e58847",
- "sha256:75ba769017b944fcacbf6a80c18b2761a1795b03f8899acdad1f1c39db4409be",
- "sha256:7601ec171c7e8584f8ff3f4e440aa2eebf93e854f04639263875b8c2971f819f",
- "sha256:7b22c2bbfb155706b928ac4d74c1a63ac8552a55ba7fff4445155523ea4067e1",
- "sha256:800f32b00a47c27446a2b767df7538e6c66a3488632c402b4fb2224f9794f3c0",
- "sha256:81d1852fb30fab81696f93db1b1e55a5d1ff7940838191062f5f56987d5fcc3e",
- "sha256:86fd61cb2ba249b9f436d789d1356deae69ad3231dc3c0f17293ac535162672e",
- "sha256:8c40b3c9faee2e32bfce0df4ae63f4e73529766893258eca78548bac801c8f66",
- "sha256:8ee0d6027b760a11cc18281e702c0309dd92da458a74b4c15025d7fc490deede",
- "sha256:997b1d6e10ecc6fb6fe0f2c959791ae59599f41da61d652f6c903d1ee58b7370",
- "sha256:a61095f5d9d1a743e1e20ec6d6db6c2ca511961777257ebd9b288951b23b44fa",
- "sha256:a6b7ea5ea1ffe15059eb44bcbcb258f97bcb40e139b88152c40d07b1a1dfc9ac",
- "sha256:ae575ad9b674d0029fc077c5231b3bc6b433a3d1a62a8c363df96974b5534728",
- "sha256:be5fe974e39ceb0d6c9db0663c0464669cf866b2851c73971409b9566e880eab",
- "sha256:be9045646d83f6c2664c1330904b245ae2371b5c57a3195e4028aedc9f999655",
- "sha256:c1ca33565f698ac1aece152a10f432415d1a2aa9a42dfe23e5ba2bc255ab91f6",
- "sha256:c3b2e0af1f7f77c4263759c4824316ce458fabe0fceadcd24ef8ca08b2d1e402",
- "sha256:c4fcbe74fb85df8ba7825fa05eddca764138da752904b378f0ae5ab33a36c308",
- "sha256:c9defba70ab943f1df98a656247966d7729da2fe9c2d5d85346464bf320820a3",
- "sha256:cc6e3614eca88b1c8a625fc0a47d0d745e7c3255b21dac0e30b3037c5e3deeb8",
- "sha256:d01c7819a410f7c255b20799b65d36b414379a30c6f1684c7bd7eb6777338c1b",
- "sha256:efff4375a8c52f55a145dc8487a2108c2140f0bec4151ab4e1843e52eb9987ad",
- "sha256:fdc70d81235fc586b9e3d1aeef7d1553259b62ecaae9db2167a5d2550dcc391a"
+ "keyring": {
+ "hashes": [
+ "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f",
+ "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b"
],
"markers": "python_version >= '3.9'",
- "version": "==1.12.0"
+ "version": "==25.7.0"
},
"litellm": {
"hashes": [
- "sha256:1b3a1b17bd521a0ad25226fb62a912602c803922aabb4a16adf83834673be574",
- "sha256:e3398fb2575b98726e787c0a1481daed5938d58cafdcd96fbca80c312221af3e"
+ "sha256:4a4aff7558945c2f7e5c6523e67c1b5525a46b10b0e1ad6b8f847cb13b16779e",
+ "sha256:9b3e561efaba0eb1291cb1555d3dcb7283cf7f3cb65aadbcdb42e2a8765898c8"
],
"index": "pypi",
- "markers": "python_version not in '2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7' and python_version >= '3.8'",
- "version": "==1.77.7"
+ "markers": "python_version >= '3.9' and python_version < '4.0'",
+ "version": "==1.80.10"
+ },
+ "lupa": {
+ "hashes": [
+ "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d",
+ "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983",
+ "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad",
+ "sha256:05681f8ffb41f0c7fbb9ca859cc3a7e4006e9c6350d25358b535c5295c6a9928",
+ "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a",
+ "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf",
+ "sha256:10c191bc1d5565e4360d884bea58320975ddb33270cdf9a9f55d1a1efe79aa03",
+ "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f",
+ "sha256:153d2cc6b643f7efb9cfc0c6bb55ec784d5bac1a3660cfc5b958a7b8f38f4a75",
+ "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291",
+ "sha256:202160e80dbfddfb79316692a563d843b767e0f6787bbd1c455f9d54052efa6c",
+ "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31",
+ "sha256:21f2b5549681c2a13b1170a26159d30875d367d28f0247b81ca347222c755038",
+ "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c",
+ "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c",
+ "sha256:241f4ddab33b9a686fc76667241bebc39a06b74ec40d79ec222f5add9000fe57",
+ "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e",
+ "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce",
+ "sha256:3fa8777e16f3ded50b72967dc17e23f5a08e4f1e2c9456aff2ebdb57f5b2869f",
+ "sha256:43eb6e43ea8512d0d65b995d36dd9d77aa02598035e25b84c23a1b58700c9fb2",
+ "sha256:4446396ca3830be0c106c70db4b4f622c37b2d447874c07952cafb9c57949a4a",
+ "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe",
+ "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56",
+ "sha256:559714053018d9885cc8c36a33c5b7eb9aad30fb6357719cac3ce4dc6b39157e",
+ "sha256:561a8e3be800827884e767a694727ed8482d066e0d6edfcbf423b05e63b05535",
+ "sha256:57ac88a00ce59bd9d4ddcd4fca8e02564765725f5068786b011c9d1be3de20c5",
+ "sha256:5826e687c89995a6eaafeae242071ba16448eec1a9ee8e17ed48551b5d1e21c2",
+ "sha256:5871935cb36d1d22f9c04ac0db75c06751bd95edcfa0d9309f732de908e297a9",
+ "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142",
+ "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323",
+ "sha256:5deede7c5b36ab64f869dae4831720428b67955b0bb186c8349cf6ea121c852b",
+ "sha256:60a403de8cab262a4fe813085dd77010effa6e2eb1886db2181df803140533b1",
+ "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685",
+ "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa",
+ "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310",
+ "sha256:66eea57630eab5e6f49fdc5d7811c0a2a41f2011be4ea56a087ea76112011eb7",
+ "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7",
+ "sha256:6b3dabda836317e63c5ad052826e156610f356a04b3003dfa0dbe66b5d54d671",
+ "sha256:6d988c0f9331b9f2a5a55186701a25444ab10a1432a1021ee58011499ecbbdd5",
+ "sha256:6deef8f851d6afb965c84849aa5b8c38856942df54597a811ce0369ced678610",
+ "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203",
+ "sha256:728c466e91174dad238f8a9c1cbdb8e69ffe559df85f87ee76edac3395300949",
+ "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58",
+ "sha256:80b22923aa4023c86c0097b235615f89d469a0c4eee0489699c494d3367c4c85",
+ "sha256:86f04901f920bbf7c0cac56807dc9597e42347123e6f1f3ca920f15f54188ce5",
+ "sha256:8726d1c123bbe9fbb974ce29825e94121824e66003038ff4532c14cc2ed0c51c",
+ "sha256:8897dc6c3249786b2cdf2f83324febb436193d4581b6a71dea49f77bf8b19bb0",
+ "sha256:8dbdcbe818c02a2f56f5ab5ce2de374dab03e84b25266cfbaef237829bc09b3f",
+ "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8",
+ "sha256:9505ae600b5c14f3e17e70f87f88d333717f60411faca1ddc6f3e61dce85fa9e",
+ "sha256:9591700991e333b70dd92b48f152eb4731b8b24af671a9f6f721b74d68ed4499",
+ "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8",
+ "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9",
+ "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80",
+ "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff",
+ "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18",
+ "sha256:a8fcee258487cf77cdd41560046843bb38c2e18989cd19671dd1e2596f798306",
+ "sha256:aef1a8bc10c50695e1a33a07dbef803b93eb97fc150fdb19858d704a603a67dd",
+ "sha256:af880a62d47991cae78b8e9905c008cbfdc4a3a9723a66310c2634fc7644578c",
+ "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be",
+ "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9",
+ "sha256:b4b2e9b3795a9897cf6cfcc58d08210fdc0d13ab47c9a0e13858c68932d8353c",
+ "sha256:b683fbd867c2e54c44a686361b75eee7e7a790da55afdbe89f1f23b106de0274",
+ "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67",
+ "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5",
+ "sha256:bf28f68ae231b72008523ab5ac23835ba0f76e0e99ec38b59766080a84eb596a",
+ "sha256:c17f6b6193ced33cc7ca0b2b08b319a1b3501b014a3a3f9999c01cafc04c40f5",
+ "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f",
+ "sha256:c781170bc7134704ae317a66204d30688b41d3e471e17e659987ea4947e11f20",
+ "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f",
+ "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953",
+ "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9",
+ "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380",
+ "sha256:d2f656903a2ed2e074bf2b7d300968028dfa327a45b055be8e3b51ef0b82f9bf",
+ "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134",
+ "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1",
+ "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772",
+ "sha256:defaf188fde8f7a1e5ce3a5e6d945e533b8b8d547c11e43b96c9b7fe527f56dc",
+ "sha256:e4656a39d93dfa947cf3db56dc16c7916cb0cc8024acd3a952071263f675df64",
+ "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9",
+ "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6",
+ "sha256:ebe1bbf48259382c72a6fe363dea61a0fd6fe19eab95e2ae881e20f3654587bf",
+ "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75",
+ "sha256:ef8dfa7fe08bc3f4591411b8945bbeb15af8512c3e7ad5e9b1e3a9036cdbbce7",
+ "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3",
+ "sha256:f4e159e7d814171199b246f9235ca8961f6461ea8c1165ab428afa13c9289a94",
+ "sha256:fa6c1379e83d4104065c151736250a09f3a99e368423c7a20f9c59b15945e9fc",
+ "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52"
+ ],
+ "version": "==2.6"
},
"markdown-it-py": {
"hashes": [
@@ -1140,11 +1394,11 @@
},
"mcp": {
"hashes": [
- "sha256:39b8ca25460c578ee2cdad33feeea122694cfdf73eef58bee76c42f6ef0589df",
- "sha256:ec917be9a5d31b09ba331e1768aa576e0af45470d657a0319996a20a57d7d633"
+ "sha256:aeaad134664ce56f2721d1abf300666a1e8348563f4d3baff361c3b652448efc",
+ "sha256:db130e103cc50ddc3dffc928382f33ba3eaef0b711f7a87c05e7ded65b1ca062"
],
"markers": "python_version >= '3.10'",
- "version": "==1.16.0"
+ "version": "==1.24.0"
},
"mdurl": {
"hashes": [
@@ -1316,107 +1570,99 @@
},
"neo4j": {
"hashes": [
- "sha256:c98734c855b457e7a976424dc04446d652838d00907d250d6e9a595e88892378",
- "sha256:dc3fc1c99f6da2293d9deefead1e31dd7429bbb513eccf96e4134b7dbf770243"
+ "sha256:7fb79e166e281aafd67d521f6611763ebcdc529f26db506c5605f91ddcd825ea",
+ "sha256:a92023854da96aed4270e0d03d6429cdd7f0d3335eae977370934f4732de5678"
],
"markers": "python_version >= '3.10'",
- "version": "==6.0.2"
+ "version": "==6.0.3"
},
"numpy": {
"hashes": [
- "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b",
- "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54",
- "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d",
- "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5",
- "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970",
- "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8",
- "sha256:1e02c7159791cd481e1e6d5ddd766b62a4d5acf8df4d4d1afe35ee9c5c33a41e",
- "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3",
- "sha256:2e267c7da5bf7309670523896df97f93f6e469fb931161f483cd6882b3b1a5dc",
- "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e",
- "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe",
- "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5",
- "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b",
- "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652",
- "sha256:433bf137e338677cebdd5beac0199ac84712ad9d630b74eceeb759eaa45ddf30",
- "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d",
- "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb",
- "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7",
- "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a",
- "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf",
- "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93",
- "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8",
- "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19",
- "sha256:74c2a948d02f88c11a3c075d9733f1ae67d97c6bdb97f2bb542f980458b257e7",
- "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1",
- "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b",
- "sha256:7af05ed4dc19f308e1d9fc759f36f21921eb7bbfc82843eeec6b2a2863a0aefa",
- "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d",
- "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc",
- "sha256:8596ba2f8af5f93b01d97563832686d20206d303024777f6dfc2e7c7c3f1850e",
- "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86",
- "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097",
- "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a",
- "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7",
- "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30",
- "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c",
- "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8",
- "sha256:99683cbe0658f8271b333a1b1b4bb3173750ad59c0c61f5bbdc5b318918fffe3",
- "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe",
- "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00",
- "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6",
- "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe",
- "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd",
- "sha256:afd07d377f478344ec6ca2b8d4ca08ae8bd44706763d1efb56397de606393f48",
- "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae",
- "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f",
- "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a",
- "sha256:bc92a5dedcc53857249ca51ef29f5e5f2f8c513e22cfb90faeb20343b8c6f7a6",
- "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5",
- "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0",
- "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25",
- "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593",
- "sha256:cd4260f64bc794c3390a63bf0728220dd1a68170c169088a1e0dfa2fde1be12f",
- "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea",
- "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421",
- "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf",
- "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7",
- "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7",
- "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf",
- "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20",
- "sha256:d9d537a39cc9de668e5cd0e25affb17aec17b577c6b3ae8a3d866b479fbe88d0",
- "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e",
- "sha256:dca2d0fc80b3893ae72197b39f69d55a3cd8b17ea1b50aa4c62de82419936150",
- "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029",
- "sha256:e1ec5615b05369925bd1125f27df33f3b6c8bc10d788d5999ecd8769a1fa04db",
- "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021",
- "sha256:e7e946c7170858a0295f79a60214424caac2ffdb0063d4d79cb681f9aa0aa569",
- "sha256:eb63d443d7b4ffd1e873f8155260d7f58e7e4b095961b01c91062935c2491e57",
- "sha256:ec9d249840f6a565f58d8f913bccac2444235025bbb13e9a4681783572ee3caa",
- "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea",
- "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc",
- "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf",
- "sha256:f0ddb4b96a87b6728df9362135e764eac3cfa674499943ebc44ce96c478ab125",
- "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf"
+ "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b",
+ "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae",
+ "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3",
+ "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0",
+ "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b",
+ "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa",
+ "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28",
+ "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e",
+ "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017",
+ "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41",
+ "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e",
+ "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63",
+ "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9",
+ "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8",
+ "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff",
+ "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7",
+ "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139",
+ "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4",
+ "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748",
+ "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952",
+ "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd",
+ "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b",
+ "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce",
+ "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f",
+ "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5",
+ "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42",
+ "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7",
+ "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248",
+ "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e",
+ "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3",
+ "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b",
+ "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e",
+ "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0",
+ "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa",
+ "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a",
+ "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5",
+ "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d",
+ "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4",
+ "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c",
+ "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52",
+ "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5",
+ "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d",
+ "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1",
+ "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c",
+ "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18",
+ "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7",
+ "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188",
+ "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218",
+ "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2",
+ "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903",
+ "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c",
+ "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c",
+ "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234",
+ "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82",
+ "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39",
+ "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf",
+ "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20",
+ "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946",
+ "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0",
+ "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9",
+ "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff",
+ "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad",
+ "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227",
+ "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10",
+ "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e",
+ "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf",
+ "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769",
+ "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310",
+ "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425",
+ "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013",
+ "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c",
+ "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb",
+ "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d",
+ "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520"
],
"markers": "python_version >= '3.11'",
- "version": "==2.3.3"
+ "version": "==2.3.5"
},
"openai": {
"hashes": [
- "sha256:bc49d077a8bf0e370eec4d038bc05e232c20855a19df0b58e5b3e5a8da7d33e0",
- "sha256:d222e63436e33f3134a3d7ce490dc2d2f146fa98036eb65cc225df3ce163916f"
+ "sha256:746521065fed68df2f9c2d85613bb50844343ea81f60009b60e6a600c9352c79",
+ "sha256:9ff633b07a19469ec476b1e2b5b26c5ef700886524a7a72f65e6f0b5203142d5"
],
- "markers": "python_version >= '3.8'",
- "version": "==2.2.0"
- },
- "openapi-core": {
- "hashes": [
- "sha256:421e753da56c391704454e66afe4803a290108590ac8fa6f4a4487f4ec11f2d3",
- "sha256:ef7210e83a59394f46ce282639d8d26ad6fc8094aa904c9c16eb1bac8908911f"
- ],
- "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'",
- "version": "==0.19.5"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.13.0"
},
"openapi-pydantic": {
"hashes": [
@@ -1426,21 +1672,45 @@
"markers": "python_version >= '3.8' and python_version < '4.0'",
"version": "==0.5.1"
},
- "openapi-schema-validator": {
+ "opentelemetry-api": {
"hashes": [
- "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee",
- "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3"
+ "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950",
+ "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c"
],
- "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'",
- "version": "==0.6.3"
+ "markers": "python_version >= '3.9'",
+ "version": "==1.39.1"
},
- "openapi-spec-validator": {
+ "opentelemetry-exporter-prometheus": {
"hashes": [
- "sha256:4bbdc0894ec85f1d1bea1d6d9c8b2c3c8d7ccaa13577ef40da9c006c9fd0eb60",
- "sha256:cc029309b5c5dbc7859df0372d55e9d1ff43e96d678b9ba087f7c56fc586f734"
+ "sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd",
+ "sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b"
],
- "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'",
- "version": "==0.7.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==0.60b1"
+ },
+ "opentelemetry-instrumentation": {
+ "hashes": [
+ "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d",
+ "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==0.60b1"
+ },
+ "opentelemetry-sdk": {
+ "hashes": [
+ "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c",
+ "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==1.39.1"
+ },
+ "opentelemetry-semantic-conventions": {
+ "hashes": [
+ "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953",
+ "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==0.60b1"
},
"packaging": {
"hashes": [
@@ -1450,13 +1720,6 @@
"markers": "python_version >= '3.8'",
"version": "==25.0"
},
- "parse": {
- "hashes": [
- "sha256:967095588cb802add9177d0c0b6133b5ba33b1ea9007ca800e526f42a85af558",
- "sha256:b41d604d16503c79d81af5165155c0b20f6c8d6c559efa66b4b695c3e5a0a0ce"
- ],
- "version": "==1.20.2"
- },
"pathable": {
"hashes": [
"sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2",
@@ -1465,216 +1728,261 @@
"markers": "python_full_version >= '3.7.0' and python_full_version < '4.0.0'",
"version": "==0.4.4"
},
+ "pathvalidate": {
+ "hashes": [
+ "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f",
+ "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==3.3.1"
+ },
+ "platformdirs": {
+ "hashes": [
+ "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda",
+ "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==4.5.1"
+ },
"posthog": {
"hashes": [
- "sha256:b09a7e65a042ec416c28874b397d3accae412a80a8b0ef3fa686fbffc99e4d4b",
- "sha256:ee5c5ad04b857d96d9b7a4f715e23916a2f206bfcf25e5a9d328a3d27664b0d3"
+ "sha256:1fb97b11960e24fcf0b80f0a6450b2311478e5a3ee6ea3c6f9284ff89060a876",
+ "sha256:f9d4e32c1c0f2110256b1aae7046ed90af312c1dbb1eecc6a9cb427733b22970"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==7.4.0"
+ },
+ "prometheus-client": {
+ "hashes": [
+ "sha256:6ae8f9081eaaaf153a2e959d2e6c4f4fb57b12ef76c8c7980202f1e57b48b2ce",
+ "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99"
],
"markers": "python_version >= '3.9'",
- "version": "==6.7.6"
+ "version": "==0.23.1"
},
"propcache": {
"hashes": [
- "sha256:009093c9b5dbae114a5958e6a649f8a5d94dd6866b0f82b60395eb92c58002d4",
- "sha256:015b2ca2f98ea9e08ac06eecc409d5d988f78c5fd5821b2ad42bc9afcd6b1557",
- "sha256:01c0ebc172ca28e9d62876832befbf7f36080eee6ed9c9e00243de2a8089ad57",
- "sha256:02e071548b6a376e173b0102c3f55dc16e7d055b5307d487e844c320e38cacf2",
- "sha256:0363a696a9f24b37a04ed5e34c2e07ccbe92798c998d37729551120a1bb744c4",
- "sha256:0596d2ae99d74ca436553eb9ce11fe4163dc742fcf8724ebe07d7cb0db679bb1",
- "sha256:075ca32384294434344760fdcb95f7833e1d7cf7c4e55f0e726358140179da35",
- "sha256:077a32977399dc05299b16e793210341a0b511eb0a86d1796873e83ce47334cc",
- "sha256:082a643479f49a6778dcd68a80262fc324b14fd8e9b1a5380331fe41adde1738",
- "sha256:087e2d3d7613e1b59b2ffca0daabd500c1a032d189c65625ee05ea114afcad0b",
- "sha256:0964c55c95625193defeb4fd85f8f28a9a754ed012cab71127d10e3dc66b1373",
- "sha256:0b04ac2120c161416c866d0b6a4259e47e92231ff166b518cc0efb95777367c3",
- "sha256:0b12df77eb19266efd146627a65b8ad414f9d15672d253699a50c8205661a820",
- "sha256:0cd30341142c68377cf3c4e2d9f0581e6e528694b2d57c62c786be441053d2fc",
- "sha256:0ea11fceb31fa95b0fa2007037f19e922e2caceb7dc6c6cac4cb56e2d291f1a2",
- "sha256:184c779363740d6664982ad05699f378f7694220e2041996f12b7c2a4acdcad0",
- "sha256:1927b78dd75fc31a7fdc76cc7039e39f3170cb1d0d9a271e60f0566ecb25211a",
- "sha256:1cdabd60e109506462e6a7b37008e57979e737dc6e7dfbe1437adcfe354d1a0a",
- "sha256:1e7fa29c71ffa8d6a37324258737d09475f84715a6e8c350f67f0bc8e5e44993",
- "sha256:1e7fd82d4a5b7583588f103b0771e43948532f1292105f13ee6f3b300933c4ca",
- "sha256:2015218812ee8f13bbaebc9f52b1e424cc130b68d4857bef018e65e3834e1c4d",
- "sha256:213eb0d3bc695a70cffffe11a1c2e1c2698d89ffd8dba35a49bc44a035d45c93",
- "sha256:2166466a666a5bebc332cd209cad77d996fad925ca7e8a2a6310ba9e851ae641",
- "sha256:227892597953611fce2601d49f1d1f39786a6aebc2f253c2de775407f725a3f6",
- "sha256:22f589652ee38de96aa58dd219335604e09666092bc250c1d9c26a55bcef9932",
- "sha256:236c8da353ea7c22a8e963ab78cddb1126f700ae9538e2c4c6ef471e5545494b",
- "sha256:24403152e41abf09488d3ae9c0c3bf7ff93e2fb12b435390718f21810353db28",
- "sha256:26692850120241a99bb4a4eec675cd7b4fdc431144f0d15ef69f7f8599f6165f",
- "sha256:2a4bf309d057327f1f227a22ac6baf34a66f9af75e08c613e47c4d775b06d6c7",
- "sha256:2af6de831a26f42a3f94592964becd8d7f238551786d7525807f02e53defbd13",
- "sha256:2c46d37955820dd883cf9156ceb7825b8903e910bdd869902e20a5ac4ecd2c8b",
- "sha256:33ad7d37b9a386f97582f5d042cc7b8d4b3591bb384cf50866b749a17e4dba90",
- "sha256:34000e31795bdcda9826e0e70e783847a42e3dcd0d6416c5d3cb717905ebaec0",
- "sha256:381c84a445efb8c9168f1393a5a7c566de22edc42bfe207a142fff919b37f5d9",
- "sha256:399c73201d88c856a994916200d7cba41d7687096f8eb5139eb68f02785dc3f7",
- "sha256:39f0f6a3b56e82dc91d84c763b783c5c33720a33c70ee48a1c13ba800ac1fa69",
- "sha256:4596c12aa7e3bb2abf158ea8f79eb0fb4851606695d04ab846b2bb386f5690a1",
- "sha256:4a52c25a51d5894ba60c567b0dbcf73de2f3cd642cf5343679e07ca3a768b085",
- "sha256:4bf95be277fbb51513895c2cecc81ab12a421cdbd8837f159828a919a0167f96",
- "sha256:4c2735d3305e6cecab6e53546909edf407ad3da5b9eeaf483f4cf80142bb21be",
- "sha256:4c491462e1dc80f9deb93f428aad8d83bb286de212837f58eb48e75606e7726c",
- "sha256:515b610a364c8cdd2b72c734cc97dece85c416892ea8d5c305624ac8734e81db",
- "sha256:545987971b2aded25ba4698135ea0ae128836e7deb6e18c29a581076aaef44aa",
- "sha256:55a54de5266bc44aa274915cdf388584fa052db8748a869e5500ab5993bac3f4",
- "sha256:566552ed9b003030745e5bc7b402b83cf3cecae1bade95262d78543741786db5",
- "sha256:5710b1c01472542bb024366803812ca13e8774d21381bcfc1f7ae738eeb38acc",
- "sha256:5a531d29d7b873b12730972237c48b1a4e5980b98cf21b3f09fa4710abd3a8c3",
- "sha256:5b113feeda47f908562d9a6d0e05798ad2f83d4473c0777dafa2bc7756473218",
- "sha256:5e0a5bc019014531308fb67d86066d235daa7551baf2e00e1ea7b00531f6ea85",
- "sha256:626ec13592928b677f48ff5861040b604b635e93d8e2162fb638397ea83d07e8",
- "sha256:659a0ea6d9017558ed7af00fb4028186f64d0ba9adfc70a4d2c85fcd3d026321",
- "sha256:65ff56a31f25925ef030b494fe63289bf07ef0febe6da181b8219146c590e185",
- "sha256:681a168d06284602d56e97f09978057aa88bcc4177352b875b3d781df4efd4cb",
- "sha256:6a6a36b94c09711d6397d79006ca47901539fbc602c853d794c39abd6a326549",
- "sha256:6d1f67dad8cc36e8abc2207a77f3f952ac80be7404177830a7af4635a34cbc16",
- "sha256:6ebc6e2e65c31356310ddb6519420eaa6bb8c30fbd809d0919129c89dcd70f4c",
- "sha256:71a400b2f0b079438cc24f9a27f02eff24d8ef78f2943f949abc518b844ade3d",
- "sha256:71c45f02ffbb8a21040ae816ceff7f6cd749ffac29fc0f9daa42dc1a9652d577",
- "sha256:728d98179e92d77096937fdfecd2c555a3d613abe56c9909165c24196a3b5012",
- "sha256:72b51340047ac43b3cf388eebd362d052632260c9f73a50882edbb66e589fd44",
- "sha256:779aaae64089e2f4992e993faea801925395d26bb5de4a47df7ef7f942c14f80",
- "sha256:783e91595cf9b66c2deda17f2e8748ae8591aa9f7c65dcab038872bfe83c5bb1",
- "sha256:790286d3d542c0ef9f6d0280d1049378e5e776dcba780d169298f664c39394db",
- "sha256:7aa8cc5c94e682dce91cb4d12d7b81c01641f4ef5b3b3dc53325d43f0e3b9f2e",
- "sha256:7d51f70f77950f8efafed4383865d3533eeee52d8a0dd1c35b65f24de41de4e0",
- "sha256:7da5c4c72ae40fd3ce87213ab057db66df53e55600d0b9e72e2b7f5a470a2cc4",
- "sha256:7dfa60953169d2531dd8ae306e9c27c5d4e5efe7a2ba77049e8afdaece062937",
- "sha256:7ea86eb32e74f9902df57e8608e8ac66f1e1e1d24d1ed2ddeb849888413b924d",
- "sha256:7f088e21d15b3abdb9047e4b7b7a0acd79bf166893ac2b34a72ab1062feb219e",
- "sha256:83ae2f5343f6f06f4c91ae530d95f56b415f768f9c401a5ee2a10459cf74370b",
- "sha256:84f847e64f4d1a232e50460eebc1196642ee9b4c983612f41cd2d44fd2fe7c71",
- "sha256:858eaabd2191dd0da5272993ad08a748b5d3ae1aefabea8aee619b45c2af4a64",
- "sha256:8659f995b19185179474b18de8755689e1f71e1334d05c14e1895caa4e409cf7",
- "sha256:88d50d662c917ec2c9d3858920aa7b9d5bfb74ab9c51424b775ccbe683cb1b4e",
- "sha256:892a072e5b19c3f324a4f8543c9f7e8fc2b0aa08579e46f69bdf0cfc1b440454",
- "sha256:8d18d796ffecdc8253742fd53a94ceee2e77ad149eb9ed5960c2856b5f692f71",
- "sha256:92bc43a1ab852310721ce856f40a3a352254aa6f5e26f0fad870b31be45bba2e",
- "sha256:944de70384c62d16d4a00c686b422aa75efbc67c4addaebefbb56475d1c16034",
- "sha256:94a278c45e6463031b5a8278e40a07edf2bcc3b5379510e22b6c1a6e6498c194",
- "sha256:94b0f7407d18001dbdcbb239512e753b1b36725a6e08a4983be1c948f5435f79",
- "sha256:96153e037ae065bb71cae889f23c933190d81ae183f3696a030b47352fd8655d",
- "sha256:9ba68c57cde9c667f6b65b98bc342dfa7240b1272ffb2c24b32172ee61b6d281",
- "sha256:a1d5e474d43c238035b74ecf997f655afa67f979bae591ac838bb3fbe3076392",
- "sha256:a4efbaf10793fd574c76a5732c75452f19d93df6e0f758c67dd60552ebd8614b",
- "sha256:a60634a9de41f363923c6adfb83105d39e49f7a3058511563ed3de6748661af6",
- "sha256:a7f06f077fc4ef37e8a37ca6bbb491b29e29db9fb28e29cf3896aad10dbd4137",
- "sha256:a8ef2ea819549ae2e8698d2ec229ae948d7272feea1cb2878289f767b6c585a4",
- "sha256:a9725d96a81e17e48a0fe82d0c3de2f5e623d7163fec70a6c7df90753edd1bec",
- "sha256:ab9c1bd95ebd1689f0e24f2946c495808777e9e8df7bb3c1dfe3e9eb7f47fe0d",
- "sha256:abe04e7aa5ab2e4056fcf3255ebee2071e4a427681f76d4729519e292c46ecc1",
- "sha256:ae3adf88a66f5863cf79394bc359da523bb27a2ed6ba9898525a6a02b723bfc5",
- "sha256:b2f29697d1110e8cdf7a39cc630498df0082d7898b79b731c1c863f77c6e8cfc",
- "sha256:b730048ae8b875e2c0af1a09ca31b303fc7b5ed27652beec03fa22b29545aec9",
- "sha256:bcb5bfac5b9635e6fc520c8af6efc7a0a56f12a1fe9e9d3eb4328537e316dd6a",
- "sha256:bd6c6dba1a3b8949e08c4280071c86e38cb602f02e0ed6659234108c7a7cd710",
- "sha256:c0e1c218fff95a66ad9f2f83ad41a67cf4d0a3f527efe820f57bde5fda616de4",
- "sha256:c1443fa4bb306461a3a8a52b7de0932a2515b100ecb0ebc630cc3f87d451e0a9",
- "sha256:c1ad731253eb738f9cadd9fa1844e019576c70bca6a534252e97cf33a57da529",
- "sha256:c20d796210720455086ef3f85adc413d1e41d374742f9b439354f122bbc3b528",
- "sha256:c2e274f3d1cbb2ddcc7a55ce3739af0f8510edc68a7f37981b2258fa1eedc833",
- "sha256:c3f4b125285d354a627eb37f3ea7c13b8842c7c0d47783581d0df0e272dbf5f0",
- "sha256:c9b8119244d122241a9c4566bce49bb20408a6827044155856735cf14189a7da",
- "sha256:cd6e22255ed73efeaaeb1765505a66a48a9ec9ebc919fce5ad490fe5e33b1555",
- "sha256:cd8684f628fe285ea5c86f88e1c30716239dc9d6ac55e7851a4b7f555b628da3",
- "sha256:cdb0cecafb528ab15ed89cdfed183074d15912d046d3e304955513b50a34b907",
- "sha256:d74aa60b1ec076d4d5dcde27c9a535fc0ebb12613f599681c438ca3daa68acac",
- "sha256:d7f008799682e8826ce98f25e8bc43532d2cd26c187a1462499fa8d123ae054f",
- "sha256:d9a8d277dc218ddf04ec243a53ac309b1afcebe297c0526a8f82320139b56289",
- "sha256:da47070e1340a1639aca6b1c18fe1f1f3d8d64d3a1f9ddc67b94475f44cd40f3",
- "sha256:da584d917a1a17f690fc726617fd2c3f3006ea959dae5bb07a5630f7b16f9f5f",
- "sha256:de536cf796abc5b58d11c0ad56580215d231d9554ea4bb6b8b1b3bed80aa3234",
- "sha256:de8e310d24b5a61de08812dd70d5234da1458d41b059038ee7895a9e4c8cae79",
- "sha256:df7107a91126a495880576610ae989f19106e1900dd5218d08498391fa43b31d",
- "sha256:e0ce7f3d1faf7ad58652ed758cc9753049af5308b38f89948aa71793282419c5",
- "sha256:e2d01fd53e89cb3d71d20b8c225a8c70d84660f2d223afc7ed7851a4086afe6d",
- "sha256:e5227da556b2939da6125cda1d5eecf9e412e58bc97b41e2f192605c3ccbb7c2",
- "sha256:e6229ad15366cd8b6d6b4185c55dd48debf9ca546f91416ba2e5921ad6e210a6",
- "sha256:e878553543ece1f8006d0ba4d096b40290580db173bfb18e16158045b9371335",
- "sha256:eb77a85253174bf73e52c968b689d64be62d71e8ac33cabef4ca77b03fb4ef92",
- "sha256:f114a3e1f8034e2957d34043b7a317a8a05d97dfe8fddb36d9a2252c0117dbbc",
- "sha256:f495007ada16a4e16312b502636fafff42a9003adf1d4fb7541e0a0870bc056f",
- "sha256:f5c82af8e329c3cdc3e717dd3c7b2ff1a218b6de611f6ce76ee34967570a9de9"
+ "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e",
+ "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4",
+ "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be",
+ "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3",
+ "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85",
+ "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b",
+ "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367",
+ "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf",
+ "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393",
+ "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888",
+ "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37",
+ "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8",
+ "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60",
+ "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1",
+ "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4",
+ "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717",
+ "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7",
+ "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc",
+ "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe",
+ "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb",
+ "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75",
+ "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6",
+ "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e",
+ "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff",
+ "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566",
+ "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12",
+ "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367",
+ "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874",
+ "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf",
+ "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566",
+ "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a",
+ "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc",
+ "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a",
+ "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1",
+ "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6",
+ "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61",
+ "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726",
+ "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49",
+ "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44",
+ "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af",
+ "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa",
+ "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153",
+ "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc",
+ "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5",
+ "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938",
+ "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf",
+ "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925",
+ "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8",
+ "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c",
+ "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85",
+ "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e",
+ "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0",
+ "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1",
+ "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0",
+ "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992",
+ "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db",
+ "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f",
+ "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d",
+ "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1",
+ "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e",
+ "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900",
+ "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89",
+ "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a",
+ "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b",
+ "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f",
+ "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f",
+ "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1",
+ "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183",
+ "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66",
+ "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21",
+ "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db",
+ "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded",
+ "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb",
+ "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19",
+ "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0",
+ "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165",
+ "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778",
+ "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455",
+ "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f",
+ "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b",
+ "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237",
+ "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81",
+ "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859",
+ "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c",
+ "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835",
+ "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393",
+ "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5",
+ "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641",
+ "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144",
+ "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74",
+ "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db",
+ "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac",
+ "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403",
+ "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9",
+ "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f",
+ "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311",
+ "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581",
+ "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36",
+ "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00",
+ "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a",
+ "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f",
+ "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2",
+ "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7",
+ "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239",
+ "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757",
+ "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72",
+ "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9",
+ "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4",
+ "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24",
+ "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207",
+ "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e",
+ "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1",
+ "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d",
+ "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37",
+ "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c",
+ "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e",
+ "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570",
+ "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af",
+ "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f",
+ "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88",
+ "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48",
+ "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781"
],
"markers": "python_version >= '3.9'",
- "version": "==0.4.0"
+ "version": "==0.4.1"
},
"psycopg2-binary": {
"hashes": [
- "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff",
- "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5",
- "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f",
- "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5",
- "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0",
- "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c",
- "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c",
- "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341",
- "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f",
- "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7",
- "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d",
- "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007",
- "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142",
- "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92",
- "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb",
- "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5",
- "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5",
- "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8",
- "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1",
- "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68",
- "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73",
- "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1",
- "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53",
- "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d",
- "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906",
- "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0",
- "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2",
- "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a",
- "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b",
- "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44",
- "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648",
- "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7",
- "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f",
- "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa",
- "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697",
- "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d",
- "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b",
- "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526",
- "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4",
- "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287",
- "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e",
- "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673",
- "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0",
- "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30",
- "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3",
- "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e",
- "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92",
- "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a",
- "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c",
- "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8",
- "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909",
- "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47",
- "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864",
- "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc",
- "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00",
- "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb",
- "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539",
- "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b",
- "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481",
- "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5",
- "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4",
- "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64",
- "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392",
- "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4",
- "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1",
- "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1",
- "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567",
- "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"
+ "sha256:00ce1830d971f43b667abe4a56e42c1e2d594b32da4802e44a73bacacb25535f",
+ "sha256:04195548662fa544626c8ea0f06561eb6203f1984ba5b4562764fbeb4c3d14b1",
+ "sha256:0da4de5c1ac69d94ed4364b6cbe7190c1a70d325f112ba783d83f8440285f152",
+ "sha256:0e8480afd62362d0a6a27dd09e4ca2def6fa50ed3a4e7c09165266106b2ffa10",
+ "sha256:20e7fb94e20b03dcc783f76c0865f9da39559dcc0c28dd1a3fce0d01902a6b9c",
+ "sha256:2c226ef95eb2250974bf6fa7a842082b31f68385c4f3268370e3f3870e7859ee",
+ "sha256:2d11098a83cca92deaeaed3d58cfd150d49b3b06ee0d0852be466bf87596899e",
+ "sha256:2e164359396576a3cc701ba8af4751ae68a07235d7a380c631184a611220d9a4",
+ "sha256:304fd7b7f97eef30e91b8f7e720b3db75fee010b520e434ea35ed1ff22501d03",
+ "sha256:31b32c457a6025e74d233957cc9736742ac5a6cb196c6b68499f6bb51390bd6a",
+ "sha256:32770a4d666fbdafab017086655bcddab791d7cb260a16679cc5a7338b64343b",
+ "sha256:366df99e710a2acd90efed3764bb1e28df6c675d33a7fb40df9b7281694432ee",
+ "sha256:37d8412565a7267f7d79e29ab66876e55cb5e8e7b3bbf94f8206f6795f8f7e7e",
+ "sha256:4012c9c954dfaccd28f94e84ab9f94e12df76b4afb22331b1f0d3154893a6316",
+ "sha256:41360b01c140c2a03d346cec3280cf8a71aa07d94f3b1509fa0161c366af66b4",
+ "sha256:44fc5c2b8fa871ce7f0023f619f1349a0aa03a0857f2c96fbc01c657dcbbdb49",
+ "sha256:47f212c1d3be608a12937cc131bd85502954398aaa1320cb4c14421a0ffccf4c",
+ "sha256:4bdab48575b6f870f465b397c38f1b415520e9879fdf10a53ee4f49dcbdf8a21",
+ "sha256:4dca1f356a67ecb68c81a7bc7809f1569ad9e152ce7fd02c2f2036862ca9f66b",
+ "sha256:5c6ff3335ce08c75afaed19e08699e8aacf95d4a260b495a4a8545244fe2ceb3",
+ "sha256:5f3f2732cf504a1aa9e9609d02f79bea1067d99edf844ab92c247bbca143303b",
+ "sha256:62b6d93d7c0b61a1dd6197d208ab613eb7dcfdcca0a49c42ceb082257991de9d",
+ "sha256:691c807d94aecfbc76a14e1408847d59ff5b5906a04a23e12a89007672b9e819",
+ "sha256:763c93ef1df3da6d1a90f86ea7f3f806dc06b21c198fa87c3c25504abec9404a",
+ "sha256:84011ba3109e06ac412f95399b704d3d6950e386b7994475b231cf61eec2fc1f",
+ "sha256:865f9945ed1b3950d968ec4690ce68c55019d79e4497366d36e090327ce7db14",
+ "sha256:875039274f8a2361e5207857899706da840768e2a775bf8c65e82f60b197df02",
+ "sha256:8b81627b691f29c4c30a8f322546ad039c40c328373b11dff7490a3e1b517855",
+ "sha256:8c55b385daa2f92cb64b12ec4536c66954ac53654c7f15a203578da4e78105c0",
+ "sha256:91537a8df2bde69b1c1db01d6d944c831ca793952e4f57892600e96cee95f2cd",
+ "sha256:92e3b669236327083a2e33ccfa0d320dd01b9803b3e14dd986a4fc54aa00f4e1",
+ "sha256:9b52a3f9bb540a3e4ec0f6ba6d31339727b2950c9772850d6545b7eae0b9d7c5",
+ "sha256:9bd81e64e8de111237737b29d68039b9c813bdf520156af36d26819c9a979e5f",
+ "sha256:9c55460033867b4622cda1b6872edf445809535144152e5d14941ef591980edf",
+ "sha256:9d3a9edcfbe77a3ed4bc72836d466dfce4174beb79eda79ea155cc77237ed9e8",
+ "sha256:a1cf393f1cdaf6a9b57c0a719a1068ba1069f022a59b8b1fe44b006745b59757",
+ "sha256:a28d8c01a7b27a1e3265b11250ba7557e5f72b5ee9e5f3a2fa8d2949c29bf5d2",
+ "sha256:a311f1edc9967723d3511ea7d2708e2c3592e3405677bf53d5c7246753591fbb",
+ "sha256:a6c0e4262e089516603a09474ee13eabf09cb65c332277e39af68f6233911087",
+ "sha256:ab8905b5dcb05bf3fb22e0cf90e10f469563486ffb6a96569e51f897c750a76a",
+ "sha256:b31e90fdd0f968c2de3b26ab014314fe814225b6c324f770952f7d38abf17e3c",
+ "sha256:b33fabeb1fde21180479b2d4667e994de7bbf0eec22832ba5d9b5e4cf65b6c6d",
+ "sha256:b637d6d941209e8d96a072d7977238eea128046effbf37d1d8b2c0764750017d",
+ "sha256:b6aed9e096bf63f9e75edf2581aa9a7e7186d97ab5c177aa6c87797cd591236c",
+ "sha256:b8fb3db325435d34235b044b199e56cdf9ff41223a4b9752e8576465170bb38c",
+ "sha256:ba34475ceb08cccbdd98f6b46916917ae6eeb92b5ae111df10b544c3a4621dc4",
+ "sha256:be9b840ac0525a283a96b556616f5b4820e0526addb8dcf6525a0fa162730be4",
+ "sha256:bf940cd7e7fec19181fdbc29d76911741153d51cab52e5c21165f3262125685e",
+ "sha256:c0377174bf1dd416993d16edc15357f6eb17ac998244cca19bc67cdc0e2e5766",
+ "sha256:c3cb3a676873d7506825221045bd70e0427c905b9c8ee8d6acd70cfcbd6e576d",
+ "sha256:c47676e5b485393f069b4d7a811267d3168ce46f988fa602658b8bb901e9e64d",
+ "sha256:c665f01ec8ab273a61c62beeb8cce3014c214429ced8a308ca1fc410ecac3a39",
+ "sha256:cffe9d7697ae7456649617e8bb8d7a45afb71cd13f7ab22af3e5c61f04840908",
+ "sha256:d526864e0f67f74937a8fce859bd56c979f5e2ec57ca7c627f5f1071ef7fee60",
+ "sha256:d57c9c387660b8893093459738b6abddbb30a7eab058b77b0d0d1c7d521ddfd7",
+ "sha256:d6fe6b47d0b42ce1c9f1fa3e35bb365011ca22e39db37074458f27921dca40f2",
+ "sha256:db4fd476874ccfdbb630a54426964959e58da4c61c9feba73e6094d51303d7d8",
+ "sha256:e0deeb03da539fa3577fcb0b3f2554a97f7e5477c246098dbb18091a4a01c16f",
+ "sha256:e35b7abae2b0adab776add56111df1735ccc71406e56203515e228a8dc07089f",
+ "sha256:ebb415404821b6d1c47353ebe9c8645967a5235e6d88f914147e7fd411419e6f",
+ "sha256:edcb3aeb11cb4bf13a2af3c53a15b3d612edeb6409047ea0b5d6a21a9d744b34",
+ "sha256:ef7a6beb4beaa62f88592ccc65df20328029d721db309cb3250b0aae0fa146c3",
+ "sha256:efff12b432179443f54e230fdf60de1f6cc726b6c832db8701227d089310e8aa",
+ "sha256:f07c9c4a5093258a03b28fab9b4f151aa376989e7f35f855088234e656ee6a94",
+ "sha256:f090b7ddd13ca842ebfe301cd587a76a4cf0913b1e429eb92c1be5dbeb1a19bc",
+ "sha256:fa0f693d3c68ae925966f0b14b8edda71696608039f4ed61b1fe9ffa468d16db",
+ "sha256:fcf21be3ce5f5659daefd2b3b3b6e4727b028221ddc94e6c1523425579664747"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==2.9.10"
+ "markers": "python_version >= '3.9'",
+ "version": "==2.9.11"
+ },
+ "py-key-value-aio": {
+ "extras": [
+ "disk",
+ "keyring",
+ "memory",
+ "redis"
+ ],
+ "hashes": [
+ "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64",
+ "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==0.3.0"
+ },
+ "py-key-value-shared": {
+ "hashes": [
+ "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298",
+ "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==0.3.0"
},
"pycparser": {
"hashes": [
@@ -1689,138 +1997,154 @@
"email"
],
"hashes": [
- "sha256:c1a077e6270dbfb37bfd8b498b3981e2bb18f68103720e51fa6c306a5a9af563",
- "sha256:f6a1da352d42790537e95e83a8bdfb91c7efbae63ffd0b86fa823899e807116f"
+ "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49",
+ "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"
],
"markers": "python_version >= '3.9'",
- "version": "==2.12.0"
+ "version": "==2.12.5"
},
"pydantic-core": {
"hashes": [
- "sha256:0234236514f44a5bf552105cfe2543a12f48203397d9d0f866affa569345a5b5",
- "sha256:05226894a26f6f27e1deb735d7308f74ef5fa3a6de3e0135bb66cdcaee88f64b",
- "sha256:055c7931b0329cb8acde20cdde6d9c2cbc2a02a0a8e54a792cddd91e2ea92c65",
- "sha256:07588570a805296ece009c59d9a679dc08fab72fb337365afb4f3a14cfbfc176",
- "sha256:08a589f850803a74e0fcb16a72081cafb0d72a3cdda500106942b07e76b7bf62",
- "sha256:10ce489cf09a4956a1549af839b983edc59b0f60e1b068c21b10154e58f54f80",
- "sha256:12d4257fc9187a0ccd41b8b327d6a4e57281ab75e11dda66a9148ef2e1fb712f",
- "sha256:13ab9cc2de6f9d4ab645a050ae5aee61a2424ac4d3a16ba23d4c2027705e0301",
- "sha256:170406a37a5bc82c22c3274616bf6f17cc7df9c4a0a0a50449e559cb755db669",
- "sha256:1ab7e594a2a5c24ab8013a7dc8cfe5f2260e80e490685814122081705c2cf2b0",
- "sha256:1ad375859a6d8c356b7704ec0f547a58e82ee80bb41baa811ad710e124bc8f2f",
- "sha256:1b5c4374a152e10a22175d7790e644fbd8ff58418890e07e2073ff9d4414efae",
- "sha256:1b974e41adfbb4ebb0f65fc4ca951347b17463d60893ba7d5f7b9bb087c83897",
- "sha256:1e2df5f8344c99b6ea5219f00fdc8950b8e6f2c422fbc1cc122ec8641fac85a1",
- "sha256:1e798b4b304a995110d41ec93653e57975620ccb2842ba9420037985e7d7284e",
- "sha256:209910e88afb01fd0fd403947b809ba8dba0e08a095e1f703294fda0a8fdca51",
- "sha256:241299ca91fc77ef64f11ed909d2d9220a01834e8e6f8de61275c4dd16b7c936",
- "sha256:248dafb3204136113c383e91a4d815269f51562b6659b756cf3df14eefc7d0bb",
- "sha256:2757606b7948bb853a27e4040820306eaa0ccb9e8f9f8a0fa40cb674e170f350",
- "sha256:28527e4b53400cd60ffbd9812ccb2b5135d042129716d71afd7e45bf42b855c0",
- "sha256:2876a095292668d753f1a868c4a57c4ac9f6acbd8edda8debe4218d5848cf42f",
- "sha256:2896510fce8f4725ec518f8b9d7f015a00db249d2fd40788f442af303480063d",
- "sha256:2bf1917385ebe0f968dc5c6ab1375886d56992b93ddfe6bf52bff575d03662be",
- "sha256:2e71b1c6ceb9c78424ae9f63a07292fb769fb890a4e7efca5554c47f33a60ea5",
- "sha256:300a9c162fea9906cc5c103893ca2602afd84f0ec90d3be36f4cc360125d22e1",
- "sha256:30edab28829703f876897c9471a857e43d847b8799c3c9e2fbce644724b50aa4",
- "sha256:34df1fe8fea5d332484a763702e8b6a54048a9d4fe6ccf41e34a128238e01f52",
- "sha256:35291331e9d8ed94c257bab6be1cb3a380b5eee570a2784bffc055e18040a2ea",
- "sha256:365109d1165d78d98e33c5bfd815a9b5d7d070f578caefaabcc5771825b4ecb5",
- "sha256:377defd66ee2003748ee93c52bcef2d14fde48fe28a0b156f88c3dbf9bc49a50",
- "sha256:3925446673641d37c30bd84a9d597e49f72eacee8b43322c8999fa17d5ae5bc4",
- "sha256:3d43bf082025082bda13be89a5f876cc2386b7727c7b322be2d2b706a45cea8e",
- "sha256:421b5595f845842fc093f7250e24ee395f54ca62d494fdde96f43ecf9228ae01",
- "sha256:42ae9352cf211f08b04ea110563d6b1e415878eea5b4c70f6bdb17dca3b932d2",
- "sha256:440d0df7415b50084a4ba9d870480c16c5f67c0d1d4d5119e3f70925533a0edc",
- "sha256:447ddf56e2b7d28d200d3e9eafa936fe40485744b5a824b67039937580b3cb20",
- "sha256:46a1c935c9228bad738c8a41de06478770927baedf581d172494ab36a6b96575",
- "sha256:47694a31c710ced9205d5f1e7e8af3ca57cbb8a503d98cb9e33e27c97a501601",
- "sha256:47f1f642a205687d59b52dc1a9a607f45e588f5a2e9eeae05edd80c7a8c47674",
- "sha256:49bd51cc27adb980c7b97357ae036ce9b3c4d0bb406e84fbe16fb2d368b602a8",
- "sha256:4dc703015fbf8764d6a8001c327a87f1823b7328d40b47ce6000c65918ad2b4f",
- "sha256:4f276a6134fe1fc1daa692642a3eaa2b7b858599c49a7610816388f5e37566a1",
- "sha256:4f94f3ab188f44b9a73f7295663f3ecb8f2e2dd03a69c8f2ead50d37785ecb04",
- "sha256:4fee76d757639b493eb600fba668f1e17475af34c17dd61db7a47e824d464ca9",
- "sha256:5042da12e5d97d215f91567110fdfa2e2595a25f17c19b9ff024f31c34f9b53e",
- "sha256:530bbb1347e3e5ca13a91ac087c4971d7da09630ef8febd27a20a10800c2d06d",
- "sha256:555ecf7e50f1161d3f693bc49f23c82cf6cdeafc71fa37a06120772a09a38795",
- "sha256:5da98cc81873f39fd56882e1569c4677940fbc12bce6213fad1ead784192d7c8",
- "sha256:63892ead40c1160ac860b5debcc95c95c5a0035e543a8b5a4eac70dd22e995f4",
- "sha256:6550617a0c2115be56f90c31a5370261d8ce9dbf051c3ed53b51172dd34da696",
- "sha256:65a0ea16cfea7bfa9e43604c8bd726e63a3788b61c384c37664b55209fcb1d74",
- "sha256:666aee751faf1c6864b2db795775dd67b61fdcf646abefa309ed1da039a97209",
- "sha256:6771a2d9f83c4038dfad5970a3eef215940682b2175e32bcc817bdc639019b28",
- "sha256:678f9d76a91d6bcedd7568bbf6beb77ae8447f85d1aeebaab7e2f0829cfc3a13",
- "sha256:68f2251559b8efa99041bb63571ec7cdd2d715ba74cc82b3bc9eff824ebc8bf0",
- "sha256:706abf21e60a2857acdb09502bc853ee5bce732955e7b723b10311114f033115",
- "sha256:70e790fce5f05204ef4403159857bfcd587779da78627b0babb3654f75361ebf",
- "sha256:71eaa38d342099405dae6484216dcf1e8e4b0bebd9b44a4e08c9b43db6a2ab67",
- "sha256:7a97939d6ea44763c456bd8a617ceada2c9b96bb5b8ab3dfa0d0827df7619014",
- "sha256:7d82ae99409eb69d507a89835488fb657faa03ff9968a9379567b0d2e2e56bc5",
- "sha256:7f0bf7f5c8f7bf345c527e8a0d72d6b26eda99c1227b0c34e7e59e181260de31",
- "sha256:80745b9770b4a38c25015b517451c817799bfb9d6499b0d13d8227ec941cb513",
- "sha256:80e97ccfaf0aaf67d55de5085b0ed0d994f57747d9d03f2de5cc9847ca737b08",
- "sha256:82b887a711d341c2c47352375d73b029418f55b20bd7815446d175a70effa706",
- "sha256:83b64d70520e7890453f1aa21d66fda44e7b35f1cfea95adf7b4289a51e2b479",
- "sha256:84d0ff869f98be2e93efdf1ae31e5a15f0926d22af8677d51676e373abbfe57a",
- "sha256:85ff7911c6c3e2fd8d3779c50925f6406d770ea58ea6dde9c230d35b52b16b4a",
- "sha256:8ae0dc57b62a762985bc7fbf636be3412394acc0ddb4ade07fe104230f1b9762",
- "sha256:8fa93fadff794c6d15c345c560513b160197342275c6d104cc879f932b978afc",
- "sha256:93e9decce94daf47baf9e9d392f5f2557e783085f7c5e522011545d9d6858e00",
- "sha256:968e4ffdfd35698a5fe659e5e44c508b53664870a8e61c8f9d24d3d145d30257",
- "sha256:9cebf1ca35f10930612d60bd0f78adfacee824c30a880e3534ba02c207cceceb",
- "sha256:a31ca0cd0e4d12ea0df0077df2d487fc3eb9d7f96bbb13c3c5b88dcc21d05159",
- "sha256:a38a5263185407ceb599f2f035faf4589d57e73c7146d64f10577f6449e8171d",
- "sha256:a75a33b4db105dd1c8d57839e17ee12db8d5ad18209e792fa325dbb4baeb00f4",
- "sha256:ab0adafdf2b89c8b84f847780a119437a0931eca469f7b44d356f2b426dd9741",
- "sha256:ad4111acc63b7384e205c27a2f15e23ac0ee21a9d77ad6f2e9cb516ec90965fb",
- "sha256:af2385d3f98243fb733862f806c5bb9122e5fba05b373e3af40e3c82d711cef1",
- "sha256:b04fa9ed049461a7398138c604b00550bc89e3e1151d84b81ad6dc93e39c4c06",
- "sha256:b054ef1a78519cb934b58e9c90c09e93b837c935dcd907b891f2b265b129eb6e",
- "sha256:b3b7d9cfbfdc43c80a16638c6dc2768e3956e73031fca64e8e1a3ae744d1faeb",
- "sha256:b42ae7fd6760782c975897e1fdc810f483b021b32245b0105d40f6e7a3803e4b",
- "sha256:b5674314987cdde5a5511b029fa5fb1556b3d147a367e01dd583b19cfa8e35df",
- "sha256:b5f1d5d6bbba484bdf220c72d8ecd0be460f4bd4c5e534a541bb2cd57589fb8b",
- "sha256:b83aaeff0d7bde852c32e856f3ee410842ebc08bc55c510771d87dcd1c01e1ed",
- "sha256:b92d6c628e9a338846a28dfe3fcdc1a3279388624597898b105e078cdfc59298",
- "sha256:bf0bd5417acf7f6a7ec3b53f2109f587be176cb35f9cf016da87e6017437a72d",
- "sha256:c7bc140c596097cb53b30546ca257dbe3f19282283190b1b5142928e5d5d3a20",
- "sha256:c8a1af9ac51969a494c6a82b563abae6859dc082d3b999e8fa7ba5ee1b05e8e8",
- "sha256:c95caff279d49c1d6cdfe2996e6c2ad712571d3b9caaa209a404426c326c4bde",
- "sha256:cec0e75eb61f606bad0a32f2be87507087514e26e8c73db6cbdb8371ccd27917",
- "sha256:ced20e62cfa0f496ba68fa5d6c7ee71114ea67e2a5da3114d6450d7f4683572a",
- "sha256:d2ae423c65c556f09569524b80ffd11babff61f33055ef9773d7c9fabc11ed8d",
- "sha256:db2f82c0ccbce8f021ad304ce35cbe02aa2f95f215cac388eed542b03b4d5eb4",
- "sha256:dc17b6ecf4983d298686014c92ebc955a9f9baf9f57dad4065e7906e7bee6222",
- "sha256:dce8b22663c134583aaad24827863306a933f576c79da450be3984924e2031d1",
- "sha256:df11c24e138876ace5ec6043e5cae925e34cf38af1a1b3d63589e8f7b5f5cdc4",
- "sha256:dff5bee1d21ee58277900692a641925d2dddfde65182c972569b1a276d2ac8fb",
- "sha256:e019167628f6e6161ae7ab9fb70f6d076a0bf0d55aa9b20833f86a320c70dd65",
- "sha256:e244c37d5471c9acdcd282890c6c4c83747b77238bfa19429b8473586c907656",
- "sha256:e63036298322e9aea1c8b7c0a6c1204d615dbf6ec0668ce5b83ff27f07404a61",
- "sha256:e82947de92068b0a21681a13dd2102387197092fbe7defcfb8453e0913866506",
- "sha256:eec83fc6abef04c7f9bec616e2d76ee9a6a4ae2a359b10c21d0f680e24a247ca",
- "sha256:f1ebc7ab67b856384aba09ed74e3e977dded40e693de18a4f197c67d0d4e6d8e",
- "sha256:f1fc716c0eb1663c59699b024428ad5ec2bcc6b928527b8fe28de6cb89f47efb",
- "sha256:f2611bdb694116c31e551ed82e20e39a90bea9b7ad9e54aaf2d045ad621aa7a1",
- "sha256:f2ab7d10d0ab2ed6da54c757233eb0f48ebfb4f86e9b88ccecb3f92bbd61a538",
- "sha256:f4a9543ca355e6df8fbe9c83e9faab707701e9103ae857ecb40f1c0cf8b0e94d",
- "sha256:f9b9c968cfe5cd576fdd7361f47f27adeb120517e637d1b189eea1c3ece573f4",
- "sha256:fabcbdb12de6eada8d6e9a759097adb3c15440fafc675b3e94ae5c9cb8d678a0",
- "sha256:fecc130893a9b5f7bfe230be1bb8c61fe66a19db8ab704f808cb25a82aad0bc9",
- "sha256:ff548c908caffd9455fd1342366bcf8a1ec8a3fca42f35c7fc60883d6a901074",
- "sha256:fff2b76c8e172d34771cd4d4f0ade08072385310f214f823b5a6ad4006890d32"
+ "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90",
+ "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740",
+ "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504",
+ "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84",
+ "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33",
+ "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c",
+ "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0",
+ "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e",
+ "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0",
+ "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a",
+ "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34",
+ "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2",
+ "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3",
+ "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815",
+ "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14",
+ "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba",
+ "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375",
+ "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf",
+ "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963",
+ "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1",
+ "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808",
+ "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553",
+ "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1",
+ "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2",
+ "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5",
+ "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470",
+ "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2",
+ "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b",
+ "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660",
+ "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c",
+ "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093",
+ "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5",
+ "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594",
+ "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008",
+ "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a",
+ "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a",
+ "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd",
+ "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284",
+ "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586",
+ "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869",
+ "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294",
+ "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f",
+ "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66",
+ "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51",
+ "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc",
+ "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97",
+ "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a",
+ "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d",
+ "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9",
+ "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c",
+ "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07",
+ "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36",
+ "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e",
+ "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05",
+ "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e",
+ "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941",
+ "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3",
+ "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612",
+ "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3",
+ "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b",
+ "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe",
+ "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146",
+ "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11",
+ "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60",
+ "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd",
+ "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b",
+ "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c",
+ "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a",
+ "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460",
+ "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1",
+ "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf",
+ "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf",
+ "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858",
+ "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2",
+ "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9",
+ "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2",
+ "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3",
+ "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6",
+ "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770",
+ "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d",
+ "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc",
+ "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23",
+ "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26",
+ "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa",
+ "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8",
+ "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d",
+ "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3",
+ "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d",
+ "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034",
+ "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9",
+ "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1",
+ "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56",
+ "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b",
+ "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c",
+ "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a",
+ "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e",
+ "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9",
+ "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5",
+ "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a",
+ "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556",
+ "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e",
+ "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49",
+ "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2",
+ "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9",
+ "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b",
+ "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc",
+ "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb",
+ "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0",
+ "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8",
+ "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82",
+ "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69",
+ "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b",
+ "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c",
+ "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75",
+ "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5",
+ "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f",
+ "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad",
+ "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b",
+ "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7",
+ "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425",
+ "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"
],
"markers": "python_version >= '3.9'",
- "version": "==2.41.1"
+ "version": "==2.41.5"
},
"pydantic-settings": {
"hashes": [
- "sha256:d0e87a1c7d33593beb7194adb8470fc426e95ba02af83a0f23474a04c9a08180",
- "sha256:fe2cea3413b9530d10f3a5875adffb17ada5c1e1bab0b2885546d7310415207c"
+ "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0",
+ "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809"
],
- "markers": "python_version >= '3.9'",
- "version": "==2.11.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==2.12.0"
+ },
+ "pydocket": {
+ "hashes": [
+ "sha256:3192dfdb9ad772cc1481dc39194f474863f073266399795584dc7262e7510f94",
+ "sha256:3cf7030941f175f073cf05fc6fdf0ceede0af640f786de7dd22556d08025799f"
+ ],
+ "markers": "python_version >= '3.10'",
+ "version": "==0.15.6"
},
"pygments": {
"hashes": [
@@ -1831,6 +2155,9 @@
"version": "==2.19.2"
},
"pyjwt": {
+ "extras": [
+ "crypto"
+ ],
"hashes": [
"sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953",
"sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"
@@ -1864,20 +2191,28 @@
},
"python-dotenv": {
"hashes": [
- "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc",
- "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"
+ "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6",
+ "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61"
],
"markers": "python_version >= '3.9'",
- "version": "==1.1.1"
+ "version": "==1.2.1"
+ },
+ "python-json-logger": {
+ "hashes": [
+ "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2",
+ "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==4.0.0"
},
"python-multipart": {
"hashes": [
- "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104",
- "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"
+ "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92",
+ "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==0.0.20"
+ "markers": "python_version >= '3.10'",
+ "version": "==0.0.21"
},
"pytz": {
"hashes": [
@@ -1967,11 +2302,11 @@
},
"redis": {
"hashes": [
- "sha256:ca49577a531ea64039b5a36db3d6cd1a0c7a60c34124d46924a45b956e8cf14c",
- "sha256:dc1909bd24669cc31b5f67a039700b16ec30571096c5f1f0d9d2324bff31af97"
+ "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010",
+ "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f"
],
- "markers": "python_version >= '3.8'",
- "version": "==5.3.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==6.4.0"
},
"referencing": {
"hashes": [
@@ -1983,124 +2318,124 @@
},
"regex": {
"hashes": [
- "sha256:032720248cbeeae6444c269b78cb15664458b7bb9ed02401d3da59fe4d68c3a5",
- "sha256:039a9d7195fd88c943d7c777d4941e8ef736731947becce773c31a1009cb3c35",
- "sha256:039f11b618ce8d71a1c364fdee37da1012f5a3e79b1b2819a9f389cd82fd6282",
- "sha256:05440bc172bc4b4b37fb9667e796597419404dbba62e171e1f826d7d2a9ebcef",
- "sha256:06104cd203cdef3ade989a1c45b6215bf42f8b9dd705ecc220c173233f7cba41",
- "sha256:065b6956749379d41db2625f880b637d4acc14c0a4de0d25d609a62850e96d36",
- "sha256:0716e4d6e58853d83f6563f3cf25c281ff46cf7107e5f11879e32cb0b59797d9",
- "sha256:0ac936537ad87cef9e0e66c5144484206c1354224ee811ab1519a32373e411f3",
- "sha256:0c3506682ea19beefe627a38872d8da65cc01ffa25ed3f2e422dffa1474f0788",
- "sha256:0cc3521060162d02bd36927e20690129200e5ac9d2c6d32b70368870b122db25",
- "sha256:0dc6893b1f502d73037cf807a321cdc9be29ef3d6219f7970f842475873712ac",
- "sha256:0f0d676522d68c207828dcd01fb6f214f63f238c283d9f01d85fc664c7c85b56",
- "sha256:0ffd9e230b826b15b369391bec167baed57c7ce39efc35835448618860995946",
- "sha256:1137cabc0f38807de79e28d3f6e3e3f2cc8cfb26bead754d02e6d1de5f679203",
- "sha256:12296202480c201c98a84aecc4d210592b2f55e200a1d193235c4db92b9f6788",
- "sha256:13202e4c4ac0ef9a317fff817674b293c8f7e8c68d3190377d8d8b749f566e12",
- "sha256:168be0d2f9b9d13076940b1ed774f98595b4e3c7fc54584bba81b3cc4181742e",
- "sha256:16bd2944e77522275e5ee36f867e19995bcaa533dcb516753a26726ac7285442",
- "sha256:16eaf74b3c4180ede88f620f299e474913ab6924d5c4b89b3833bc2345d83b3d",
- "sha256:1a351aff9e07a2dabb5022ead6380cff17a4f10e4feb15f9100ee56c4d6d06af",
- "sha256:1b9d9a2d6cda6621551ca8cf7a06f103adf72831153f3c0d982386110870c4d3",
- "sha256:1e85f73ef7095f0380208269055ae20524bfde3f27c5384126ddccf20382a638",
- "sha256:1ef86a9ebc53f379d921fb9a7e42b92059ad3ee800fcd9e0fe6181090e9f6c23",
- "sha256:220381f1464a581f2ea988f2220cf2a67927adcef107d47d6897ba5a2f6d51a4",
- "sha256:274687e62ea3cf54846a9b25fc48a04459de50af30a7bd0b61a9e38015983494",
- "sha256:29cd86aa7cb13a37d0f0d7c21d8d949fe402ffa0ea697e635afedd97ab4b69f1",
- "sha256:2a40f929cd907c7e8ac7566ac76225a77701a6221bca937bdb70d56cb61f57b2",
- "sha256:2e1eddc06eeaffd249c0adb6fafc19e2118e6308c60df9db27919e96b5656096",
- "sha256:300e25dbbf8299d87205e821a201057f2ef9aa3deb29caa01cd2cac669e508d5",
- "sha256:34d674cbba70c9398074c8a1fcc1a79739d65d1105de2a3c695e2b05ea728251",
- "sha256:3810a65675845c3bdfa58c3c7d88624356dd6ee2fc186628295e0969005f928d",
- "sha256:385c9b769655cb65ea40b6eea6ff763cbb6d69b3ffef0b0db8208e1833d4e746",
- "sha256:3acc471d1dd7e5ff82e6cacb3b286750decd949ecd4ae258696d04f019817ef8",
- "sha256:3b524d010973f2e1929aeb635418d468d869a5f77b52084d9f74c272189c251d",
- "sha256:3d86b5247bf25fa3715e385aa9ff272c307e0636ce0c9595f64568b41f0a9c77",
- "sha256:3dbcfcaa18e9480669030d07371713c10b4f1a41f791ffa5cb1a99f24e777f40",
- "sha256:40532bff8a1a0621e7903ae57fce88feb2e8a9a9116d341701302c9302aef06e",
- "sha256:431bd2a8726b000eb6f12429c9b438a24062a535d06783a93d2bcbad3698f8a8",
- "sha256:436e1b31d7efd4dcd52091d076482031c611dde58bf9c46ca6d0a26e33053a7e",
- "sha256:47acd811589301298c49db2c56bde4f9308d6396da92daf99cba781fa74aa450",
- "sha256:48317233294648bf7cd068857f248e3a57222259a5304d32c7552e2284a1b2ad",
- "sha256:4a12a06c268a629cb67cc1d009b7bb0be43e289d00d5111f86a2efd3b1949444",
- "sha256:4b8cdbddf2db1c5e80338ba2daa3cfa3dec73a46fff2a7dda087c8efbf12d62f",
- "sha256:4baeb1b16735ac969a7eeecc216f1f8b7caf60431f38a2671ae601f716a32d25",
- "sha256:4dc98ba7dd66bd1261927a9f49bd5ee2bcb3660f7962f1ec02617280fc00f5eb",
- "sha256:4f130c3a7845ba42de42f380fff3c8aebe89a810747d91bcf56d40a069f15352",
- "sha256:50e8290707f2fb8e314ab3831e594da71e062f1d623b05266f8cfe4db4949afd",
- "sha256:51076980cd08cd13c88eb7365427ae27f0d94e7cebe9ceb2bb9ffdae8fc4d82a",
- "sha256:5514b8e4031fdfaa3d27e92c75719cbe7f379e28cacd939807289bce76d0e35a",
- "sha256:57929d0f92bebb2d1a83af372cd0ffba2263f13f376e19b1e4fa32aec4efddc3",
- "sha256:57a161bd3acaa4b513220b49949b07e252165e6b6dc910ee7617a37ff4f5b425",
- "sha256:5adf266f730431e3be9021d3e5b8d5ee65e563fec2883ea8093944d21863b379",
- "sha256:5db95ff632dbabc8c38c4e82bf545ab78d902e81160e6e455598014f0abe66b9",
- "sha256:5f96fa342b6f54dcba928dd452e8d8cb9f0d63e711d1721cd765bb9f73bb048d",
- "sha256:6479d5555122433728760e5f29edb4c2b79655a8deb681a141beb5c8a025baea",
- "sha256:65d3c38c39efce73e0d9dc019697b39903ba25b1ad45ebbd730d2cf32741f40d",
- "sha256:6a4b44df31d34fa51aa5c995d3aa3c999cec4d69b9bd414a8be51984d859f06d",
- "sha256:6a52219a93dd3d92c675383efff6ae18c982e2d7651c792b1e6d121055808743",
- "sha256:6b498437c026a3d5d0be0020023ff76d70ae4d77118e92f6f26c9d0423452446",
- "sha256:726177ade8e481db669e76bf99de0b278783be8acd11cef71165327abd1f170a",
- "sha256:7b47fcf9f5316c0bdaf449e879407e1b9937a23c3b369135ca94ebc8d74b1742",
- "sha256:7c9f285a071ee55cd9583ba24dde006e53e17780bb309baa8e4289cd472bcc47",
- "sha256:7cc9e5525cada99699ca9223cce2d52e88c52a3d2a0e842bd53de5497c604164",
- "sha256:7e2b414deae99166e22c005e154a5513ac31493db178d8aec92b3269c9cce8c9",
- "sha256:828446870bd7dee4e0cbeed767f07961aa07f0ea3129f38b3ccecebc9742e0b8",
- "sha256:8620d247fb8c0683ade51217b459cb4a1081c0405a3072235ba43a40d355c09a",
- "sha256:874ff523b0fecffb090f80ae53dc93538f8db954c8bb5505f05b7787ab3402a0",
- "sha256:87f681bfca84ebd265278b5daa1dcb57f4db315da3b5d044add7c30c10442e61",
- "sha256:8900b3208e022570ae34328712bef6696de0804c122933414014bae791437ab2",
- "sha256:895197241fccf18c0cea7550c80e75f185b8bd55b6924fcae269a1a92c614a07",
- "sha256:8e5f41ad24a1e0b5dfcf4c4e5d9f5bd54c895feb5708dd0c1d0d35693b24d478",
- "sha256:8f9698b6f6895d6db810e0bda5364f9ceb9e5b11328700a90cae573574f61eea",
- "sha256:9098e29b3ea4ffffeade423f6779665e2a4f8db64e699c0ed737ef0db6ba7b12",
- "sha256:90b6b7a2d0f45b7ecaaee1aec6b362184d6596ba2092dd583ffba1b78dd0231c",
- "sha256:92a8e375ccdc1256401c90e9dc02b8642894443d549ff5e25e36d7cf8a80c783",
- "sha256:9feb29817df349c976da9a0debf775c5c33fc1c8ad7b9f025825da99374770b7",
- "sha256:a021217b01be2d51632ce056d7a837d3fa37c543ede36e39d14063176a26ae29",
- "sha256:a276937d9d75085b2c91fb48244349c6954f05ee97bba0963ce24a9d915b8b68",
- "sha256:a295916890f4df0902e4286bc7223ee7f9e925daa6dcdec4192364255b70561a",
- "sha256:a61e85bfc63d232ac14b015af1261f826260c8deb19401c0597dbb87a864361e",
- "sha256:a78722c86a3e7e6aadf9579e3b0ad78d955f2d1f1a8ca4f67d7ca258e8719d4b",
- "sha256:ae77e447ebc144d5a26d50055c6ddba1d6ad4a865a560ec7200b8b06bc529368",
- "sha256:ae9b3840c5bd456780e3ddf2f737ab55a79b790f6409182012718a35c6d43282",
- "sha256:b176326bcd544b5e9b17d6943f807697c0cb7351f6cfb45bf5637c95ff7e6306",
- "sha256:b7531a8ef61de2c647cdf68b3229b071e46ec326b3138b2180acb4275f470b01",
- "sha256:b80fa342ed1ea095168a3f116637bd1030d39c9ff38dc04e54ef7c521e01fc95",
- "sha256:bbb9246568f72dce29bcd433517c2be22c7791784b223a810225af3b50d1aafb",
- "sha256:bc4b8e9d16e20ddfe16430c23468a8707ccad3365b06d4536142e71823f3ca29",
- "sha256:c190af81e5576b9c5fdc708f781a52ff20f8b96386c6e2e0557a78402b029f4a",
- "sha256:c204e93bf32cd7a77151d44b05eb36f469d0898e3fba141c026a26b79d9914a0",
- "sha256:c28821d5637866479ec4cc23b8c990f5bc6dd24e5e4384ba4a11d38a526e1414",
- "sha256:c5ba23274c61c6fef447ba6a39333297d0c247f53059dba0bca415cac511edc4",
- "sha256:c6db75b51acf277997f3adcd0ad89045d856190d13359f15ab5dda21581d9129",
- "sha256:c81b892af4a38286101502eae7aec69f7cd749a893d9987a92776954f3943408",
- "sha256:c90471671c2cdf914e58b6af62420ea9ecd06d1554d7474d50133ff26ae88feb",
- "sha256:d13ab0490128f2bb45d596f754148cd750411afc97e813e4b3a61cf278a23bb6",
- "sha256:d3bc882119764ba3a119fbf2bd4f1b47bc56c1da5d42df4ed54ae1e8e66fdf8f",
- "sha256:d488c236ac497c46a5ac2005a952c1a0e22a07be9f10c3e735bc7d1209a34773",
- "sha256:d4a691494439287c08ddb9b5793da605ee80299dd31e95fa3f323fac3c33d9d4",
- "sha256:d59ecf3bb549e491c8104fea7313f3563c7b048e01287db0a90485734a70a730",
- "sha256:dbef80defe9fb21310948a2595420b36c6d641d9bea4c991175829b2cc4bc06a",
- "sha256:dec57f96d4def58c422d212d414efe28218d58537b5445cf0c33afb1b4768571",
- "sha256:dfbde38f38004703c35666a1e1c088b778e35d55348da2b7b278914491698d6a",
- "sha256:e1dd06f981eb226edf87c55d523131ade7285137fbde837c34dc9d1bf309f459",
- "sha256:e3ef8cf53dc8df49d7e28a356cf824e3623764e9833348b655cfed4524ab8a90",
- "sha256:e4121f1ce2b2b5eec4b397cc1b277686e577e658d8f5870b7eb2d726bd2300ab",
- "sha256:ec46332c41add73f2b57e2f5b642f991f6b15e50e9f86285e08ffe3a512ac39f",
- "sha256:ef8d10cc0989565bcbe45fb4439f044594d5c2b8919d3d229ea2c4238f1d55b0",
- "sha256:f04d2f20da4053d96c08f7fde6e1419b7ec9dbcee89c96e3d731fca77f411b95",
- "sha256:f2f422214a03fab16bfa495cfec72bee4aaa5731843b771860a471282f1bf74f",
- "sha256:f4d97071c0ba40f0cf2a93ed76e660654c399a0a04ab7d85472239460f3da84b",
- "sha256:f5cca697da89b9f8ea44115ce3130f6c54c22f541943ac8e9900461edc2b8bd4",
- "sha256:fb137ec7c5c54f34a25ff9b31f6b7b0c2757be80176435bf367111e3f71d72df",
- "sha256:fb967eb441b0f15ae610b7069bdb760b929f267efbf522e814bbbfffdf125ce2",
- "sha256:fe5d50572bc885a0a799410a717c42b1a6b50e2f45872e2b40f4f288f9bce8a2"
+ "sha256:04d2765516395cf7dda331a244a3282c0f5ae96075f728629287dfa6f76ba70a",
+ "sha256:087511f5c8b7dfbe3a03f5d5ad0c2a33861b1fc387f21f6f60825a44865a385a",
+ "sha256:08b884f4226602ad40c5d55f52bf91a9df30f513864e0054bad40c0e9cf1afb7",
+ "sha256:0d31e08426ff4b5b650f68839f5af51a92a5b51abd8554a60c2fbc7c71f25d0b",
+ "sha256:0f9397d561a4c16829d4e6ff75202c1c08b68a3bdbfe29dbfcdb31c9830907c6",
+ "sha256:10483eefbfb0adb18ee9474498c9a32fcf4e594fbca0543bb94c48bac6183e2e",
+ "sha256:149eb0bba95231fb4f6d37c8f760ec9fa6fabf65bab555e128dde5f2475193ec",
+ "sha256:1e00ec2970aab10dc5db34af535f21fcf32b4a31d99e34963419636e2f85ae39",
+ "sha256:1eb1ebf6822b756c723e09f5186473d93236c06c579d2cc0671a722d2ab14281",
+ "sha256:1fedc720f9bb2494ce31a58a1631f9c82df6a09b49c19517ea5cc280b4541e01",
+ "sha256:1ff0d190c7f68ae7769cd0313fe45820ba07ffebfddfaa89cc1eb70827ba0ddc",
+ "sha256:2292cd5a90dab247f9abe892ac584cb24f0f54680c73fcb4a7493c66c2bf2467",
+ "sha256:22b29dda7e1f7062a52359fca6e58e548e28c6686f205e780b02ad8ef710de36",
+ "sha256:22c12d837298651e5550ac1d964e4ff57c3f56965fc1812c90c9fb2028eaf267",
+ "sha256:22dd622a402aad4558277305350699b2be14bc59f64d64ae1d928ce7d072dced",
+ "sha256:22e7d1cdfa88ef33a2ae6aa0d707f9255eb286ffbd90045f1088246833223aee",
+ "sha256:28ba4d69171fc6e9896337d4fc63a43660002b7da53fc15ac992abcf3410917c",
+ "sha256:2ab815eb8a96379a27c3b6157fcb127c8f59c36f043c1678110cea492868f1d5",
+ "sha256:2b441a4ae2c8049106e8b39973bfbddfb25a179dda2bdb99b0eeb60c40a6a3af",
+ "sha256:2fa2eed3f76677777345d2f81ee89f5de2f5745910e805f7af7386a920fa7313",
+ "sha256:32f74f35ff0f25a5021373ac61442edcb150731fbaa28286bbc8bb1582c89d02",
+ "sha256:3809988f0a8b8c9dcc0f92478d6501fac7200b9ec56aecf0ec21f4a2ec4b6009",
+ "sha256:3839967cf4dc4b985e1570fd8d91078f0c519f30491c60f9ac42a8db039be204",
+ "sha256:38af559ad934a7b35147716655d4a2f79fcef2d695ddfe06a06ba40ae631fa7e",
+ "sha256:3a91e4a29938bc1a082cc28fdea44be420bf2bebe2665343029723892eb073e1",
+ "sha256:3b30bc921d50365775c09a7ed446359e5c0179e9e2512beec4a60cbcef6ddd50",
+ "sha256:3b3a5f320136873cc5561098dfab677eea139521cb9a9e8db98b7e64aef44cbc",
+ "sha256:3bf28b1873a8af8bbb58c26cc56ea6e534d80053b41fb511a35795b6de507e6a",
+ "sha256:3e0b11b2b2433d1c39c7c7a30e3f3d0aeeea44c2a8d0bae28f6b95f639927a69",
+ "sha256:3e816cc9aac1cd3cc9a4ec4d860f06d40f994b5c7b4d03b93345f44e08cc68bf",
+ "sha256:3f8bf11a4827cc7ce5a53d4ef6cddd5ad25595d3c1435ef08f76825851343154",
+ "sha256:435bbad13e57eb5606a68443af62bed3556de2f46deb9f7d4237bc2f1c9fb3a0",
+ "sha256:43b4fb020e779ca81c1b5255015fe2b82816c76ec982354534ad9ec09ad7c9e3",
+ "sha256:442d86cf1cfe4faabf97db7d901ef58347efd004934da045c745e7b5bd57ac49",
+ "sha256:44f264d4bf02f3176467d90b294d59bf1db9fe53c141ff772f27a8b456b2a9ed",
+ "sha256:454d9b4ae7881afbc25015b8627c16d88a597479b9dea82b8c6e7e2e07240dc7",
+ "sha256:4aecb6f461316adf9f1f0f6a4a1a3d79e045f9b71ec76055a791affa3b285850",
+ "sha256:4bf146dca15cdd53224a1bf46d628bd7590e4a07fbb69e720d561aea43a32b38",
+ "sha256:4c5238d32f3c5269d9e87be0cf096437b7622b6920f5eac4fd202468aaeb34d2",
+ "sha256:4e1e592789704459900728d88d41a46fe3969b82ab62945560a31732ffc19a6d",
+ "sha256:509dc827f89c15c66a0c216331260d777dd6c81e9a4e4f830e662b0bb296c313",
+ "sha256:51c1c1847128238f54930edb8805b660305dca164645a9fd29243f5610beea34",
+ "sha256:5cf77eac15bd264986c4a2c63353212c095b40f3affb2bc6b4ef80c4776c1a28",
+ "sha256:5d9903ca42bfeec4cebedba8022a7c97ad2aab22e09573ce9976ba01b65e4361",
+ "sha256:61a08bcb0ec14ff4e0ed2044aad948d0659604f824cbd50b55e30b0ec6f09c73",
+ "sha256:62ba394a3dda9ad41c7c780f60f6e4a70988741415ae96f6d1bf6c239cf01379",
+ "sha256:639431bdc89d6429f6721625e8129413980ccd62e9d3f496be618a41d205f160",
+ "sha256:64350685ff08b1d3a6fff33f45a9ca183dc1d58bbfe4981604e70ec9801bbc26",
+ "sha256:6538241f45eb5a25aa575dbba1069ad786f68a4f2773a29a2bd3dd1f9de787be",
+ "sha256:669dcfb2e38f9e8c69507bace46f4889e3abbfd9b0c29719202883c0a603598f",
+ "sha256:66d559b21d3640203ab9075797a55165d79017520685fb407b9234d72ab63c62",
+ "sha256:6dd329a1b61c0ee95ba95385fb0c07ea0d3fe1a21e1349fa2bec272636217118",
+ "sha256:728a9d2d173a65b62bdc380b7932dd8e74ed4295279a8fe1021204ce210803e7",
+ "sha256:732aea6de26051af97b94bc98ed86448821f839d058e5d259c72bf6d73ad0fc0",
+ "sha256:74d04244852ff73b32eeede4f76f51c5bcf44bc3c207bc3e6cf1c5c45b890708",
+ "sha256:7521684c8c7c4f6e88e35ec89680ee1aa8358d3f09d27dfbdf62c446f5d4c695",
+ "sha256:75fa6f0056e7efb1f42a1c34e58be24072cb9e61a601340cc1196ae92326a4f9",
+ "sha256:78c2d02bb6e1da0720eedc0bad578049cad3f71050ef8cd065ecc87691bed2b0",
+ "sha256:795ea137b1d809eb6836b43748b12634291c0ed55ad50a7d72d21edf1cd565c4",
+ "sha256:7a50cd39f73faa34ec18d6720ee25ef10c4c1839514186fcda658a06c06057a2",
+ "sha256:7a7c7fdf755032ffdd72c77e3d8096bdcb0eb92e89e17571a196f03d88b11b3c",
+ "sha256:7be0277469bf3bd7a34a9c57c1b6a724532a0d235cd0dc4e7f4316f982c28b19",
+ "sha256:7eb542fd347ce61e1321b0a6b945d5701528dca0cd9759c2e3bb8bd57e47964d",
+ "sha256:7fe6e5440584e94cc4b3f5f4d98a25e29ca12dccf8873679a635638349831b98",
+ "sha256:81519e25707fc076978c6143b81ea3dc853f176895af05bf7ec51effe818aeec",
+ "sha256:838441333bc90b829406d4a03cb4b8bf7656231b84358628b0406d803931ef32",
+ "sha256:849202cd789e5f3cf5dcc7822c34b502181b4824a65ff20ce82da5524e45e8e9",
+ "sha256:856a25c73b697f2ce2a24e7968285579e62577a048526161a2c0f53090bea9f9",
+ "sha256:87eb52a81ef58c7ba4d45c3ca74e12aa4b4e77816f72ca25258a85b3ea96cb48",
+ "sha256:885b26aa3ee56433b630502dc3d36ba78d186a00cc535d3806e6bfd9ed3c70ab",
+ "sha256:8a3d571bd95fade53c86c0517f859477ff3a93c3fde10c9e669086f038e0f207",
+ "sha256:8e026094aa12b43f4fd74576714e987803a315c76edb6b098b9809db5de58f74",
+ "sha256:9697a52e57576c83139d7c6f213d64485d3df5bf84807c35fa409e6c970801c6",
+ "sha256:9b5aca4d5dfd7fbfbfbdaf44850fcc7709a01146a797536a8f84952e940cca76",
+ "sha256:9ddc42e68114e161e51e272f667d640f97e84a2b9ef14b7477c53aac20c2d59a",
+ "sha256:9f95fbaa0ee1610ec0fc6b26668e9917a582ba80c52cc6d9ada15e30aa9ab9ad",
+ "sha256:a12ab1f5c29b4e93db518f5e3872116b7e9b1646c9f9f426f777b50d44a09e8c",
+ "sha256:a295ca2bba5c1c885826ce3125fa0b9f702a1be547d821c01d65f199e10c01e2",
+ "sha256:a4cb042b615245d5ff9b3794f56be4138b5adc35a4166014d31d1814744148c7",
+ "sha256:adad1a1bcf1c9e76346e091d22d23ac54ef28e1365117d99521631078dfec9de",
+ "sha256:b4774ff32f18e0504bfc4e59a3e71e18d83bc1e171a3c8ed75013958a03b2f14",
+ "sha256:b6f78f98741dcc89607c16b1e9426ee46ce4bf31ac5e6b0d40e81c89f3481ea5",
+ "sha256:b7f9ee819f94c6abfa56ec7b1dbab586f41ebbdc0a57e6524bd5e7f487a878c7",
+ "sha256:ba0d8a5d7f04f73ee7d01d974d47c5834f8a1b0224390e4fe7c12a3a92a78ecc",
+ "sha256:bac4200befe50c670c405dc33af26dad5a3b6b255dd6c000d92fe4629f9ed6a5",
+ "sha256:bc8ab71e2e31b16e40868a40a69007bc305e1109bd4658eb6cad007e0bf67c41",
+ "sha256:bce22519c989bb72a7e6b36a199384c53db7722fe669ba891da75907fe3587db",
+ "sha256:bf3490bcbb985a1ae97b2ce9ad1c0f06a852d5b19dde9b07bdf25bf224248c95",
+ "sha256:c1e448051717a334891f2b9a620fe36776ebf3dd8ec46a0b877c8ae69575feb4",
+ "sha256:c54f768482cef41e219720013cd05933b6f971d9562544d691c68699bf2b6801",
+ "sha256:c56b4d162ca2b43318ac671c65bd4d563e841a694ac70e1a976ac38fcf4ca1d2",
+ "sha256:c9c30003b9347c24bcc210958c5d167b9e4f9be786cb380a7d32f14f9b84674f",
+ "sha256:cc4076a5b4f36d849fd709284b4a3b112326652f3b0466f04002a6c15a0c96c1",
+ "sha256:cfe6d3f0c9e3b7e8c0c694b24d25e677776f5ca26dce46fd6b0489f9c8339391",
+ "sha256:d6c2d5919075a1f2e413c00b056ea0c2f065b3f5fe83c3d07d325ab92dce51d6",
+ "sha256:d8b4a27eebd684319bdf473d39f1d79eed36bf2cd34bd4465cdb4618d82b3d56",
+ "sha256:dbe6095001465294f13f1adcd3311e50dd84e5a71525f20a10bd16689c61ce0b",
+ "sha256:dd16e78eb18ffdb25ee33a0682d17912e8cc8a770e885aeee95020046128f1ce",
+ "sha256:ddd76a9f58e6a00f8772e72cff8ebcff78e022be95edf018766707c730593e1e",
+ "sha256:df9eb838c44f570283712e7cff14c16329a9f0fb19ca492d21d4b7528ee6821e",
+ "sha256:dfec44d532be4c07088c3de2876130ff0fbeeacaa89a137decbbb5f665855a0f",
+ "sha256:e18bc3f73bd41243c9b38a6d9f2366cd0e0137a9aebe2d8ff76c5b67d4c0a3f4",
+ "sha256:e43586ce5bd28f9f285a6e729466841368c4a0353f6fd08d4ce4630843d3648a",
+ "sha256:e6b49cd2aad93a1790ce9cffb18964f6d3a4b0b3dbdbd5de094b65296fce6e58",
+ "sha256:e6c7a21dffba883234baefe91bc3388e629779582038f75d2a5be918e250f0ed",
+ "sha256:e721d1b46e25c481dc5ded6f4b3f66c897c58d2e8cfdf77bbced84339108b0b9",
+ "sha256:eadade04221641516fa25139273505a1c19f9bf97589a05bc4cfcd8b4a618031",
+ "sha256:ee3a83ce492074c35a74cc76cf8235d49e77b757193a5365ff86e3f2f93db9fd",
+ "sha256:f117efad42068f9715677c8523ed2be1518116d1c49b1dd17987716695181efe",
+ "sha256:f3b5a391c7597ffa96b41bd5cbd2ed0305f515fcbb367dfa72735679d5502364",
+ "sha256:f4ff94e58e84aedb9c9fce66d4ef9f27a190285b451420f297c9a09f2b9abee9",
+ "sha256:f99be08cfead2020c7ca6e396c13543baea32343b7a9a5780c462e323bd8872f",
+ "sha256:fd0a5e563c756de210bb964789b5abe4f114dacae9104a47e1a649b910361536",
+ "sha256:feff9e54ec0dd3833d659257f5c3f5322a12eee58ffa360984b716f8b92983f4",
+ "sha256:ffcca5b9efe948ba0661e9df0fa50d2bc4b097c70b9810212d6b62f05d83b2dd"
],
"markers": "python_version >= '3.9'",
- "version": "==2025.9.18"
+ "version": "==2025.11.3"
},
"requests": {
"hashes": [
@@ -2110,190 +2445,149 @@
"markers": "python_version >= '3.9'",
"version": "==2.32.5"
},
- "rfc3339-validator": {
- "hashes": [
- "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b",
- "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==0.1.4"
- },
"rich": {
"hashes": [
- "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f",
- "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8"
+ "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4",
+ "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"
],
"markers": "python_full_version >= '3.8.0'",
- "version": "==14.1.0"
+ "version": "==14.2.0"
},
"rich-rst": {
"hashes": [
- "sha256:498a74e3896507ab04492d326e794c3ef76e7cda078703aa592d1853d91098c1",
- "sha256:fad46e3ba42785ea8c1785e2ceaa56e0ffa32dbe5410dec432f37e4107c4f383"
+ "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4",
+ "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a"
],
- "markers": "python_version >= '3.6'",
- "version": "==1.3.1"
+ "version": "==1.3.2"
},
"rpds-py": {
"hashes": [
- "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400",
- "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1",
- "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e",
- "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f",
- "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60",
- "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059",
- "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2",
- "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff",
- "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef",
- "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd",
- "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf",
- "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d",
- "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e",
- "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52",
- "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8",
- "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d",
- "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc",
- "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5",
- "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8",
- "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf",
- "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c",
- "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418",
- "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746",
- "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905",
- "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688",
- "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39",
- "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb",
- "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502",
- "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66",
- "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b",
- "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc",
- "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675",
- "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013",
- "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1",
- "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1",
- "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a",
- "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734",
- "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5",
- "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e",
- "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92",
- "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c",
- "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195",
- "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786",
- "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274",
- "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3",
- "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859",
- "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a",
- "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125",
- "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71",
- "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83",
- "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3",
- "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5",
- "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817",
- "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48",
- "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772",
- "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2",
- "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948",
- "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef",
- "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde",
- "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9",
- "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802",
- "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3",
- "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab",
- "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be",
- "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6",
- "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8",
- "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad",
- "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf",
- "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec",
- "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4",
- "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1",
- "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a",
- "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8",
- "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39",
- "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4",
- "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab",
- "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808",
- "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5",
- "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10",
- "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797",
- "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3",
- "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61",
- "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228",
- "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4",
- "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf",
- "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881",
- "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002",
- "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52",
- "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9",
- "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1",
- "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f",
- "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998",
- "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485",
- "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456",
- "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd",
- "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e",
- "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475",
- "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e",
- "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c",
- "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334",
- "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90",
- "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2",
- "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657",
- "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15",
- "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b",
- "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33",
- "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2",
- "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8",
- "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881",
- "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136",
- "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212",
- "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc",
- "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0",
- "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e",
- "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819",
- "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527",
- "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed",
- "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df",
- "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb",
- "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a",
- "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a",
- "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21",
- "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf",
- "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8",
- "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594",
- "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a",
- "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e",
- "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7",
- "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8",
- "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6",
- "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3",
- "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec",
- "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3",
- "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723",
- "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b",
- "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb",
- "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081",
- "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7",
- "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d",
- "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9",
- "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9",
- "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4",
- "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444",
- "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a",
- "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0",
- "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b",
- "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83",
- "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3",
- "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636",
- "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc",
- "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2",
- "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a",
- "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb",
- "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec",
- "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"
+ "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f",
+ "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136",
+ "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3",
+ "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7",
+ "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65",
+ "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4",
+ "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169",
+ "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf",
+ "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4",
+ "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2",
+ "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c",
+ "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4",
+ "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3",
+ "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6",
+ "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7",
+ "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89",
+ "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85",
+ "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6",
+ "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa",
+ "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb",
+ "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6",
+ "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87",
+ "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856",
+ "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4",
+ "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f",
+ "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53",
+ "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229",
+ "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad",
+ "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23",
+ "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db",
+ "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038",
+ "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27",
+ "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00",
+ "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18",
+ "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083",
+ "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c",
+ "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738",
+ "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898",
+ "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e",
+ "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7",
+ "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08",
+ "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6",
+ "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551",
+ "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e",
+ "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288",
+ "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df",
+ "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0",
+ "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2",
+ "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05",
+ "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0",
+ "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464",
+ "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5",
+ "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404",
+ "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7",
+ "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139",
+ "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394",
+ "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb",
+ "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15",
+ "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff",
+ "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed",
+ "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6",
+ "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e",
+ "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95",
+ "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d",
+ "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950",
+ "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3",
+ "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5",
+ "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97",
+ "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e",
+ "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e",
+ "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b",
+ "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd",
+ "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad",
+ "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8",
+ "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425",
+ "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221",
+ "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d",
+ "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825",
+ "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51",
+ "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e",
+ "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f",
+ "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8",
+ "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f",
+ "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d",
+ "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07",
+ "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877",
+ "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31",
+ "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58",
+ "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94",
+ "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28",
+ "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000",
+ "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1",
+ "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1",
+ "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7",
+ "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7",
+ "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40",
+ "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d",
+ "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0",
+ "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84",
+ "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f",
+ "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a",
+ "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7",
+ "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419",
+ "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8",
+ "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a",
+ "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9",
+ "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be",
+ "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed",
+ "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a",
+ "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d",
+ "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324",
+ "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f",
+ "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2",
+ "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f",
+ "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"
],
- "markers": "python_version >= '3.9'",
- "version": "==0.27.1"
+ "markers": "python_version >= '3.10'",
+ "version": "==0.30.0"
+ },
+ "shellingham": {
+ "hashes": [
+ "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686",
+ "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==1.5.4"
},
"six": {
"hashes": [
@@ -2311,21 +2605,28 @@
"markers": "python_version >= '3.7'",
"version": "==1.3.1"
},
+ "sortedcontainers": {
+ "hashes": [
+ "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
+ "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
+ ],
+ "version": "==2.4.0"
+ },
"sse-starlette": {
"hashes": [
- "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a",
- "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a"
+ "sha256:32c80ef0d04506ced4b0b6ab8fe300925edc37d26f666afb1874c754895f5dc3",
+ "sha256:5e34286862e96ead0eb70f5ddd0bd21ab1f6473a8f44419dd267f431611383dd"
],
"markers": "python_version >= '3.9'",
- "version": "==3.0.2"
+ "version": "==3.0.4"
},
"starlette": {
"hashes": [
- "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659",
- "sha256:7e8cee469a8ab2352911528110ce9088fdc6a37d9876926e73da7ce4aa4c7a46"
+ "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca",
+ "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca"
],
- "markers": "python_version >= '3.9'",
- "version": "==0.48.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==0.50.0"
},
"tenacity": {
"hashes": [
@@ -2428,6 +2729,22 @@
"markers": "python_version >= '3.7'",
"version": "==4.67.1"
},
+ "typer": {
+ "hashes": [
+ "sha256:1aaf6494031793e4876fb0bacfa6a912b551cf43c1e63c800df8b1a866720c37",
+ "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==0.20.0"
+ },
+ "typer-slim": {
+ "hashes": [
+ "sha256:9fc6607b3c6c20f5c33ea9590cbeb17848667c51feee27d9e314a579ab07d1a3",
+ "sha256:f42a9b7571a12b97dddf364745d29f12221865acef7a2680065f9bb29c7dc89d"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==0.20.0"
+ },
"typing-extensions": {
"hashes": [
"sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466",
@@ -2446,28 +2763,182 @@
},
"urllib3": {
"hashes": [
- "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760",
- "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"
+ "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797",
+ "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"
],
"markers": "python_version >= '3.9'",
- "version": "==2.5.0"
+ "version": "==2.6.2"
},
"uvicorn": {
"hashes": [
- "sha256:4115c8add6d3fd536c8ee77f0e14a7fd2ebba939fed9b02583a97f80648f9e13",
- "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c"
+ "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02",
+ "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d"
],
"index": "pypi",
"markers": "python_version >= '3.9'",
- "version": "==0.37.0"
- },
- "werkzeug": {
- "hashes": [
- "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4",
- "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5"
+ "version": "==0.38.0"
+ },
+ "websockets": {
+ "hashes": [
+ "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2",
+ "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9",
+ "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5",
+ "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3",
+ "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8",
+ "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e",
+ "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1",
+ "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256",
+ "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85",
+ "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880",
+ "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123",
+ "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375",
+ "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065",
+ "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed",
+ "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41",
+ "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411",
+ "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597",
+ "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f",
+ "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c",
+ "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3",
+ "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb",
+ "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e",
+ "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee",
+ "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f",
+ "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf",
+ "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf",
+ "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4",
+ "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a",
+ "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665",
+ "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22",
+ "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675",
+ "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4",
+ "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d",
+ "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5",
+ "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65",
+ "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792",
+ "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57",
+ "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9",
+ "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3",
+ "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151",
+ "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d",
+ "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475",
+ "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940",
+ "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431",
+ "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee",
+ "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413",
+ "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8",
+ "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b",
+ "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a",
+ "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054",
+ "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb",
+ "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205",
+ "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04",
+ "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4",
+ "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa",
+ "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9",
+ "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122",
+ "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b",
+ "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905",
+ "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770",
+ "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe",
+ "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b",
+ "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562",
+ "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561",
+ "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215",
+ "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931",
+ "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9",
+ "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f",
+ "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"
],
"markers": "python_version >= '3.9'",
- "version": "==3.1.1"
+ "version": "==15.0.1"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56",
+ "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828",
+ "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f",
+ "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396",
+ "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77",
+ "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d",
+ "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139",
+ "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7",
+ "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb",
+ "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f",
+ "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f",
+ "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067",
+ "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f",
+ "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7",
+ "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b",
+ "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc",
+ "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05",
+ "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd",
+ "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7",
+ "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9",
+ "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81",
+ "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977",
+ "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa",
+ "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b",
+ "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe",
+ "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58",
+ "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8",
+ "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77",
+ "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85",
+ "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c",
+ "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df",
+ "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454",
+ "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a",
+ "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e",
+ "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c",
+ "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6",
+ "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5",
+ "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9",
+ "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd",
+ "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277",
+ "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225",
+ "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22",
+ "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116",
+ "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16",
+ "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc",
+ "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00",
+ "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2",
+ "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a",
+ "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804",
+ "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04",
+ "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1",
+ "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba",
+ "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390",
+ "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0",
+ "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d",
+ "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22",
+ "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0",
+ "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2",
+ "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18",
+ "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6",
+ "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311",
+ "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89",
+ "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f",
+ "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39",
+ "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4",
+ "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5",
+ "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa",
+ "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a",
+ "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050",
+ "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6",
+ "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235",
+ "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056",
+ "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2",
+ "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418",
+ "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c",
+ "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a",
+ "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6",
+ "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0",
+ "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775",
+ "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10",
+ "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.17.3"
},
"yarl": {
"hashes": [
@@ -2617,104 +3088,138 @@
"develop": {
"astroid": {
"hashes": [
- "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce",
- "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec"
+ "sha256:ac8fb7ca1c08eb9afec91ccc23edbd8ac73bb22cbdd7da1d488d9fb8d6579070",
+ "sha256:d7546c00a12efc32650b19a2bb66a153883185d3179ab0d4868086f807338b9b"
],
- "markers": "python_full_version >= '3.9.0'",
- "version": "==3.3.11"
+ "markers": "python_full_version >= '3.10.0'",
+ "version": "==4.0.2"
},
"certifi": {
"hashes": [
- "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de",
- "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"
+ "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b",
+ "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"
],
"markers": "python_version >= '3.7'",
- "version": "==2025.10.5"
+ "version": "==2025.11.12"
},
"charset-normalizer": {
"hashes": [
- "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91",
- "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0",
- "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154",
- "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601",
- "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884",
- "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07",
- "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c",
- "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64",
- "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe",
- "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f",
- "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432",
- "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc",
- "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa",
- "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9",
- "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae",
- "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19",
- "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d",
- "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e",
- "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4",
- "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7",
- "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312",
- "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92",
- "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31",
- "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c",
- "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f",
- "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99",
- "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b",
- "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15",
- "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392",
- "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f",
- "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8",
- "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491",
- "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0",
- "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc",
- "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0",
- "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f",
- "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a",
- "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40",
- "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927",
- "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849",
- "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce",
- "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14",
- "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05",
- "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c",
- "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c",
- "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a",
- "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc",
- "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34",
- "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9",
- "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096",
- "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14",
- "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30",
- "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b",
- "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b",
- "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942",
- "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db",
- "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5",
- "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b",
- "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce",
- "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669",
- "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0",
- "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018",
- "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93",
- "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe",
- "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049",
- "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a",
- "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef",
- "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2",
- "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca",
- "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16",
- "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f",
- "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb",
- "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1",
- "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557",
- "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37",
- "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7",
- "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72",
- "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c",
- "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"
+ "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad",
+ "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93",
+ "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394",
+ "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89",
+ "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc",
+ "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86",
+ "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63",
+ "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d",
+ "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f",
+ "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8",
+ "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0",
+ "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505",
+ "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161",
+ "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af",
+ "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152",
+ "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318",
+ "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72",
+ "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4",
+ "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e",
+ "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3",
+ "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576",
+ "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c",
+ "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1",
+ "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8",
+ "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1",
+ "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2",
+ "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44",
+ "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26",
+ "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88",
+ "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016",
+ "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede",
+ "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf",
+ "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a",
+ "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc",
+ "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0",
+ "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84",
+ "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db",
+ "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1",
+ "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7",
+ "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed",
+ "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8",
+ "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133",
+ "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e",
+ "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef",
+ "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14",
+ "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2",
+ "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0",
+ "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d",
+ "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828",
+ "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f",
+ "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf",
+ "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6",
+ "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328",
+ "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090",
+ "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa",
+ "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381",
+ "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c",
+ "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb",
+ "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc",
+ "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a",
+ "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec",
+ "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc",
+ "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac",
+ "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e",
+ "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313",
+ "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569",
+ "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3",
+ "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d",
+ "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525",
+ "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894",
+ "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3",
+ "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9",
+ "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a",
+ "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9",
+ "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14",
+ "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25",
+ "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50",
+ "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf",
+ "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1",
+ "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3",
+ "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac",
+ "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e",
+ "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815",
+ "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c",
+ "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6",
+ "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6",
+ "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e",
+ "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4",
+ "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84",
+ "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69",
+ "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15",
+ "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191",
+ "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0",
+ "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897",
+ "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd",
+ "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2",
+ "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794",
+ "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d",
+ "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074",
+ "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3",
+ "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224",
+ "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838",
+ "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a",
+ "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d",
+ "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d",
+ "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f",
+ "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8",
+ "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490",
+ "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966",
+ "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9",
+ "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3",
+ "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e",
+ "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"
],
"markers": "python_version >= '3.7'",
- "version": "==3.4.3"
+ "version": "==3.4.4"
},
"dill": {
"hashes": [
@@ -2726,87 +3231,81 @@
},
"greenlet": {
"hashes": [
- "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b",
- "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735",
- "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079",
- "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d",
- "sha256:16458c245a38991aa19676900d48bd1a6f2ce3e16595051a4db9d012154e8433",
- "sha256:18d9260df2b5fbf41ae5139e1be4e796d99655f023a636cd0e11e6406cca7d58",
- "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52",
- "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31",
- "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246",
- "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f",
- "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671",
- "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8",
- "sha256:27890167f55d2387576d1f41d9487ef171849ea0359ce1510ca6e06c8bece11d",
- "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f",
- "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0",
- "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd",
- "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337",
- "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0",
- "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633",
- "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b",
- "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa",
- "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31",
- "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9",
- "sha256:65458b409c1ed459ea899e939f0e1cdb14f58dbc803f2f93c5eab5694d32671b",
- "sha256:671df96c1f23c4a0d4077a325483c1503c96a1b7d9db26592ae770daa41233d4",
- "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc",
- "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c",
- "sha256:81701fd84f26330f0d5f4944d4e92e61afe6319dcd9775e39396e39d7c3e5f98",
- "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f",
- "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c",
- "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590",
- "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3",
- "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2",
- "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9",
- "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5",
- "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02",
- "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0",
- "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1",
- "sha256:b6a7c19cf0d2742d0809a4c05975db036fdff50cd294a93632d6a310bf9ac02c",
- "sha256:b90654e092f928f110e0007f572007c9727b5265f7632c2fa7415b4689351594",
- "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5",
- "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d",
- "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a",
- "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6",
- "sha256:c8c9e331e58180d0d83c5b7999255721b725913ff6bc6cf39fa2a45841a4fd4b",
- "sha256:c9913f1a30e4526f432991f89ae263459b1c64d1608c0d22a5c79c287b3c70df",
- "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945",
- "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae",
- "sha256:d2e685ade4dafd447ede19c31277a224a239a0a1a4eca4e6390efedf20260cfb",
- "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504",
- "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb",
- "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01",
- "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c",
- "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968"
+ "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b",
+ "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527",
+ "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365",
+ "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221",
+ "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd",
+ "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53",
+ "sha256:2de5a0b09eab81fc6a382791b995b1ccf2b172a9fec934747a7a23d2ff291794",
+ "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492",
+ "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3",
+ "sha256:39b28e339fc3c348427560494e28d8a6f3561c8d2bcf7d706e1c624ed8d822b9",
+ "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3",
+ "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b",
+ "sha256:4243050a88ba61842186cb9e63c7dfa677ec146160b0efd73b855a3d9c7fcf32",
+ "sha256:4449a736606bd30f27f8e1ff4678ee193bc47f6ca810d705981cfffd6ce0d8c5",
+ "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8",
+ "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955",
+ "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f",
+ "sha256:670d0f94cd302d81796e37299bcd04b95d62403883b24225c6b5271466612f45",
+ "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9",
+ "sha256:6cb3a8ec3db4a3b0eb8a3c25436c2d49e3505821802074969db017b87bc6a948",
+ "sha256:6f8496d434d5cb2dce025773ba5597f71f5410ae499d5dd9533e0653258cdb3d",
+ "sha256:73631cd5cccbcfe63e3f9492aaa664d278fda0ce5c3d43aeda8e77317e38efbd",
+ "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170",
+ "sha256:7652ee180d16d447a683c04e4c5f6441bae7ba7b17ffd9f6b3aff4605e9e6f71",
+ "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54",
+ "sha256:7dee147740789a4632cace364816046e43310b59ff8fb79833ab043aefa72fd5",
+ "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614",
+ "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3",
+ "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38",
+ "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808",
+ "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739",
+ "sha256:a687205fb22794e838f947e2194c0566d3812966b41c78709554aa883183fb62",
+ "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39",
+ "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb",
+ "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39",
+ "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55",
+ "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb",
+ "sha256:b299a0cb979f5d7197442dccc3aee67fce53500cd88951b7e6c35575701c980b",
+ "sha256:b3c374782c2935cc63b2a27ba8708471de4ad1abaa862ffdb1ef45a643ddbb7d",
+ "sha256:b49e7ed51876b459bd645d83db257f0180e345d3f768a35a85437a24d5a49082",
+ "sha256:b96dc7eef78fd404e022e165ec55327f935b9b52ff355b067eb4a0267fc1cffb",
+ "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7",
+ "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc",
+ "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931",
+ "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388",
+ "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45",
+ "sha256:e29f3018580e8412d6aaf5641bb7745d38c85228dacf51a73bd4e26ddf2a6a8e",
+ "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655"
],
- "markers": "python_version >= '3.9'",
- "version": "==3.2.4"
+ "markers": "python_version >= '3.10'",
+ "version": "==3.3.0"
},
"idna": {
"hashes": [
- "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9",
- "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"
+ "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea",
+ "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"
],
- "markers": "python_version >= '3.6'",
- "version": "==3.10"
+ "markers": "python_version >= '3.8'",
+ "version": "==3.11"
},
"iniconfig": {
"hashes": [
- "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7",
- "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"
+ "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730",
+ "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"
],
- "markers": "python_version >= '3.8'",
- "version": "==2.1.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==2.3.0"
},
"isort": {
"hashes": [
- "sha256:58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784",
- "sha256:9b8f96a14cfee0677e78e941ff62f03769a06d412aabb9e2a90487b3b7e8d481"
+ "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1",
+ "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187"
],
- "markers": "python_full_version >= '3.9.0'",
- "version": "==6.1.0"
+ "markers": "python_full_version >= '3.10.0'",
+ "version": "==7.0.0"
},
"mccabe": {
"hashes": [
@@ -2826,26 +3325,26 @@
},
"platformdirs": {
"hashes": [
- "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85",
- "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"
+ "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda",
+ "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"
],
- "markers": "python_version >= '3.9'",
- "version": "==4.4.0"
+ "markers": "python_version >= '3.10'",
+ "version": "==4.5.1"
},
"playwright": {
"hashes": [
- "sha256:012dc89ccdcbd774cdde8aeee14c08e0dd52ddb9135bf10e9db040527386bd76",
- "sha256:25b0d6b3fd991c315cca33c802cf617d52980108ab8431e3e1d37b5de755c10e",
- "sha256:29a0777c4ce1273acf90c87e4ae2fe0130182100d99bcd2ae5bf486093044838",
- "sha256:29e6d1558ad9d5b5c19cbec0a72f6a2e35e6353cd9f262e22148685b86759f90",
- "sha256:7eb5956473ca1951abb51537e6a0da55257bb2e25fc37c2b75af094a5c93736c",
- "sha256:8290cf27a5d542e2682ac274da423941f879d07b001f6575a5a3a257b1d4ba1c",
- "sha256:c6d4d8f6f8c66c483b0835569c7f0caa03230820af8e500c181c93509c92d831",
- "sha256:d7da108a95001e412effca4f7610de79da1637ccdf670b1ae3fdc08b9694c034"
+ "sha256:0ef7e6fd653267798a8a968ff7aa2dcac14398b7dd7440ef57524e01e0fbbd65",
+ "sha256:2745490ae8dd58d27e5ea4d9aa28402e8e2991eb84fb4b2fd5fbde2106716f6f",
+ "sha256:3c7fc49bb9e673489bf2622855f9486d41c5101bbed964638552b864c4591f94",
+ "sha256:404be089b49d94bc4c1fe0dfb07664bda5ffe87789034a03bffb884489bdfb5c",
+ "sha256:64cda7cf4e51c0d35dab55190841bfcdfb5871685ec22cb722cd0ad2df183e34",
+ "sha256:b228b3395212b9472a4ee5f1afe40d376eef9568eb039fcb3e563de8f4f4657b",
+ "sha256:b33eb89c516cbc6723f2e3523bada4a4eb0984a9c411325c02d7016a5d625e9c",
+ "sha256:d87b79bcb082092d916a332c27ec9732e0418c319755d235d93cc6be13bdd721"
],
"index": "pypi",
"markers": "python_version >= '3.9'",
- "version": "==1.55.0"
+ "version": "==1.56.0"
},
"pluggy": {
"hashes": [
@@ -2873,12 +3372,12 @@
},
"pylint": {
"hashes": [
- "sha256:01f9b0462c7730f94786c283f3e52a1fbdf0494bbe0971a78d7277ef46a751e7",
- "sha256:d312737d7b25ccf6b01cc4ac629b5dcd14a0fcf3ec392735ac70f137a9d5f83a"
+ "sha256:63e06a37d5922555ee2c20963eb42559918c20bd2b21244e4ef426e7c43b92e0",
+ "sha256:d9b71674e19b1c36d79265b5887bf8e55278cbe236c9e95d22dc82cf044fdbd2"
],
"index": "pypi",
- "markers": "python_full_version >= '3.9.0'",
- "version": "==3.3.9"
+ "markers": "python_full_version >= '3.10.0'",
+ "version": "==4.0.4"
},
"pytest": {
"hashes": [
@@ -2908,12 +3407,12 @@
},
"pytest-playwright": {
"hashes": [
- "sha256:94b551b2677ecdc16284fcd6a4f0045eafda47a60e74410f3fe4d8260e12cabf",
- "sha256:fcc46510fb75f8eba6df3bc8e84e4e902483d92be98075f20b9d160651a36d90"
+ "sha256:247b61123b28c7e8febb993a187a07e54f14a9aa04edc166f7a976d88f04c770",
+ "sha256:8084e015b2b3ecff483c2160f1c8219b38b66c0d4578b23c0f700d1b0240ea38"
],
"index": "pypi",
- "markers": "python_version >= '3.9'",
- "version": "==0.7.1"
+ "markers": "python_version >= '3.10'",
+ "version": "==0.7.2"
},
"python-slugify": {
"hashes": [
@@ -2956,11 +3455,11 @@
},
"urllib3": {
"hashes": [
- "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760",
- "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"
+ "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797",
+ "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd"
],
"markers": "python_version >= '3.9'",
- "version": "==2.5.0"
+ "version": "==2.6.2"
}
}
}
diff --git a/README.md b/README.md
index 17d60f44..105065b0 100644
--- a/README.md
+++ b/README.md
@@ -232,7 +232,7 @@ Follow these steps to run and develop QueryWeaver from source.
- Python 3.12+
- pipenv
- A FalkorDB instance (local or remote)
-- Node.js and npm (for the TypeScript frontend)
+- Node.js and npm (for the React frontend)
### Install and configure
@@ -276,11 +276,11 @@ make run-prod # production mode (ensure frontend build if needed)
### Frontend build (when needed)
-The frontend is a TypeScript app in `app/`. Build before production runs or after frontend changes:
+The frontend is a modern React + Vite app in `app/`. Build before production runs or after frontend changes:
```bash
make install # installs backend and frontend deps
-make build-prod # builds the frontend into app/public/js/app.js
+make build-prod # builds the frontend into app/dist/
# or manually
cd app
@@ -416,7 +416,7 @@ GitHub Actions run unit and E2E tests on pushes and pull requests. Failures capt
## Project layout (high level)
- `api/` – FastAPI backend
-- `app/` – TypeScript frontend
+- `app/` – React + Vite frontend
- `tests/` – unit and E2E tests
diff --git a/api/agents/analysis_agent.py b/api/agents/analysis_agent.py
index 0c677af7..ccd7c98a 100644
--- a/api/agents/analysis_agent.py
+++ b/api/agents/analysis_agent.py
@@ -202,6 +202,7 @@ def _build_prompt( # pylint: disable=too-many-arguments, too-many-positional-a
- Never skip explaining missing information, ambiguities, or instruction issues.
- Respond ONLY in strict JSON format, without extra text.
- If the query relates to a previous question, you MUST take into account the previous question and its answer, and answer based on the context and information provided so far.
+ - CRITICAL: When table or column names contain special characters (especially dashes/hyphens like '-'), you MUST wrap them in double quotes for PostgreSQL (e.g., "table-name") or backticks for MySQL (e.g., `table-name`). This is NON-NEGOTIABLE.
If the user is asking a follow-up or continuing question, use the conversation history and previous answers to resolve references, context, or ambiguities. Always base your analysis on the cumulative context, not just the current question.
diff --git a/api/app_factory.py b/api/app_factory.py
index b774f7db..c3920487 100644
--- a/api/app_factory.py
+++ b/api/app_factory.py
@@ -5,7 +5,7 @@
from dotenv import load_dotenv
from fastapi import FastAPI, Request, HTTPException
-from fastapi.responses import RedirectResponse, JSONResponse
+from fastapi.responses import RedirectResponse, JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from starlette.middleware.sessions import SessionMiddleware
from starlette.middleware.base import BaseHTTPMiddleware
@@ -184,16 +184,55 @@ def custom_openapi():
# Add security middleware
app.add_middleware(SecurityMiddleware)
- # Mount static files
- static_path = os.path.join(os.path.dirname(__file__), "../app/public")
- if os.path.exists(static_path):
- app.mount("/static", StaticFiles(directory=static_path), name="static")
+ # Mount static files from the React build (app/dist)
+ # This serves the bundled assets (JS, CSS, images, etc.)
+ dist_path = os.path.join(os.path.dirname(__file__), "../app/dist")
+ if os.path.exists(dist_path):
+ # Mount the built React app's static assets
+ # Vite bundles JS/CSS into assets/, and copies public/ files to dist root
+ app.mount(
+ "/assets",
+ StaticFiles(directory=os.path.join(dist_path, "assets")),
+ name="assets"
+ )
+
+ # Mount public folders if they exist
+ if os.path.exists(os.path.join(dist_path, "icons")):
+ app.mount(
+ "/icons",
+ StaticFiles(directory=os.path.join(dist_path, "icons")),
+ name="icons"
+ )
+ if os.path.exists(os.path.join(dist_path, "img")):
+ app.mount(
+ "/img",
+ StaticFiles(directory=os.path.join(dist_path, "img")),
+ name="img"
+ )
+
+ # Serve favicon and other root files
+ app.mount("/static", StaticFiles(directory=dist_path), name="static")
+ else:
+ logging.warning(
+ "React build directory not found at %s. "
+ "Run 'cd app && npm run build' to build the frontend.",
+ dist_path
+ )
# Initialize authentication (OAuth and sessions)
init_auth(app)
setup_oauth_handlers(app, app.state.oauth)
+ # Serve favicon
+ @app.get("/favicon.ico", include_in_schema=False)
+ async def favicon():
+ """Serve the favicon from the React build directory."""
+ favicon_path = os.path.join(dist_path, "favicon.ico")
+ if os.path.exists(favicon_path):
+ return FileResponse(favicon_path, media_type="image/x-icon")
+ return JSONResponse({"error": "Favicon not found"}, status_code=404)
+
@app.exception_handler(Exception)
async def handle_oauth_error(
request: Request, exc: Exception
@@ -212,4 +251,14 @@ async def handle_oauth_error(
# For other errors, let them bubble up
raise exc
+ # Serve React app for all non-API routes (SPA catch-all)
+ @app.get("/{full_path:path}", include_in_schema=False)
+ async def serve_react_app(_full_path: str):
+ """Serve the React app for all routes not handled by API endpoints."""
+ # Serve index.html for the React SPA
+ index_path = os.path.join(dist_path, "index.html")
+ if os.path.exists(index_path):
+ return FileResponse(index_path)
+ return JSONResponse({"error": "React app not found"}, status_code=404)
+
return app
diff --git a/api/auth/user_management.py b/api/auth/user_management.py
index 27c3349e..c7a82196 100644
--- a/api/auth/user_management.py
+++ b/api/auth/user_management.py
@@ -291,6 +291,39 @@ async def wrapper(request: Request, *args, **kwargs):
return wrapper
+def token_optional(func):
+ """Decorator for routes that work with or without authentication.
+ Sets request.state.user_id if authenticated, None if not.
+ Does not raise 401 - allows unauthenticated access.
+ """
+
+ @wraps(func)
+ async def wrapper(request: Request, *args, **kwargs):
+ try:
+ user_info, is_authenticated = await validate_user(request)
+
+ if is_authenticated and user_info:
+ # Authenticated - set user info
+ email = user_info.get("email")
+ request.state.user_id = base64.b64encode(email.encode()).decode()
+ request.state.user_email = email
+ else:
+ # Not authenticated - set to None (allow demo mode)
+ request.state.user_id = None
+ request.state.user_email = None
+
+ return await func(request, *args, **kwargs)
+
+ except Exception as e: # pylint: disable=broad-exception-caught
+ logging.exception("Unexpected error in token_optional: %s", e)
+ # Don't raise 401 - allow the request to proceed
+ request.state.user_id = None
+ request.state.user_email = None
+ return await func(request, *args, **kwargs)
+
+ return wrapper
+
+
def _validate_user_input(provider_user_id: str, email: str, provider: str):
"""Validate input parameters for user creation/update."""
if not provider_user_id or not email or not provider:
diff --git a/api/core/schema_loader.py b/api/core/schema_loader.py
index 3e54a576..bb4dcedb 100644
--- a/api/core/schema_loader.py
+++ b/api/core/schema_loader.py
@@ -127,7 +127,8 @@ async def generate():
yield _step_result(progress)
except InvalidArgumentError as ia:
- yield _step_result({"type": "error", "message": str(ia)})
+ logging.warning("Invalid argument in load_database: %s", str(ia))
+ yield _step_result({"type": "error", "message": "Invalid database connection request"})
except Exception as e: # pylint: disable=broad-exception-caught
logging.exception("Unexpected error in connect_database stream: %s", str(e))
yield _step_result({"type": "error", "message": "Internal server error"})
diff --git a/api/core/text2sql.py b/api/core/text2sql.py
index 4adb450e..4df9db08 100644
--- a/api/core/text2sql.py
+++ b/api/core/text2sql.py
@@ -18,6 +18,7 @@
from api.loaders.postgres_loader import PostgresLoader
from api.loaders.mysql_loader import MySQLLoader
from api.memory.graphiti_tool import MemoryTool
+from api.sql_utils import SQLIdentifierQuoter, DatabaseSpecificQuoter
# Use the same delimiter as in the JavaScript
MESSAGE_DELIMITER = "|||FALKORDB_MESSAGE_BOUNDARY|||"
@@ -316,6 +317,33 @@ async def generate(): # pylint: disable=too-many-locals,too-many-branches,too-m
follow_up_result = ""
execution_error = False
+ # Auto-quote table names with special characters (like dashes)
+ original_sql = answer_an['sql_query']
+ if original_sql:
+ # Extract known table names from the result schema
+ known_tables = {table[0] for table in result} if result else set()
+
+ # Determine database type and get appropriate quote character
+ db_type, _ = get_database_type_and_loader(db_url)
+ quote_char = DatabaseSpecificQuoter.get_quote_char(
+ db_type or 'postgresql'
+ )
+
+ # Auto-quote identifiers with special characters
+ sanitized_sql, was_modified = (
+ SQLIdentifierQuoter.auto_quote_identifiers(
+ original_sql, known_tables, quote_char
+ )
+ )
+
+ if was_modified:
+ msg = (
+ "SQL query auto-sanitized: quoted table names with "
+ "special characters"
+ )
+ logging.info(msg)
+ answer_an['sql_query'] = sanitized_sql
+
logging.info("Generated SQL query: %s", answer_an['sql_query']) # nosemgrep
yield json.dumps(
{
@@ -590,7 +618,7 @@ async def generate(): # pylint: disable=too-many-locals,too-many-branches,too-m
return generate()
-async def execute_destructive_operation(
+async def execute_destructive_operation( # pylint: disable=too-many-statements
user_id: str,
graph_id: str,
confirm_data: ConfirmRequest,
@@ -613,7 +641,7 @@ async def execute_destructive_operation(
raise InvalidArgumentError("No SQL query provided")
# Create a generator function for streaming the confirmation response
- async def generate_confirmation():
+ async def generate_confirmation(): # pylint: disable=too-many-locals,too-many-statements
# Create memory tool for saving query results
memory_tool = await MemoryTool.create(user_id, graph_id)
@@ -635,6 +663,39 @@ async def generate_confirmation():
"message": "Step 2: Executing confirmed SQL query"}
yield json.dumps(step) + MESSAGE_DELIMITER
+ # Auto-quote table names for confirmed destructive operations
+ sql_query = confirm_data.sql_query if hasattr(
+ confirm_data, 'sql_query'
+ ) else ""
+ if sql_query:
+ # Get schema to extract known tables
+ graph = db.select_graph(graph_id)
+ tables_query = "MATCH (t:Table) RETURN t.name"
+ try:
+ tables_res = (await graph.query(tables_query)).result_set
+ known_tables = (
+ {row[0] for row in tables_res}
+ if tables_res else set()
+ )
+ except Exception: # pylint: disable=broad-exception-caught
+ known_tables = set()
+
+ # Determine database type and get appropriate quote character
+ db_type, _ = get_database_type_and_loader(db_url)
+ quote_char = DatabaseSpecificQuoter.get_quote_char(
+ db_type or 'postgresql'
+ )
+
+ # Auto-quote identifiers
+ sanitized_sql, was_modified = (
+ SQLIdentifierQuoter.auto_quote_identifiers(
+ sql_query, known_tables, quote_char
+ )
+ )
+ if was_modified:
+ logging.info("Confirmed SQL query auto-sanitized")
+ sql_query = sanitized_sql
+
# Check if this query modifies the database schema using appropriate loader
is_schema_modifying, operation_type = (
loader_class.is_schema_modifying_query(sql_query)
@@ -716,6 +777,7 @@ async def generate_confirmation():
except Exception as e: # pylint: disable=broad-exception-caught
logging.error("Error executing confirmed SQL query: %s", str(e)) # nosemgrep
+ error_message = str(e) if str(e) else "Error executing query"
# Save failed confirmed query to memory
save_query_task = asyncio.create_task(
@@ -736,7 +798,7 @@ async def generate_confirmation():
)
yield json.dumps(
- {"type": "error", "message": "Error executing query"}
+ {"type": "error", "message": error_message}
) + MESSAGE_DELIMITER
else:
# User cancelled or provided invalid confirmation
diff --git a/api/loaders/mysql_loader.py b/api/loaders/mysql_loader.py
index 6ec40a06..2938b263 100644
--- a/api/loaders/mysql_loader.py
+++ b/api/loaders/mysql_loader.py
@@ -205,10 +205,10 @@ async def load(prefix: str, connection_url: str) -> AsyncGenerator[tuple[bool, s
except pymysql.MySQLError as e:
logging.error("MySQL connection error: %s", e)
- yield False, f"MySQL connection error: {str(e)}"
+ yield False, "Failed to connect to MySQL database"
except Exception as e: # pylint: disable=broad-exception-caught
logging.error("Error loading MySQL schema: %s", e)
- yield False, f"Error loading MySQL schema: {str(e)}"
+ yield False, "Failed to load MySQL database schema"
@staticmethod
def extract_tables_info(cursor, db_name: str) -> Dict[str, Any]:
diff --git a/api/loaders/postgres_loader.py b/api/loaders/postgres_loader.py
index 354a528f..cd44e77f 100644
--- a/api/loaders/postgres_loader.py
+++ b/api/loaders/postgres_loader.py
@@ -148,10 +148,10 @@ async def load(prefix: str, connection_url: str) -> AsyncGenerator[tuple[bool, s
except psycopg2.Error as e:
logging.error("PostgreSQL connection error: %s", e)
- yield False, f"PostgreSQL connection error: {str(e)}"
+ yield False, "Failed to connect to PostgreSQL database"
except Exception as e: # pylint: disable=broad-exception-caught
logging.error("Error loading PostgreSQL schema: %s", e)
- yield False, f"Error loading PostgreSQL schema: {str(e)}"
+ yield False, "Failed to load PostgreSQL database schema"
@staticmethod
def extract_tables_info(cursor) -> Dict[str, Any]:
diff --git a/api/routes/auth.py b/api/routes/auth.py
index c7ddb675..01613eb7 100644
--- a/api/routes/auth.py
+++ b/api/routes/auth.py
@@ -391,25 +391,37 @@ def _build_callback_url(request: Request, path: str) -> str:
return urljoin(base, path.lstrip("/"))
# ---- Routes ----
-@auth_router.get("/", response_class=HTMLResponse)
-async def home(request: Request) -> HTMLResponse:
+@auth_router.get("/", response_class=HTMLResponse, include_in_schema=False)
+async def home() -> HTMLResponse:
"""
- Handle the home page, rendering the landing page for unauthenticated users
- and the chat page for authenticated users.
+ Serve the React SPA (Single Page Application).
+ The React app handles authentication state via /auth-status endpoint.
"""
- user_info, is_authenticated_flag = await validate_user(request)
- auth_config = _get_auth_config()
-
- return templates.TemplateResponse(
- "chat.j2",
- {
- "request": request,
- "is_authenticated": is_authenticated_flag,
- "user_info": user_info,
- "general_prefix": GENERAL_PREFIX,
- **auth_config,
- }
- )
+ from fastapi.responses import FileResponse
+
+ # Serve the React build's index.html
+ dist_path = Path(__file__).resolve().parents[1] / "../app/dist"
+ index_path = dist_path / "index.html"
+
+ if not index_path.exists():
+ return HTMLResponse(
+ content="""
+
+
QueryWeaver - Build Required
+
+ 🛠️ Frontend Not Built
+ Please build the React frontend first:
+ cd app && npm run build
+ Or run in development mode (recommended for development):
+ cd app && npm run dev
+ The dev server will run on http://localhost:8080 with hot reload.
+
+
+ """,
+ status_code=503
+ )
+
+ return FileResponse(index_path)
@auth_router.get("/login/google", name="google.login", response_class=RedirectResponse)
async def login_google(request: Request) -> RedirectResponse:
@@ -507,7 +519,7 @@ async def google_authorized(request: Request) -> RedirectResponse:
except Exception as e:
logging.error("Google OAuth authentication failed: %s", str(e)) # nosemgrep
- raise HTTPException(status_code=400, detail=f"Authentication failed: {str(e)}") from e
+ raise HTTPException(status_code=400, detail="Authentication failed") from e
@auth_router.get("/login/google/callback", response_class=RedirectResponse)
@@ -611,7 +623,7 @@ async def github_authorized(request: Request) -> RedirectResponse:
except Exception as e:
logging.error("GitHub OAuth authentication failed: %s", str(e)) # nosemgrep
- raise HTTPException(status_code=400, detail=f"Authentication failed: {str(e)}") from e
+ raise HTTPException(status_code=400, detail="Authentication failed") from e
@auth_router.get("/login/github/callback", response_class=RedirectResponse)
@@ -622,17 +634,62 @@ async def github_callback_compat(request: Request) -> RedirectResponse:
return RedirectResponse(url=redirect, status_code=status.HTTP_307_TEMPORARY_REDIRECT)
-@auth_router.get("/logout", response_class=RedirectResponse)
-async def logout(request: Request) -> RedirectResponse:
- """Handle user logout and delete session cookies."""
- resp = RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
+@auth_router.get("/auth-status")
+async def auth_status(request: Request) -> JSONResponse:
+ """Check authentication status for the React app.
+
+ Returns:
+ JSONResponse: Authentication status with user info if authenticated
+ """
+ user_info, is_authenticated = await validate_user(request)
+
+ if is_authenticated and user_info:
+ return JSONResponse(
+ content={
+ "authenticated": True,
+ "user": {
+ "id": str(user_info.get("id")),
+ "email": user_info.get("email"),
+ "name": user_info.get("name"),
+ "picture": user_info.get("picture"),
+ "provider": user_info.get("provider")
+ }
+ }
+ )
+
+ # Not authenticated - return 200 with authenticated: false
+ # This is NOT an error - unauthenticated users can still use the app
+ return JSONResponse(
+ content={"authenticated": False},
+ status_code=200
+ )
+
+
+@auth_router.get("/logout")
+@auth_router.post("/logout")
+async def logout(request: Request):
+ """Handle user logout and delete session cookies.
+ Supports both GET and POST methods for backward compatibility:
+ - GET: For direct navigation (bookmarks, links, old clients)
+ - POST: For programmatic logout from the app
+ """
+ # For GET requests, redirect to home page
+ if request.method == "GET":
+ response = RedirectResponse(url="/", status_code=302)
+ api_token = request.cookies.get("api_token")
+ if api_token:
+ response.delete_cookie("api_token")
+ await delete_user_token(api_token)
+ return response
+
+ # For POST requests, return JSON
+ response = JSONResponse(content={"success": True})
api_token = request.cookies.get("api_token")
if api_token:
- resp.delete_cookie("api_token")
+ response.delete_cookie("api_token")
await delete_user_token(api_token)
-
- return resp
+ return response
# ---- Hook for app factory ----
def init_auth(app):
diff --git a/api/routes/database.py b/api/routes/database.py
index 0454161a..293c63ad 100644
--- a/api/routes/database.py
+++ b/api/routes/database.py
@@ -30,6 +30,7 @@ async def connect_database(request: Request, db_request: DatabaseConnectionReque
Accepts a JSON payload with a database URL and attempts to connect.
Supports both PostgreSQL and MySQL databases.
Streams progress steps as a sequence of JSON messages separated by MESSAGE_DELIMITER.
+ Requires authentication.
"""
generator = await load_database(db_request.url, request.state.user_id)
return StreamingResponse(generator, media_type="application/json")
diff --git a/api/routes/graphs.py b/api/routes/graphs.py
index a3b14e22..a7403e78 100644
--- a/api/routes/graphs.py
+++ b/api/routes/graphs.py
@@ -1,5 +1,6 @@
"""Graph-related routes for the text2sql API."""
+import logging
from fastapi import APIRouter, Request, HTTPException, UploadFile, File
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel
@@ -38,12 +39,13 @@ class GraphData(BaseModel):
"",
operation_id="list_databases",
tags=["mcp_tool"],
- responses={401: UNAUTHORIZED_RESPONSE},
+ responses={401: UNAUTHORIZED_RESPONSE}
)
@token_required
async def list_graphs(request: Request):
"""
- This route is used to list all the graphs (databases names) that are available in the database.
+ List all available graphs/databases for the authenticated user.
+ Requires authentication.
"""
graphs = await list_databases(request.state.user_id, GENERAL_PREFIX)
return JSONResponse(content=graphs)
@@ -53,17 +55,14 @@ async def list_graphs(request: Request):
"/{graph_id}/data",
operation_id="database_schema",
tags=["mcp_tool"],
- responses={401: UNAUTHORIZED_RESPONSE},
+ responses={401: UNAUTHORIZED_RESPONSE}
)
@token_required
async def get_graph_data(
request: Request, graph_id: str
): # pylint: disable=too-many-locals,too-many-branches
- """Return all nodes and edges for the specified database schema (namespaced to the user).
-
- This endpoint returns a JSON object with two keys: `nodes` and `edges`.
- Nodes contain a minimal set of properties (id, name, labels, props).
- Edges contain source and target node names (or internal ids), type and props.
+ """Return all nodes and edges for the specified database schema.
+ Requires authentication.
args:
graph_id (str): The ID of the graph to query (the database name).
@@ -73,9 +72,14 @@ async def get_graph_data(
schema = await get_schema(request.state.user_id, graph_id)
return JSONResponse(content=schema)
except GraphNotFoundError as gnfe:
- return JSONResponse(content={"error": str(gnfe)}, status_code=404)
+ logging.warning("Graph not found: %s", str(gnfe))
+ return JSONResponse(content={"error": "Database not found"}, status_code=404)
except InternalError as ie:
- return JSONResponse(content={"error": str(ie)}, status_code=500)
+ logging.error("Internal error getting schema: %s", str(ie))
+ return JSONResponse(
+ content={"error": "Failed to retrieve database schema"},
+ status_code=500
+ )
@graphs_router.post("", responses={401: UNAUTHORIZED_RESPONSE})
@@ -125,7 +129,7 @@ async def load_graph(
"/{graph_id}",
operation_id="query_database",
tags=["mcp_tool"],
- responses={401: UNAUTHORIZED_RESPONSE},
+ responses={401: UNAUTHORIZED_RESPONSE}
)
@token_required
async def query_graph(
@@ -133,6 +137,7 @@ async def query_graph(
): # pylint: disable=too-many-statements
"""
Query the Database with the given graph_id and chat_data.
+ Requires authentication.
Args:
graph_id (str): The ID of the graph to query.
@@ -142,7 +147,8 @@ async def query_graph(
generator = await query_database(request.state.user_id, graph_id, chat_data)
return StreamingResponse(generator, media_type="application/json")
except InvalidArgumentError as iae:
- return JSONResponse(content={"error": str(iae)}, status_code=400)
+ logging.warning("Invalid argument in query: %s", str(iae))
+ return JSONResponse(content={"error": "Invalid query request"}, status_code=400)
@graphs_router.post("/{graph_id}/confirm", responses={401: UNAUTHORIZED_RESPONSE})
@@ -153,7 +159,8 @@ async def confirm_destructive_operation(
confirm_data: ConfirmRequest,
):
"""
- Handle user confirmation for destructive SQL operations
+ Handle user confirmation for destructive SQL operations.
+ Requires authentication.
"""
try:
@@ -162,7 +169,8 @@ async def confirm_destructive_operation(
)
return StreamingResponse(generator, media_type="application/json")
except InvalidArgumentError as iae:
- return JSONResponse(content={"error": str(iae)}, status_code=400)
+ logging.warning("Invalid argument in destructive operation: %s", str(iae))
+ return JSONResponse(content={"error": "Invalid confirmation request"}, status_code=400)
@graphs_router.post("/{graph_id}/refresh", responses={401: UNAUTHORIZED_RESPONSE})
@@ -172,11 +180,22 @@ async def refresh_graph_schema(request: Request, graph_id: str):
Manually refresh the graph schema from the database.
This endpoint allows users to manually trigger a schema refresh
if they suspect the graph is out of sync with the database.
+ Streams progress steps as a sequence of JSON messages.
"""
try:
- return await refresh_database_schema(request.state.user_id, graph_id)
- except InternalError as ie:
- return JSONResponse(content={"error": str(ie)}, status_code=500)
+ generator = await refresh_database_schema(request.state.user_id, graph_id)
+ return StreamingResponse(generator, media_type="application/json")
+ except (InternalError, InvalidArgumentError) as e:
+ # Log detailed error internally, send generic message to user
+ if isinstance(e, InternalError):
+ logging.error("Internal error refreshing schema: %s", str(e))
+ error_message = "Failed to refresh database schema"
+ status_code = 500
+ else:
+ logging.warning("Invalid argument refreshing schema: %s", str(e))
+ error_message = "Invalid request to refresh schema"
+ status_code = 400
+ return JSONResponse(content={"error": error_message}, status_code=status_code)
@graphs_router.delete("/{graph_id}", responses={401: UNAUTHORIZED_RESPONSE})
@@ -195,8 +214,14 @@ async def delete_graph(request: Request, graph_id: str):
return JSONResponse(content=result)
except InvalidArgumentError as iae:
- return JSONResponse(content={"error": str(iae)}, status_code=400)
+ logging.warning("Invalid argument in delete: %s", str(iae))
+ return JSONResponse(content={"error": "Invalid delete request"}, status_code=400)
except GraphNotFoundError as gnfe:
- return JSONResponse(content={"error": str(gnfe)}, status_code=404)
+ logging.warning("Graph not found for deletion: %s", str(gnfe))
+ return JSONResponse(content={"error": "Database not found"}, status_code=404)
except InternalError as ie:
- return JSONResponse(content={"error": str(ie)}, status_code=500)
+ logging.error("Internal error deleting database: %s", str(ie))
+ return JSONResponse(
+ content={"error": "Failed to delete database"},
+ status_code=500
+ )
diff --git a/api/sql_utils/__init__.py b/api/sql_utils/__init__.py
new file mode 100644
index 00000000..795a5a40
--- /dev/null
+++ b/api/sql_utils/__init__.py
@@ -0,0 +1,5 @@
+"""Utility modules for QueryWeaver API."""
+
+from .sql_sanitizer import SQLIdentifierQuoter, DatabaseSpecificQuoter
+
+__all__ = ['SQLIdentifierQuoter', 'DatabaseSpecificQuoter']
diff --git a/api/sql_utils/sql_sanitizer.py b/api/sql_utils/sql_sanitizer.py
new file mode 100644
index 00000000..6f7d127e
--- /dev/null
+++ b/api/sql_utils/sql_sanitizer.py
@@ -0,0 +1,171 @@
+"""SQL sanitization utilities for handling identifiers with special characters."""
+
+import re
+from typing import Set, Tuple
+
+
+class SQLIdentifierQuoter:
+ """
+ Utility class for automatically quoting SQL identifiers (table/column names)
+ that contain special characters like dashes.
+ """
+
+ # Characters that require quoting in identifiers
+ SPECIAL_CHARS = {'-', ' ', '.', '@', '#', '$', '%', '^', '&', '*', '(',
+ ')', '+', '=', '[', ']', '{', '}', '|', '\\', ':',
+ ';', '"', "'", '<', '>', ',', '?', '/'}
+ # SQL keywords that should not be quoted
+ SQL_KEYWORDS = {
+ 'SELECT', 'FROM', 'WHERE', 'JOIN', 'LEFT', 'RIGHT', 'INNER', 'OUTER', 'ON',
+ 'AS', 'AND', 'OR', 'NOT', 'IN', 'BETWEEN', 'LIKE', 'IS', 'NULL', 'ORDER',
+ 'BY', 'GROUP', 'HAVING', 'LIMIT', 'OFFSET', 'INSERT', 'UPDATE', 'DELETE',
+ 'CREATE', 'DROP', 'ALTER', 'TABLE', 'INTO', 'VALUES', 'SET', 'COUNT',
+ 'SUM', 'AVG', 'MAX', 'MIN', 'DISTINCT', 'ALL', 'UNION', 'INTERSECT',
+ 'EXCEPT', 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', 'CAST', 'ASC', 'DESC'
+ }
+
+ @classmethod
+ def needs_quoting(cls, identifier: str) -> bool:
+ """
+ Check if an identifier needs quoting based on special characters.
+
+ Args:
+ identifier: The table or column name to check
+
+ Returns:
+ True if the identifier needs quoting, False otherwise
+ """
+ # Already quoted
+ if (identifier.startswith('"') and identifier.endswith('"')) or \
+ (identifier.startswith('`') and identifier.endswith('`')):
+ return False
+
+ # Check if it's a SQL keyword
+ if identifier.upper() in cls.SQL_KEYWORDS:
+ return False
+
+ # Check for special characters
+ return any(char in cls.SPECIAL_CHARS for char in identifier)
+
+ @staticmethod
+ def quote_identifier(identifier: str, quote_char: str = '"') -> str:
+ """
+ Quote an identifier if not already quoted.
+
+ Args:
+ identifier: The identifier to quote
+ quote_char: The quote character to use (default: " for PostgreSQL/standard SQL)
+
+ Returns:
+ Quoted identifier
+ """
+ identifier = identifier.strip()
+
+ # Don't double-quote
+ if (identifier.startswith('"') and identifier.endswith('"')) or \
+ (identifier.startswith('`') and identifier.endswith('`')):
+ return identifier
+
+ return f'{quote_char}{identifier}{quote_char}'
+
+ @classmethod
+ def extract_table_names_from_query(cls, sql_query: str) -> Set[str]:
+ """
+ Extract potential table names from a SQL query.
+ Looks for identifiers after FROM, JOIN, UPDATE, INSERT INTO, etc.
+
+ Args:
+ sql_query: The SQL query to parse
+
+ Returns:
+ Set of potential table names
+ """
+ table_names = set()
+
+ # Pattern to match table names after FROM, JOIN, UPDATE, INSERT INTO, etc.
+ # This is a heuristic approach - not perfect but handles common cases
+ patterns = [
+ r'\bFROM\s+([a-zA-Z0-9_\-]+)',
+ r'\bJOIN\s+([a-zA-Z0-9_\-]+)',
+ r'\bUPDATE\s+([a-zA-Z0-9_\-]+)',
+ r'\bINSERT\s+INTO\s+([a-zA-Z0-9_\-]+)',
+ r'\bTABLE\s+([a-zA-Z0-9_\-]+)',
+ ]
+
+ for pattern in patterns:
+ matches = re.finditer(pattern, sql_query, re.IGNORECASE)
+ for match in matches:
+ table_name = match.group(1).strip()
+ # Skip if it's already quoted or an alias
+ if not ((table_name.startswith('"') and table_name.endswith('"')) or
+ (table_name.startswith('`') and table_name.endswith('`'))):
+ table_names.add(table_name)
+
+ return table_names
+
+ @classmethod
+ def auto_quote_identifiers(
+ cls,
+ sql_query: str,
+ known_tables: Set[str],
+ quote_char: str = '"'
+ ) -> Tuple[str, bool]:
+ """
+ Automatically quote table names with special characters in a SQL query.
+
+ Args:
+ sql_query: The SQL query to process
+ known_tables: Set of known table names from the database schema
+ quote_char: Quote character to use (default: " for PostgreSQL, use ` for MySQL)
+
+ Returns:
+ Tuple of (modified_query, was_modified)
+ """
+ modified = False
+ result_query = sql_query
+
+ # Extract potential table names from query
+ query_tables = cls.extract_table_names_from_query(sql_query)
+
+ # For each table that needs quoting
+ for table in query_tables:
+ # Check if this table exists in known schema and needs quoting
+ if table in known_tables and cls.needs_quoting(table):
+ # Quote the table name
+ quoted = cls.quote_identifier(table, quote_char)
+
+ # Replace unquoted occurrences with quoted version
+ # Use word boundaries to avoid partial replacements
+ # Handle cases: FROM table, JOIN table, table.column, etc.
+ patterns_to_replace = [
+ (rf'\b{re.escape(table)}\b(?!\s*\.)', quoted),
+ (rf'\b{re.escape(table)}\.', f'{quoted}.'),
+ ]
+
+ for pattern, replacement in patterns_to_replace:
+ new_query = re.sub(pattern, replacement, result_query, flags=re.IGNORECASE)
+ if new_query != result_query:
+ modified = True
+ result_query = new_query
+
+ return result_query, modified
+
+
+class DatabaseSpecificQuoter: # pylint: disable=too-few-public-methods
+ """Factory class to get the appropriate quote character for different databases."""
+
+ @staticmethod
+ def get_quote_char(db_type: str) -> str:
+ """
+ Get the appropriate quote character for a database type.
+
+ Args:
+ db_type: Database type ('postgresql', 'mysql', etc.)
+
+ Returns:
+ Quote character to use
+ """
+ if db_type.lower() in ['mysql', 'mariadb']:
+ return '`'
+ # PostgreSQL, SQLite, SQL Server (standard SQL) use double quotes
+ return '"'
diff --git a/app/components.json b/app/components.json
new file mode 100644
index 00000000..62e10116
--- /dev/null
+++ b/app/components.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "src/index.css",
+ "baseColor": "slate",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ }
+}
diff --git a/app/eslint.config.cjs b/app/eslint.config.cjs
index b054baed..bb46a38b 100644
--- a/app/eslint.config.cjs
+++ b/app/eslint.config.cjs
@@ -20,7 +20,10 @@ module.exports = [
{
rules: {
// Base JS recommended rules
- 'no-unused-vars': 'warn',
+ 'no-unused-vars': ['warn', {
+ 'argsIgnorePattern': '^_',
+ 'varsIgnorePattern': '^_'
+ }],
// TypeScript rules
'@typescript-eslint/no-explicit-any': 'off',
},
diff --git a/app/hooks/use-mobile.ts b/app/hooks/use-mobile.ts
new file mode 100644
index 00000000..80e2b99b
--- /dev/null
+++ b/app/hooks/use-mobile.ts
@@ -0,0 +1,18 @@
+import { useEffect, useState } from 'react';
+
+// Returns true if the viewport is less than the given breakpoint (default: 768px)
+export function useIsMobile(breakpoint = 768): boolean {
+ const [isMobile, setIsMobile] = useState(() =>
+ typeof window !== 'undefined' ? window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches : false
+ );
+
+ useEffect(() => {
+ const media = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
+ const listener = () => setIsMobile(media.matches);
+ media.addEventListener('change', listener);
+ setIsMobile(media.matches);
+ return () => media.removeEventListener('change', listener);
+ }, [breakpoint]);
+
+ return isMobile;
+}
diff --git a/app/index.html b/app/index.html
new file mode 100644
index 00000000..bd2ee032
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ QueryWeaver - Text-to-SQL for Enterprise Databases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/package-lock.json b/app/package-lock.json
index 19303528..534f8cf8 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -7,18 +7,104 @@
"": {
"name": "queryweaver-app",
"version": "0.0.1",
+ "dependencies": {
+ "@hookform/resolvers": "^3.10.0",
+ "@radix-ui/react-accordion": "^1.2.11",
+ "@radix-ui/react-alert-dialog": "^1.1.14",
+ "@radix-ui/react-aspect-ratio": "^1.1.7",
+ "@radix-ui/react-avatar": "^1.1.10",
+ "@radix-ui/react-checkbox": "^1.3.2",
+ "@radix-ui/react-collapsible": "^1.1.11",
+ "@radix-ui/react-context-menu": "^2.2.15",
+ "@radix-ui/react-dialog": "^1.1.14",
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
+ "@radix-ui/react-hover-card": "^1.1.14",
+ "@radix-ui/react-label": "^2.1.7",
+ "@radix-ui/react-menubar": "^1.1.15",
+ "@radix-ui/react-navigation-menu": "^1.2.13",
+ "@radix-ui/react-popover": "^1.1.14",
+ "@radix-ui/react-progress": "^1.1.7",
+ "@radix-ui/react-radio-group": "^1.3.7",
+ "@radix-ui/react-scroll-area": "^1.2.9",
+ "@radix-ui/react-select": "^2.2.5",
+ "@radix-ui/react-separator": "^1.1.7",
+ "@radix-ui/react-slider": "^1.3.5",
+ "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-switch": "^1.2.5",
+ "@radix-ui/react-tabs": "^1.1.12",
+ "@radix-ui/react-toast": "^1.2.14",
+ "@radix-ui/react-toggle": "^1.1.9",
+ "@radix-ui/react-toggle-group": "^1.1.10",
+ "@radix-ui/react-tooltip": "^1.2.7",
+ "@tanstack/react-query": "^5.83.0",
+ "@types/d3": "^7.4.3",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "cmdk": "^1.1.1",
+ "d3": "^7.9.0",
+ "date-fns": "^3.6.0",
+ "embla-carousel-react": "^8.6.0",
+ "input-otp": "^1.4.2",
+ "lucide-react": "^0.462.0",
+ "next-themes": "^0.3.0",
+ "react": "^18.3.1",
+ "react-day-picker": "^8.10.1",
+ "react-dom": "^18.3.1",
+ "react-force-graph-2d": "^1.29.0",
+ "react-hook-form": "^7.61.1",
+ "react-resizable-panels": "^2.1.9",
+ "react-router-dom": "^6.30.1",
+ "recharts": "^2.15.4",
+ "sonner": "^1.7.4",
+ "tailwind-merge": "^2.6.0",
+ "tailwindcss-animate": "^1.0.7",
+ "vaul": "^0.9.9",
+ "zod": "^3.25.76"
+ },
"devDependencies": {
- "@typescript-eslint/eslint-plugin": "^8.44.0",
- "@typescript-eslint/parser": "^8.44.0",
- "esbuild": "^0.25.10",
- "eslint": "^9.36.0",
- "typescript": "^5.9.2"
+ "@eslint/js": "^9.32.0",
+ "@tailwindcss/typography": "^0.5.16",
+ "@types/node": "^22.16.5",
+ "@types/react": "^18.3.23",
+ "@types/react-dom": "^18.3.7",
+ "@vitejs/plugin-react-swc": "^3.11.0",
+ "autoprefixer": "^10.4.21",
+ "eslint": "^9.32.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^15.15.0",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.38.0",
+ "vite": "^5.4.19"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
+ "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz",
- "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
"cpu": [
"ppc64"
],
@@ -29,13 +115,13 @@
"aix"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz",
- "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
@@ -46,13 +132,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz",
- "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
@@ -63,13 +149,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz",
- "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
@@ -80,13 +166,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz",
- "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
@@ -97,13 +183,13 @@
"darwin"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz",
- "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
@@ -114,13 +200,13 @@
"darwin"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz",
- "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
@@ -131,13 +217,13 @@
"freebsd"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz",
- "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
@@ -148,13 +234,13 @@
"freebsd"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz",
- "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
@@ -165,13 +251,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz",
- "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
@@ -182,13 +268,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz",
- "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
@@ -199,13 +285,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz",
- "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
@@ -216,13 +302,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz",
- "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
@@ -233,13 +319,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz",
- "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
@@ -250,13 +336,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz",
- "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
@@ -267,13 +353,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz",
- "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
@@ -284,13 +370,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz",
- "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
@@ -301,30 +387,13 @@
"linux"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz",
- "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz",
- "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
@@ -335,30 +404,13 @@
"netbsd"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz",
- "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz",
- "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
@@ -369,30 +421,13 @@
"openbsd"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz",
- "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz",
- "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
@@ -403,13 +438,13 @@
"sunos"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz",
- "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
@@ -420,13 +455,13 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz",
- "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
@@ -437,13 +472,13 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz",
- "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
@@ -454,7 +489,7 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@eslint-community/eslint-utils": {
@@ -476,10 +511,23 @@
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
- "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
"dev": true,
"license": "MIT",
"engines": {
@@ -487,13 +535,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.21.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
- "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.6",
+ "@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -501,44 +549,23 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/config-array/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/@eslint/config-array/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/@eslint/config-helpers": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
- "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
"license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/core": {
- "version": "0.15.2",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
- "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -572,44 +599,23 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
+ "node": ">=18"
},
- "engines": {
- "node": "*"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/js": {
- "version": "9.36.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz",
- "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==",
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
+ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -620,9 +626,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
- "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -630,19 +636,66 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
- "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.15.2",
+ "@eslint/core": "^0.17.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
+ "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.4"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@hookform/resolvers": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz",
+ "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react-hook-form": "^7.0.0"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -695,11 +748,62 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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/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/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
@@ -713,7 +817,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -723,7 +826,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
@@ -733,623 +835,4788 @@
"node": ">= 8"
}
},
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@radix-ui/number": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
"license": "MIT"
},
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
"license": "MIT"
},
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz",
- "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==",
- "dev": true,
+ "node_modules/@radix-ui/react-accordion": {
+ "version": "1.2.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz",
+ "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==",
"license": "MIT",
"dependencies": {
- "@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.44.1",
- "@typescript-eslint/type-utils": "8.44.1",
- "@typescript-eslint/utils": "8.44.1",
- "@typescript-eslint/visitor-keys": "8.44.1",
- "graphemer": "^1.4.0",
- "ignore": "^7.0.0",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collapsible": "1.1.12",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.44.1",
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/parser": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz",
- "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==",
- "dev": true,
+ "node_modules/@radix-ui/react-alert-dialog": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz",
+ "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.44.1",
- "@typescript-eslint/types": "8.44.1",
- "@typescript-eslint/typescript-estree": "8.44.1",
- "@typescript-eslint/visitor-keys": "8.44.1",
- "debug": "^4.3.4"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dialog": "1.1.15",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz",
- "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==",
- "dev": true,
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.44.1",
- "@typescript-eslint/types": "^8.44.1",
- "debug": "^4.3.4"
+ "@radix-ui/react-primitive": "2.1.3"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz",
- "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==",
- "dev": true,
+ "node_modules/@radix-ui/react-aspect-ratio": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.8.tgz",
+ "integrity": "sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.44.1",
- "@typescript-eslint/visitor-keys": "8.44.1"
+ "@radix-ui/react-primitive": "2.1.4"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz",
- "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==",
- "dev": true,
+ "node_modules/@radix-ui/react-aspect-ratio/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
"license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz",
- "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==",
- "dev": true,
+ "node_modules/@radix-ui/react-avatar": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz",
+ "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.44.1",
- "@typescript-eslint/typescript-estree": "8.44.1",
- "@typescript-eslint/utils": "8.44.1",
- "debug": "^4.3.4",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-is-hydrated": "0.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/types": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz",
- "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==",
- "dev": true,
+ "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
"license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz",
- "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==",
- "dev": true,
+ "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.44.1",
- "@typescript-eslint/tsconfig-utils": "8.44.1",
- "@typescript-eslint/types": "8.44.1",
- "@typescript-eslint/visitor-keys": "8.44.1",
- "debug": "^4.3.4",
- "fast-glob": "^3.3.2",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^2.1.0"
+ "@radix-ui/react-slot": "1.2.4"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
+ "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/utils": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz",
- "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==",
- "dev": true,
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
+ "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.44.1",
- "@typescript-eslint/types": "8.44.1",
- "@typescript-eslint/typescript-estree": "8.44.1"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
},
"peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.44.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz",
- "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==",
- "dev": true,
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.44.1",
- "eslint-visitor-keys": "^4.2.1"
+ "@radix-ui/react-compose-refs": "1.1.2"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "dev": true,
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "engines": {
- "node": ">=0.4.0"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
+ "node_modules/@radix-ui/react-context-menu": {
+ "version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz",
+ "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==",
"license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
"peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
"license": "MIT",
"dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
}
},
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
+ "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
"license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1"
+ "@radix-ui/react-compose-refs": "1.1.2"
},
- "engines": {
- "node": ">=8"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
"license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
"license": "MIT",
"dependencies": {
- "fill-range": "^7.1.1"
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
},
- "engines": {
- "node": ">=8"
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-hover-card": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz",
+ "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
+ "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menubar": {
+ "version": "1.1.16",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz",
+ "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.16",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-navigation-menu": {
+ "version": "1.2.14",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz",
+ "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
+ "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz",
+ "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-radio-group": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz",
+ "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-scroll-area": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz",
+ "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-focus-guards": "1.1.3",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+ "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.4"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slider": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
+ "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
+ "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
+ "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toast": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz",
+ "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toggle": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz",
+ "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toggle-group": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz",
+ "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-toggle": "1.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+ "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.11",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.8",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-is-hydrated": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+ "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+ "license": "MIT",
+ "dependencies": {
+ "use-sync-external-store": "^1.5.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.23.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.1.tgz",
+ "integrity": "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.27",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz",
+ "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz",
+ "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz",
+ "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz",
+ "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz",
+ "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz",
+ "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz",
+ "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz",
+ "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz",
+ "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz",
+ "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz",
+ "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz",
+ "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz",
+ "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz",
+ "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz",
+ "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz",
+ "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz",
+ "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz",
+ "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz",
+ "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz",
+ "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz",
+ "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz",
+ "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@swc/core": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.2.tgz",
+ "integrity": "sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "@swc/types": "^0.1.25"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.15.2",
+ "@swc/core-darwin-x64": "1.15.2",
+ "@swc/core-linux-arm-gnueabihf": "1.15.2",
+ "@swc/core-linux-arm64-gnu": "1.15.2",
+ "@swc/core-linux-arm64-musl": "1.15.2",
+ "@swc/core-linux-x64-gnu": "1.15.2",
+ "@swc/core-linux-x64-musl": "1.15.2",
+ "@swc/core-win32-arm64-msvc": "1.15.2",
+ "@swc/core-win32-ia32-msvc": "1.15.2",
+ "@swc/core-win32-x64-msvc": "1.15.2"
+ },
+ "peerDependencies": {
+ "@swc/helpers": ">=0.5.17"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.2.tgz",
+ "integrity": "sha512-Ghyz4RJv4zyXzrUC1B2MLQBbppIB5c4jMZJybX2ebdEQAvryEKp3gq1kBksCNsatKGmEgXul88SETU19sMWcrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.2.tgz",
+ "integrity": "sha512-7n/PGJOcL2QoptzL42L5xFFfXY5rFxLHnuz1foU+4ruUTG8x2IebGhtwVTpaDN8ShEv2UZObBlT1rrXTba15Zw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.2.tgz",
+ "integrity": "sha512-ZUQVCfRJ9wimuxkStRSlLwqX4TEDmv6/J+E6FicGkQ6ssLMWoKDy0cAo93HiWt/TWEee5vFhFaSQYzCuBEGO6A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.2.tgz",
+ "integrity": "sha512-GZh3pYBmfnpQ+JIg+TqLuz+pM+Mjsk5VOzi8nwKn/m+GvQBsxD5ectRtxuWUxMGNG8h0lMy4SnHRqdK3/iJl7A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.2.tgz",
+ "integrity": "sha512-5av6VYZZeneiYIodwzGMlnyVakpuYZryGzFIbgu1XP8wVylZxduEzup4eP8atiMDFmIm+s4wn8GySJmYqeJC0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.2.tgz",
+ "integrity": "sha512-1nO/UfdCLuT/uE/7oB3EZgTeZDCIa6nL72cFEpdegnqpJVNDI6Qb8U4g/4lfVPkmHq2lvxQ0L+n+JdgaZLhrRA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.2.tgz",
+ "integrity": "sha512-Ksfrb0Tx310kr+TLiUOvB/I80lyZ3lSOp6cM18zmNRT/92NB4mW8oX2Jo7K4eVEI2JWyaQUAFubDSha2Q+439A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.2.tgz",
+ "integrity": "sha512-IzUb5RlMUY0r1A9IuJrQ7Tbts1wWb73/zXVXT8VhewbHGoNlBKE0qUhKMED6Tv4wDF+pmbtUJmKXDthytAvLmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.2.tgz",
+ "integrity": "sha512-kCATEzuY2LP9AlbU2uScjcVhgnCAkRdu62vbce17Ro5kxEHxYWcugkveyBRS3AqZGtwAKYbMAuNloer9LS/hpw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.2.tgz",
+ "integrity": "sha512-iJaHeYCF4jTn7OEKSa3KRiuVFIVYts8jYjNmCdyz1u5g8HRyTDISD76r8+ljEOgm36oviRQvcXaw6LFp1m0yyA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@swc/types": {
+ "version": "0.1.25",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz",
+ "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/counter": "^0.1.3"
+ }
+ },
+ "node_modules/@tailwindcss/typography": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
+ "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "6.0.10"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
+ }
+ },
+ "node_modules/@tanstack/query-core": {
+ "version": "5.90.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.9.tgz",
+ "integrity": "sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-query": {
+ "version": "5.90.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.9.tgz",
+ "integrity": "sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/query-core": "5.90.9"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19"
+ }
+ },
+ "node_modules/@tweenjs/tween.js": {
+ "version": "25.0.0",
+ "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz",
+ "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
+ "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/d3-axis": "*",
+ "@types/d3-brush": "*",
+ "@types/d3-chord": "*",
+ "@types/d3-color": "*",
+ "@types/d3-contour": "*",
+ "@types/d3-delaunay": "*",
+ "@types/d3-dispatch": "*",
+ "@types/d3-drag": "*",
+ "@types/d3-dsv": "*",
+ "@types/d3-ease": "*",
+ "@types/d3-fetch": "*",
+ "@types/d3-force": "*",
+ "@types/d3-format": "*",
+ "@types/d3-geo": "*",
+ "@types/d3-hierarchy": "*",
+ "@types/d3-interpolate": "*",
+ "@types/d3-path": "*",
+ "@types/d3-polygon": "*",
+ "@types/d3-quadtree": "*",
+ "@types/d3-random": "*",
+ "@types/d3-scale": "*",
+ "@types/d3-scale-chromatic": "*",
+ "@types/d3-selection": "*",
+ "@types/d3-shape": "*",
+ "@types/d3-time": "*",
+ "@types/d3-time-format": "*",
+ "@types/d3-timer": "*",
+ "@types/d3-transition": "*",
+ "@types/d3-zoom": "*"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-axis": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz",
+ "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-brush": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz",
+ "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-chord": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz",
+ "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-contour": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz",
+ "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-dispatch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz",
+ "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-drag": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
+ "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-dsv": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz",
+ "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-fetch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz",
+ "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-dsv": "*"
+ }
+ },
+ "node_modules/@types/d3-force": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
+ "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-format": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz",
+ "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-geo": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz",
+ "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-hierarchy": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz",
+ "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-polygon": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz",
+ "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-quadtree": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz",
+ "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-random": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz",
+ "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-selection": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
+ "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
+ "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-time-format": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz",
+ "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-transition": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
+ "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-zoom": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
+ "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-interpolate": "*",
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/geojson": {
+ "version": "7946.0.16",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
+ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.19.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
+ "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.26",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
+ "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz",
+ "integrity": "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.46.4",
+ "@typescript-eslint/type-utils": "8.46.4",
+ "@typescript-eslint/utils": "8.46.4",
+ "@typescript-eslint/visitor-keys": "8.46.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.46.4",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz",
+ "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.46.4",
+ "@typescript-eslint/types": "8.46.4",
+ "@typescript-eslint/typescript-estree": "8.46.4",
+ "@typescript-eslint/visitor-keys": "8.46.4",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz",
+ "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.46.4",
+ "@typescript-eslint/types": "^8.46.4",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz",
+ "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.46.4",
+ "@typescript-eslint/visitor-keys": "8.46.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz",
+ "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz",
+ "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.46.4",
+ "@typescript-eslint/typescript-estree": "8.46.4",
+ "@typescript-eslint/utils": "8.46.4",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz",
+ "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz",
+ "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.46.4",
+ "@typescript-eslint/tsconfig-utils": "8.46.4",
+ "@typescript-eslint/types": "8.46.4",
+ "@typescript-eslint/visitor-keys": "8.46.4",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz",
+ "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.46.4",
+ "@typescript-eslint/types": "8.46.4",
+ "@typescript-eslint/typescript-estree": "8.46.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz",
+ "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.46.4",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz",
+ "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "1.0.0-beta.27",
+ "@swc/core": "^1.12.11"
+ },
+ "peerDependencies": {
+ "vite": "^4 || ^5 || ^6 || ^7"
+ }
+ },
+ "node_modules/accessor-fn": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
+ "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.22",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz",
+ "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==",
+ "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.27.0",
+ "caniuse-lite": "^1.0.30001754",
+ "fraction.js": "^5.3.4",
+ "normalize-range": "^0.1.2",
+ "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/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.28",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.28.tgz",
+ "integrity": "sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/bezier-js": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz",
+ "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==",
+ "license": "MIT",
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
+ "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
+ "dev": true,
+ "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.8.25",
+ "caniuse-lite": "^1.0.30001754",
+ "electron-to-chromium": "^1.5.249",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.1.4"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/callsites": {
"version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001755",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz",
+ "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==",
+ "dev": true,
+ "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/canvas-color-tracker": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz",
+ "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "tinycolor2": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cmdk": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
+ "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "^1.1.1",
+ "@radix-ui/react-dialog": "^1.1.6",
+ "@radix-ui/react-id": "^1.1.0",
+ "@radix-ui/react-primitive": "^2.0.2"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.2.tgz",
+ "integrity": "sha512-D80T+tiqkd/8B0xNlbstWDG4x6aqVfO52+OlSUNIdkTvmNw0uQpJLeos2J/2XvpyidAFuTPmpad+tUxLndwj6g==",
+ "license": "MIT"
+ },
+ "node_modules/d3": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
+ "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "3",
+ "d3-axis": "3",
+ "d3-brush": "3",
+ "d3-chord": "3",
+ "d3-color": "3",
+ "d3-contour": "4",
+ "d3-delaunay": "6",
+ "d3-dispatch": "3",
+ "d3-drag": "3",
+ "d3-dsv": "3",
+ "d3-ease": "3",
+ "d3-fetch": "3",
+ "d3-force": "3",
+ "d3-format": "3",
+ "d3-geo": "3",
+ "d3-hierarchy": "3",
+ "d3-interpolate": "3",
+ "d3-path": "3",
+ "d3-polygon": "3",
+ "d3-quadtree": "3",
+ "d3-random": "3",
+ "d3-scale": "4",
+ "d3-scale-chromatic": "3",
+ "d3-selection": "3",
+ "d3-shape": "3",
+ "d3-time": "3",
+ "d3-time-format": "4",
+ "d3-timer": "3",
+ "d3-transition": "3",
+ "d3-zoom": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-axis": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
+ "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-binarytree": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz",
+ "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==",
+ "license": "MIT"
+ },
+ "node_modules/d3-brush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
+ "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "3",
+ "d3-transition": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-chord": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
+ "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-contour": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
+ "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "license": "ISC",
+ "dependencies": {
+ "delaunator": "5"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-drag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
+ "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-selection": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "license": "ISC",
+ "dependencies": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json.js",
+ "csv2tsv": "bin/dsv2dsv.js",
+ "dsv2dsv": "bin/dsv2dsv.js",
+ "dsv2json": "bin/dsv2json.js",
+ "json2csv": "bin/json2dsv.js",
+ "json2dsv": "bin/json2dsv.js",
+ "json2tsv": "bin/json2dsv.js",
+ "tsv2csv": "bin/dsv2dsv.js",
+ "tsv2json": "bin/dsv2json.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-fetch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
+ "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dsv": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force-3d": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz",
+ "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==",
+ "license": "MIT",
+ "dependencies": {
+ "d3-binarytree": "1",
+ "d3-dispatch": "1 - 3",
+ "d3-octree": "1",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-geo": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
+ "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.5.0 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-octree": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz",
+ "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==",
+ "license": "MIT"
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-polygon": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
+ "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-random": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
+ "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-interpolate": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-selection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
+ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-transition": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
+ "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-dispatch": "1 - 3",
+ "d3-ease": "1 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "d3-selection": "2 - 3"
+ }
+ },
+ "node_modules/d3-zoom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
+ "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-transition": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+ "license": "MIT"
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/delaunator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
+ "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
+ "license": "ISC",
+ "dependencies": {
+ "robust-predicates": "^3.0.2"
+ }
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "license": "MIT"
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.254",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.254.tgz",
+ "integrity": "sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/embla-carousel": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz",
+ "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==",
+ "license": "MIT"
+ },
+ "node_modules/embla-carousel-react": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz",
+ "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==",
+ "license": "MIT",
+ "dependencies": {
+ "embla-carousel": "8.6.0",
+ "embla-carousel-reactive-utils": "8.6.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/embla-carousel-reactive-utils": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz",
+ "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "embla-carousel": "8.6.0"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
+ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.1",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz",
+ "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-equals": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.3.tgz",
+ "integrity": "sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/float-tooltip": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz",
+ "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==",
+ "license": "MIT",
+ "dependencies": {
+ "d3-selection": "2 - 3",
+ "kapsule": "^1.16",
+ "preact": "10"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/force-graph": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.0.tgz",
+ "integrity": "sha512-aTnihCmiMA0ItLJLCbrQYS9mzriopW24goFPgUnKAAmAlPogTSmFWqoBPMXzIfPb7bs04Hur5zEI4WYgLW3Sig==",
+ "license": "MIT",
+ "dependencies": {
+ "@tweenjs/tween.js": "18 - 25",
+ "accessor-fn": "1",
+ "bezier-js": "3 - 6",
+ "canvas-color-tracker": "^1.3",
+ "d3-array": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-force-3d": "2 - 3",
+ "d3-scale": "1 - 4",
+ "d3-scale-chromatic": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-zoom": "2 - 3",
+ "float-tooltip": "^1.7",
+ "index-array-by": "1",
+ "kapsule": "^1.16",
+ "lodash-es": "4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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/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/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/index-array-by": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz",
+ "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/input-otp": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz",
+ "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
}
},
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
+ "@isaacs/cliui": "^8.0.2"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
}
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/jerrypick": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz",
+ "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "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/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
+ "argparse": "^2.0.1"
},
- "engines": {
- "node": ">=7.0.0"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true,
"license": "MIT"
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true,
"license": "MIT"
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/kapsule": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz",
+ "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==",
"license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "lodash-es": "4"
},
"engines": {
- "node": ">= 8"
+ "node": ">=12"
}
},
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "json-buffer": "3.0.1"
}
},
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/esbuild": {
- "version": "0.25.10",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
- "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==",
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
- "hasInstallScript": true,
"license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
},
"engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.10",
- "@esbuild/android-arm": "0.25.10",
- "@esbuild/android-arm64": "0.25.10",
- "@esbuild/android-x64": "0.25.10",
- "@esbuild/darwin-arm64": "0.25.10",
- "@esbuild/darwin-x64": "0.25.10",
- "@esbuild/freebsd-arm64": "0.25.10",
- "@esbuild/freebsd-x64": "0.25.10",
- "@esbuild/linux-arm": "0.25.10",
- "@esbuild/linux-arm64": "0.25.10",
- "@esbuild/linux-ia32": "0.25.10",
- "@esbuild/linux-loong64": "0.25.10",
- "@esbuild/linux-mips64el": "0.25.10",
- "@esbuild/linux-ppc64": "0.25.10",
- "@esbuild/linux-riscv64": "0.25.10",
- "@esbuild/linux-s390x": "0.25.10",
- "@esbuild/linux-x64": "0.25.10",
- "@esbuild/netbsd-arm64": "0.25.10",
- "@esbuild/netbsd-x64": "0.25.10",
- "@esbuild/openbsd-arm64": "0.25.10",
- "@esbuild/openbsd-x64": "0.25.10",
- "@esbuild/openharmony-arm64": "0.25.10",
- "@esbuild/sunos-x64": "0.25.10",
- "@esbuild/win32-arm64": "0.25.10",
- "@esbuild/win32-ia32": "0.25.10",
- "@esbuild/win32-x64": "0.25.10"
+ "node": ">= 0.8.0"
}
},
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=14"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/antonk52"
}
},
- "node_modules/eslint": {
- "version": "9.36.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz",
- "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.0",
- "@eslint/config-helpers": "^0.3.1",
- "@eslint/core": "^0.15.2",
- "@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.36.0",
- "@eslint/plugin-kit": "^0.3.5",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "@types/json-schema": "^7.0.15",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.4.0",
- "eslint-visitor-keys": "^4.2.1",
- "espree": "^10.4.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
+ "p-locate": "^5.0.0"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": ">=10"
},
"funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/eslint-scope": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
- "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
- "license": "BSD-2-Clause",
+ "license": "MIT"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
"dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
+ "js-tokens": "^3.0.0 || ^4.0.0"
},
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "bin": {
+ "loose-envify": "cli.js"
}
},
- "node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
},
- "node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "node_modules/lucide-react": {
+ "version": "0.462.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.462.0.tgz",
+ "integrity": "sha512-NTL7EbAao9IFtuSivSZgrAh4fZd09Lr+6MTkqIxuHaH2nnYiYIzXPo06cOxHg9wKLdj6LL8TByG4qpePqwgx/g==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
}
},
- "node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "license": "MIT",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": ">= 8"
}
},
- "node_modules/eslint/node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
"engines": {
- "node": ">= 4"
+ "node": ">=8.6"
}
},
- "node_modules/eslint/node_modules/minimatch": {
+ "node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
@@ -1362,179 +5629,154 @@
"node": "*"
}
},
- "node_modules/espree": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
- "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.15.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.1"
- },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
+ "node": ">=16 || 14 >=14.17"
}
},
- "node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "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==",
"dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
+ "license": "MIT"
},
- "node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
- "dev": true,
- "license": "BSD-3-Clause",
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "license": "MIT",
"dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
}
},
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "estraverse": "^5.2.0"
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
},
"engines": {
- "node": ">=4.0"
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
- }
+ "license": "MIT"
},
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/next-themes": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz",
+ "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17 || ^18",
+ "react-dom": "^16.8 || ^17 || ^18"
}
},
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
"dev": true,
"license": "MIT"
},
- "node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
"engines": {
- "node": ">=8.6.0"
+ "node": ">=0.10.0"
}
},
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 6"
+ "node": ">=0.10.0"
}
},
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true,
- "license": "MIT"
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "node_modules/fastq": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
- "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
}
},
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
},
"engines": {
- "node": ">=16.0.0"
+ "node": ">= 0.8.0"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "to-regex-range": "^5.0.1"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/find-up": {
+ "node_modules/p-locate": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
+ "p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
@@ -1543,419 +5785,647 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
+ "callsites": "^3.0.0"
},
"engines": {
- "node": ">=16"
+ "node": ">=6"
}
},
- "node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
- "license": "ISC"
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "is-glob": "^4.0.3"
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
- "dev": true,
+ "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": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=8.6"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true,
- "license": "MIT"
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">= 6"
}
},
- "node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "dev": true,
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "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.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
"engines": {
- "node": ">= 4"
+ "node": "^10 || ^12 || >=14"
}
},
- "node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
- "dev": true,
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"license": "MIT",
"dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
},
"engines": {
- "node": ">=6"
+ "node": ">=14.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "postcss": "^8.0.0"
}
},
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
+ "node_modules/postcss-js": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+ "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
"engines": {
- "node": ">=0.8.19"
+ "node": "^12 || ^14 || >= 16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
}
},
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
+ "node_modules/postcss-load-config": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+ "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.1.1"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "jiti": ">=1.21.0",
+ "postcss": ">=8.0.9",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
}
},
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "is-extglob": "^2.1.1"
+ "postcss-selector-parser": "^6.1.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
}
},
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
+ "node_modules/postcss-nested/node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
"engines": {
- "node": ">=0.12.0"
+ "node": ">=4"
}
},
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "argparse": "^2.0.1"
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
},
- "bin": {
- "js-yaml": "bin/js-yaml.js"
+ "engines": {
+ "node": ">=4"
}
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
+ "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==",
"license": "MIT"
},
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
+ "node_modules/preact": {
+ "version": "10.27.2",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz",
+ "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
},
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
},
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT",
"dependencies": {
- "json-buffer": "3.0.1"
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
}
},
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=6"
}
},
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "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/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"dependencies": {
- "p-locate": "^5.0.0"
+ "loose-envify": "^1.1.0"
},
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=0.10.0"
}
},
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
+ "node_modules/react-day-picker": {
+ "version": "8.10.1",
+ "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
+ "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
"license": "MIT",
- "engines": {
- "node": ">= 8"
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/sponsors/gpbl"
+ },
+ "peerDependencies": {
+ "date-fns": "^2.28.0 || ^3.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
},
- "engines": {
- "node": ">=8.6"
+ "peerDependencies": {
+ "react": "^18.3.1"
}
},
- "node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
+ "node_modules/react-force-graph-2d": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.29.0.tgz",
+ "integrity": "sha512-Xv5IIk+hsZmB3F2ibja/t6j/b0/1T9dtFOQacTUoLpgzRHrO6wPu1GtQ2LfRqI/imgtaapnXUgQaE8g8enPo5w==",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "force-graph": "^1.51",
+ "prop-types": "15",
+ "react-kapsule": "^2.5"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=12"
},
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "peerDependencies": {
+ "react": "*"
}
},
- "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==",
- "dev": true,
- "license": "MIT"
+ "node_modules/react-hook-form": {
+ "version": "7.66.0",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.66.0.tgz",
+ "integrity": "sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
},
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
- "node_modules/optionator": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
- "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
- "dev": true,
+ "node_modules/react-kapsule": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.7.tgz",
+ "integrity": "sha512-kifAF4ZPD77qZKc4CKLmozq6GY1sBzPEJTIJb0wWFK6HsePJatK3jXplZn2eeAt3x67CDozgi7/rO8fNQ/AL7A==",
"license": "MIT",
"dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.5"
+ "jerrypick": "^1.1.1"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
}
},
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
"license": "MIT",
"dependencies": {
- "yocto-queue": "^0.1.0"
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
},
"engines": {
"node": ">=10"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
"license": "MIT",
"dependencies": {
- "p-limit": "^3.0.2"
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
+ "node_modules/react-resizable-panels": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.9.tgz",
+ "integrity": "sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.30.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.2.tgz",
+ "integrity": "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==",
"license": "MIT",
"dependencies": {
- "callsites": "^3.0.0"
+ "@remix-run/router": "1.23.1"
},
"engines": {
- "node": ">=6"
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
}
},
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
+ "node_modules/react-router-dom": {
+ "version": "6.30.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.2.tgz",
+ "integrity": "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==",
"license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.1",
+ "react-router": "6.30.2"
+ },
"engines": {
- "node": ">=8"
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
}
},
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
+ "node_modules/react-smooth": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
+ "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "dependencies": {
+ "fast-equals": "^5.0.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
"license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
+ },
"engines": {
- "node": ">=8.6"
+ "node": ">=10"
},
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=8.10.0"
}
},
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
+ "node_modules/recharts": {
+ "version": "2.15.4",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz",
+ "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==",
"license": "MIT",
+ "dependencies": {
+ "clsx": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.21",
+ "react-is": "^18.3.1",
+ "react-smooth": "^4.0.4",
+ "recharts-scale": "^0.4.4",
+ "tiny-invariant": "^1.3.1",
+ "victory-vendor": "^36.6.8"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
+ "node_modules/recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "license": "MIT",
+ "dependencies": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
+ "node_modules/recharts/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"license": "MIT"
},
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -1970,18 +6440,64 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
- "dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
+ "node_modules/robust-predicates": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
+ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==",
+ "license": "Unlicense"
+ },
+ "node_modules/rollup": {
+ "version": "4.53.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz",
+ "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.53.2",
+ "@rollup/rollup-android-arm64": "4.53.2",
+ "@rollup/rollup-darwin-arm64": "4.53.2",
+ "@rollup/rollup-darwin-x64": "4.53.2",
+ "@rollup/rollup-freebsd-arm64": "4.53.2",
+ "@rollup/rollup-freebsd-x64": "4.53.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.53.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.53.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.53.2",
+ "@rollup/rollup-linux-arm64-musl": "4.53.2",
+ "@rollup/rollup-linux-loong64-gnu": "4.53.2",
+ "@rollup/rollup-linux-ppc64-gnu": "4.53.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.53.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.53.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.53.2",
+ "@rollup/rollup-linux-x64-gnu": "4.53.2",
+ "@rollup/rollup-linux-x64-musl": "4.53.2",
+ "@rollup/rollup-openharmony-arm64": "4.53.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.53.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.53.2",
+ "@rollup/rollup-win32-x64-gnu": "4.53.2",
+ "@rollup/rollup-win32-x64-msvc": "4.53.2",
+ "fsevents": "~2.3.2"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -2001,37 +6517,183 @@
"queue-microtask": "^1.2.2"
}
},
- "node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "node_modules/rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "license": "BSD-3-Clause"
+ },
+ "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.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sonner": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.7.4.tgz",
+ "integrity": "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ }
+ },
+ "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/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
- "shebang-regex": "^3.0.0"
+ "ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"license": "MIT",
"engines": {
"node": ">=8"
@@ -2050,6 +6712,37 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -2063,11 +6756,124 @@
"node": ">=8"
}
},
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
+ "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.18",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz",
+ "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.7",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss-animate": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT"
+ },
+ "node_modules/tinycolor2": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+ "license": "MIT"
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -2089,6 +6895,18 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "license": "Apache-2.0"
+ },
+ "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/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -2103,9 +6921,9 @@
}
},
"node_modules/typescript": {
- "version": "5.9.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
- "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -2116,6 +6934,68 @@
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.46.4",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.4.tgz",
+ "integrity": "sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.46.4",
+ "@typescript-eslint/parser": "8.46.4",
+ "@typescript-eslint/typescript-estree": "8.46.4",
+ "@typescript-eslint/utils": "8.46.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
+ "dev": true,
+ "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/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -2126,11 +7006,163 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+ "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/vaul": {
+ "version": "0.9.9",
+ "resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.9.tgz",
+ "integrity": "sha512-7afKg48srluhZwIkaU+lgGtFCUsYBSGOl8vcc8N/M3YQlZFlynHD15AE+pwrYdc826o7nrIND4lL9Y6b9WWZZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-dialog": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ }
+ },
+ "node_modules/victory-vendor": {
+ "version": "36.9.2",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+ "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+ "license": "MIT AND ISC",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.21",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.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",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -2152,6 +7184,94 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -2164,6 +7284,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/app/package.json b/app/package.json
index 5ae5c604..fd9f43de 100644
--- a/app/package.json
+++ b/app/package.json
@@ -1,18 +1,88 @@
{
"name": "queryweaver-app",
- "version": "0.0.1",
"private": true,
+ "version": "0.0.1",
+ "type": "module",
"scripts": {
- "build": "NODE_ENV=production esbuild ts/app.ts --bundle --outfile=./public/js/app.js --platform=browser --minify",
- "build:dev": "NODE_ENV=development esbuild ts/app.ts --bundle --outfile=./public/js/app.js --sourcemap --platform=browser",
- "watch": "esbuild ts/app.ts --bundle --outfile=./public/js/app.js --sourcemap --platform=browser --watch",
- "lint": "eslint --ext .ts ./ts --max-warnings=0 || true"
+ "dev": "vite",
+ "build": "vite build",
+ "build:dev": "vite build --mode development",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@hookform/resolvers": "^3.10.0",
+ "@radix-ui/react-accordion": "^1.2.11",
+ "@radix-ui/react-alert-dialog": "^1.1.14",
+ "@radix-ui/react-aspect-ratio": "^1.1.7",
+ "@radix-ui/react-avatar": "^1.1.10",
+ "@radix-ui/react-checkbox": "^1.3.2",
+ "@radix-ui/react-collapsible": "^1.1.11",
+ "@radix-ui/react-context-menu": "^2.2.15",
+ "@radix-ui/react-dialog": "^1.1.14",
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
+ "@radix-ui/react-hover-card": "^1.1.14",
+ "@radix-ui/react-label": "^2.1.7",
+ "@radix-ui/react-menubar": "^1.1.15",
+ "@radix-ui/react-navigation-menu": "^1.2.13",
+ "@radix-ui/react-popover": "^1.1.14",
+ "@radix-ui/react-progress": "^1.1.7",
+ "@radix-ui/react-radio-group": "^1.3.7",
+ "@radix-ui/react-scroll-area": "^1.2.9",
+ "@radix-ui/react-select": "^2.2.5",
+ "@radix-ui/react-separator": "^1.1.7",
+ "@radix-ui/react-slider": "^1.3.5",
+ "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-switch": "^1.2.5",
+ "@radix-ui/react-tabs": "^1.1.12",
+ "@radix-ui/react-toast": "^1.2.14",
+ "@radix-ui/react-toggle": "^1.1.9",
+ "@radix-ui/react-toggle-group": "^1.1.10",
+ "@radix-ui/react-tooltip": "^1.2.7",
+ "@tanstack/react-query": "^5.83.0",
+ "@types/d3": "^7.4.3",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "cmdk": "^1.1.1",
+ "d3": "^7.9.0",
+ "date-fns": "^3.6.0",
+ "embla-carousel-react": "^8.6.0",
+ "input-otp": "^1.4.2",
+ "lucide-react": "^0.462.0",
+ "next-themes": "^0.3.0",
+ "react": "^18.3.1",
+ "react-day-picker": "^8.10.1",
+ "react-dom": "^18.3.1",
+ "react-force-graph-2d": "^1.29.0",
+ "react-hook-form": "^7.61.1",
+ "react-resizable-panels": "^2.1.9",
+ "react-router-dom": "^6.30.1",
+ "recharts": "^2.15.4",
+ "sonner": "^1.7.4",
+ "tailwind-merge": "^2.6.0",
+ "tailwindcss-animate": "^1.0.7",
+ "vaul": "^0.9.9",
+ "zod": "^3.25.76"
},
"devDependencies": {
- "esbuild": "^0.25.10",
- "typescript": "^5.9.2",
- "eslint": "^9.36.0",
- "@typescript-eslint/parser": "^8.44.0",
- "@typescript-eslint/eslint-plugin": "^8.44.0"
+ "@eslint/js": "^9.32.0",
+ "@tailwindcss/typography": "^0.5.16",
+ "@types/node": "^22.16.5",
+ "@types/react": "^18.3.23",
+ "@types/react-dom": "^18.3.7",
+ "@vitejs/plugin-react-swc": "^3.11.0",
+ "autoprefixer": "^10.4.21",
+ "eslint": "^9.32.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^15.15.0",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.38.0",
+ "vite": "^5.4.19"
+ },
+ "overrides": {
+ "glob": "^10.5.0"
}
-}
+}
\ No newline at end of file
diff --git a/app/postcss.config.js b/app/postcss.config.js
new file mode 100644
index 00000000..2aa7205d
--- /dev/null
+++ b/app/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/app/public/css/animations.css b/app/public/css/animations.css
deleted file mode 100644
index da6771a6..00000000
--- a/app/public/css/animations.css
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Animations and Keyframes */
-
-@keyframes shadow-fade {
- 0% {
- box-shadow: 0 0 8px 1px var(--falkor-primary)
- }
-
- 50% {
- box-shadow: 0 0 12px 2px var(--falkor-primary)
- }
-
- 100% {
- box-shadow: 0 0 8px 1px var(--falkor-primary)
- }
-}
-
-@keyframes typing {
- 0% {
- content: ".";
- }
-
- 50% {
- content: "..";
- }
-
- 100% {
- content: "...";
- }
-}
-
-@keyframes pulse {
- 0%,
- 100% {
- opacity: 0.4;
- }
-
- 50% {
- opacity: 0.8;
- }
-}
-
-@keyframes spin {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
diff --git a/app/public/css/base.css b/app/public/css/base.css
deleted file mode 100644
index af715d04..00000000
--- a/app/public/css/base.css
+++ /dev/null
@@ -1,99 +0,0 @@
-/* CSS Reset and Base Styles */
-
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
-}
-
-@font-face {
- font-family: 'Fira Code';
- src: url('fonts/fira_code.ttf');
-}
-
-@font-face {
- font-family: 'Inter';
- src: url('fonts/inter.ttf');
-}
-
-* {
- font-family: 'Inter' !important;
-}
-
-.query-text {
- font-family: 'Fira Code' !important;
-}
-
-body {
- background-color: var(--falkor-secondary);
- display: flex;
- flex-direction: column;
- color: var(--text-primary);
-}
-
-/* Scrollbar Styles */
-::-webkit-scrollbar {
- width: 20px;
- height: 20px;
-}
-
-::-webkit-scrollbar-corner {
- background-color: transparent;
-}
-
-::-webkit-scrollbar-thumb {
- background-color: #d6dee1;
- border-radius: 20px;
- border: 6px solid transparent;
- background-clip: content-box;
-}
-
-::-webkit-scrollbar-thumb:hover {
- background-color: #a8bbbf;
-}
-
-/* Powered by FalkorDB footer */
-#powered-by-falkordb {
- text-align: center;
- padding: 0.5em 0;
- font-size: 1em;
- background: var(--color-bg-secondary, #222);
- color: var(--color-text-secondary, #fff);
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0; /* avoid 100vw-induced horizontal scrollbars */
- z-index: 1000;
-}
-#powered-by-falkordb a {
- color: inherit;
- text-decoration: underline;
-}
-
-#powered-by-falkordb img {
- height:1.5em;
- vertical-align:middle;
-}
-
-@media (max-width: 600px) {
- #powered-by-falkordb {
- font-size: 0.95em;
- padding: 0.4em 0;
- height: 2.2em;
- }
- body {
- padding-bottom: 2.2em; /* Prevent content from being hidden behind the fixed footer */
- overflow: auto;
- }
-}
-
-html, body {
- height: 100%;
- min-height: 100dvh;
- box-sizing: border-box;
-}
-
-#container, .chat-container {
- min-height: calc(100dvh - 2.2em);
- box-sizing: border-box;
-}
diff --git a/app/public/css/buttons.css b/app/public/css/buttons.css
deleted file mode 100644
index 38cae150..00000000
--- a/app/public/css/buttons.css
+++ /dev/null
@@ -1,498 +0,0 @@
-/* Button Styles and Interactive Elements */
-
-.input-button {
- background: var(--falkor-primary);
- color: var(--text-primary);
- cursor: pointer;
- transition: all 0.2s ease;
- border: none;
- width: 48px;
- height: 48px;
- overflow: hidden;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 6px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
-}
-
-.input-button:disabled {
- opacity: 0.5;
- cursor: not-allowed;
-}
-
-.input-button img {
- filter: var(--icon-filter) brightness(0.8) saturate(0.3);
- width: 100%;
- height: 100%;
- object-fit: contain;
-}
-
-.input-button:hover {
- box-shadow: 0 4px 12px rgba(0,0,0,0.25);
- background: var(--falkor-accent);
- transform: translateY(-1px);
-}
-
-.action-button {
- z-index: 100;
- width: 48px;
- height: 48px;
- border: none;
- border-radius: 6px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
- cursor: pointer;
- transition: all 0.2s ease;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0;
- position: relative;
-}
-
-.action-button:disabled {
- opacity: 0.5;
- cursor: not-allowed;
-}
-
-.action-button:hover {
- box-shadow: 0 4px 12px rgba(0,0,0,0.25);
- background: var(--falkor-primary);
- transform: translateY(-1px);
-}
-
-.pg-connect-btn {
- margin-left: 12px;
- padding: 0.4em 0.8em;
- background: #f5f5f5;
- border: 1px solid #ccc;
- border-radius: 6px;
- font-size: 1em;
- color: #333;
- cursor: pointer;
- transition: background 0.2s, border 0.2s;
-}
-
-.pg-connect-btn:hover {
- background: #eaeaea;
- border-color: #888;
-}
-
-.logout-btn {
- position: fixed;
- top: 20px;
- right: 30px;
- z-index: 2000;
- padding: 0.5em 1.2em;
- background: #e74c3c;
- color: #fff;
- border-radius: 6px;
- text-decoration: none;
- font-weight: bold;
- box-shadow: 0 2px 8px rgba(0,0,0,0.08);
- transition: background 0.2s;
-}
-
-.logout-btn:hover {
- background: #c0392b;
-}
-
-/* User Profile Button Styles */
-.user-profile-btn {
- position: fixed;
- top: 20px;
- right: 30px;
- z-index: 2000;
- width: 48px;
- height: 48px;
- border: none;
- border-radius: 6px;
- background: #fff;
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
- cursor: pointer;
- transition: all 0.2s ease;
- padding: 2px;
-}
-
-.user-profile-btn:hover {
- box-shadow: 0 4px 12px rgba(0,0,0,0.25);
- transform: translateY(-1px);
-}
-
-.user-profile-img {
- width: 100%;
- height: 100%;
- border-radius: 6px;
- object-fit: cover;
- font-weight: 500;
- font-size: 22px;
-}
-
-#user-profile-logout {
- background: #D32F2F;
- color: #fff;
-}
-
-#user-profile-logout:hover {
- background: #B71C1C;
-}
-
-.user-profile-action {
- cursor: pointer;
- border-radius: 4px;
- transition: all 0.2s ease;
- width: 100%;
- padding: 10px;
- font-weight: bold;
- border: none;
- color: var(--text-primary);
-}
-
-#api-tokens-btn {
- background: var(--falkor-quaternary);
-}
-
-#api-tokens-btn:hover {
- background: var(--bg-tertiary);
-}
-
-
-/* Theme Toggle Button Styles */
-#theme-toggle-btn {
- position: static;
- margin: 0;
-}
-
-/* GitHub Link Button Styles */
-#github-link-btn {
- position: fixed;
- top: 20px;
- right: 90px;
- display: flex;
- align-items: center;
- gap: 4px;
- padding: 8px 12px;
- border-radius: 6px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- text-decoration: none;
- font-size: 14px;
- font-weight: 500;
- border: 1px solid var(--border-color);
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
- transition: all 0.2s ease;
- z-index: 100;
- height: 48px;
- box-sizing: border-box;
-}
-
-#github-link-btn:hover {
- box-shadow: 0 4px 12px rgba(0,0,0,0.25);
- background: var(--falkor-primary);
- transform: translateY(-1px);
- color: var(--text-primary);
-}
-
-.theme-icon {
- width: 20px;
- height: 20px;
- color: var(--text-primary);
- transition: all 0.3s ease;
-}
-
-/* Authentication Buttons */
-.google-login-btn {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 10px;
- margin-top: 1em;
- padding: 0.7em 2em;
- background: #4285F4;
- color: #fff;
- border-radius: 6px;
- font-size: 1.1em;
- text-decoration: none;
- font-weight: 500;
- transition: background 0.2s;
-}
-
-.google-login-btn:hover {
- background: #3367d6;
-}
-
-.google-login-logo {
- height: 20px;
- margin-right: 10px;
- margin-left: 0;
- vertical-align: middle;
- display: inline-block;
-}
-
-.github-login-btn {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 10px;
- padding: 0.7em 2em;
- background: #24292f;
- color: #fff;
- border-radius: 6px;
- font-size: 1.1em;
- text-decoration: none;
- font-weight: 500;
- transition: background 0.2s;
- margin-top: 0.5em;
-}
-
-.github-login-btn:hover {
- background: #171a1d;
-}
-
-.github-login-logo {
- height: 20px;
- margin-right: 10px;
- margin-left: 0;
- vertical-align: middle;
- display: inline-block;
-}
-
-/* Confirmation Buttons */
-.confirm-btn, .cancel-btn {
- padding: 12px 24px;
- border: none;
- border-radius: 6px;
- font-size: 14px;
- font-weight: bold;
- cursor: pointer;
- transition: all 0.3s ease;
- min-width: 140px;
-}
-
-.confirm-btn {
- background: #D32F2F;
- color: white;
- border: 1px solid #D32F2F;
-}
-
-.confirm-btn:hover {
- background: #B71C1C;
- border-color: #B71C1C;
- transform: translateY(-1px);
- box-shadow: 0 2px 8px rgba(211, 47, 47, 0.3);
-}
-
-.cancel-btn {
- background: transparent;
- color: var(--text-primary);
- border: 1px solid var(--border-color);
-}
-
-.cancel-btn:hover {
- background: var(--bg-tertiary);
- border-color: var(--text-secondary);
- transform: translateY(-1px);
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
-}
-
-.confirm-btn:active, .cancel-btn:active {
- transform: translateY(0);
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
-}
-
-.confirm-btn:disabled, .cancel-btn:disabled {
- background: #cccccc;
- color: #888888;
- border-color: #cccccc;
- cursor: not-allowed;
- transform: none;
- box-shadow: none;
-}
-
-.confirm-btn:disabled:hover, .cancel-btn:disabled:hover {
- background: #cccccc;
- color: #888888;
- border-color: #cccccc;
- transform: none;
- box-shadow: none;
-}
-
-/* Left vertical toolbar (activity bar style) */
-/* Left vertical toolbar (activity bar style) */
-#left-toolbar {
- position: fixed;
- top: 0px;
- bottom: 0px;
- width: 48px;
- left: 0px;
- background: var(--bg-tertiary, rgba(255,255,255,0.02));
- /* border-radius: 10px; */
- padding: 6px 6px;
- z-index: 1050;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: flex-start;
- gap: 8px;
- box-shadow: 0 6px 18px rgba(0,0,0,0.25);
- border: 1px solid var(--border-color, rgba(255,255,255,0.03));
- backdrop-filter: blur(6px);
- overflow: hidden;
-}
-
-#left-toolbar-inner {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 10px;
- width: 100%;
-}
-
-.toolbar-button {
- width: 40px;
- height: 40px;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
-}
-
-.toolbar-button svg { color: var(--text-primary); opacity: 0.95; width:18px; height:18px }
-
-.toolbar-button:hover {
- transform: translateY(-4px) scale(1.03);
- background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
-}
-
-#toolbar-buttons {
- display: flex;
- flex-direction: column;
- gap: 8px;
- margin-top: 6px;
- width: 100%;
- align-items: center;
-}
-
-/* Footer: pin to bottom of the toolbar */
-#left-toolbar-inner {
- /* allow the inner area to grow so footer can sit at the bottom */
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 10px;
- width: 100%;
- flex: 1 1 auto;
-}
-
-#left-toolbar-footer {
- margin-top: auto; /* push footer to bottom */
- width: 100%;
- flex-shrink: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 10px 0;
- box-sizing: border-box;
-}
-
-#toolbar-footer-buttons {
- display: flex;
- flex-direction: column;
- gap: 8px;
- width: 100%;
- align-items: center;
- justify-content: center;
-}
-
-.toolbar-footer-button {
- width: 40px;
- height: 40px;
- border-radius: 8px;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-/* Collapsed state: only show the burger button. Remove background/border/shadow so the bar is unobtrusive. */
-#left-toolbar.collapsed {
- /* minimize width to avoid blocking content */
- width: 0px;
- padding: 0;
- transition: width 220ms ease, padding 220ms ease, background 200ms ease;
- background: transparent;
- box-shadow: none;
- border: none;
- align-items: flex-start; /* keep burger at top */
- overflow: visible;
- position: relative; /* allow z-index for inner button */
- pointer-events: none; /* let clicks pass through, but burger will override */
-}
-
-#left-toolbar.collapsed .toolbar-button {
- display: none; /* hide all toolbar buttons */
-}
-
-#left-toolbar.collapsed #burger-toggle-btn {
- display: flex;
- width: 48px;
- height: 48px;
- margin: 6px 0;
- position: absolute;
- top: 6px;
- left: 6px;
- z-index: 9999; /* keep on top so it's always clickable */
- pointer-events: auto;
-}
-
-/* Mobile fallback: without JS, default to only the burger visible on small viewports */
-@media (max-width: 767px) {
- #left-toolbar.collapsed {
- width: 0px;
- padding: 0;
- background: transparent;
- box-shadow: none;
- border: none;
- align-items: flex-start;
- pointer-events: none;
- }
-
- /* When NOT collapsed on mobile, show full toolbar */
- #left-toolbar:not(.collapsed) {
- width: 48px;
- padding: 6px 6px;
- background: var(--bg-tertiary, rgba(255,255,255,0.02));
- box-shadow: 0 6px 18px rgba(0,0,0,0.25);
- border: 1px solid var(--border-color, rgba(255,255,255,0.03));
- backdrop-filter: blur(6px);
- align-items: center;
- pointer-events: auto;
- z-index: 1050;
- }
-
- /* On mobile hide buttons only when explicitly collapsed (so burger can open toolbar) */
- #left-toolbar.collapsed .toolbar-button { display: none; }
- #left-toolbar.collapsed #burger-toggle-btn {
- display: flex;
- width: 48px;
- height: 48px;
- position: absolute;
- top: 6px;
- left: 6px;
- pointer-events: auto;
- }
- /* When not collapsed, show toolbar buttons as normal */
- #left-toolbar:not(.collapsed) .toolbar-button { display: flex; }
- #left-toolbar:not(.collapsed) #burger-toggle-btn {
- display: flex;
- position: relative;
- top: auto;
- left: auto;
- pointer-events: auto;
- }
-}
-
-
-
diff --git a/app/public/css/chat-components.css b/app/public/css/chat-components.css
deleted file mode 100644
index 2759f0d3..00000000
--- a/app/public/css/chat-components.css
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Chat Components Styles */
-
-.chat-header {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 20px;
- background: var(--falkor-secondary);
- color: var(--text-primary);
- padding: 16px 20px;
- text-align: center;
- position: relative;
-}
-
-.chat-header h1 {
- font-weight: 600;
- font-size: 22px;
-}
-
-.chat-messages {
- flex-grow: 1;
- padding: 20px;
- overflow-y: auto;
- display: flex;
- flex-direction: column;
- gap: 15px;
- background-color: var(--falkor-secondary);
-}
-
-@media (max-width: 768px) {
- .chat-messages {
- padding: 2px;
- }
-
- .chat-container {
- padding-right: 10px;
- padding-left: 10px;
- padding-top: 10px;
- padding-bottom: 10px;
- /* Ensure no horizontal overflow */
- max-width: 100dvw;
- overflow-x: hidden;
- box-sizing: border-box;
- /* Ensure content is accessible when toolbar is open */
- transition: margin-left 220ms ease;
- }
-}
-.message-container {
- display: flex;
- flex-direction: row;
- align-items: center;
-}
-
-.user-message-container {
- justify-content: flex-end;
- position: relative;
-}
-
-/* Hide the default "User" text when avatar is present */
-.user-message-container.has-avatar::after {
- display: none;
-}
-
-/* User message avatar styling */
-.user-message-avatar {
- height: 40px;
- width: 40px;
- border-radius: 50%;
- object-fit: cover;
- margin-left: 10px;
- border: 2px solid var(--falkor-quaternary);
- font-weight: 500;
- font-size: 16px;
- justify-content: center;
- align-items: center;
- display: flex;
-}
-
-.bot-message-container,
-.followup-message-container,
-.final-result-message-container {
- justify-content: flex-start;
-}
-
-.user-message-container::after,
-.bot-message-container::before,
-.followup-message-container::before,
-.final-result-message-container::before {
- height: 32px;
- width: 32px;
- content: 'QW';
- color: var(--text-secondary);
- display: flex;
- align-items: center;
- justify-content: center;
- font-weight: 500;
- font-size: 16px;
- margin-right: 10px;
- border-radius: 100%;
- padding: 4px;
-}
-
-.user-message-container::after {
- margin-left: 10px;
- background: var(--falkor-quaternary);
- content: 'User';
-}
-
-.bot-message-container::before {
- background: color-mix(in srgb, var(--falkor-tertiary) 33%, transparent);
-}
-
-.followup-message-container::before {
- background: color-mix(in srgb, var(--falkor-tertiary) 40%, transparent);
- border: 1px solid var(--falkor-tertiary);
-}
-
-.final-result-message-container::before {
- background: color-mix(in srgb, var(--falkor-primary) 40%, transparent);
- border: 1px solid var(--falkor-primary);
-}
-
-.loading-message-container::before {
- content: "...";
- font-size: 32px;
- line-height: 1.2;
- text-align: center;
- animation: typing 1.5s steps(3) infinite;
- padding-bottom: 16px;
- border-radius: 6px;
- color: var(--text-primary);
- background: color-mix(in srgb, var(--falkor-tertiary) 33%, transparent);
-}
-
-.message {
- max-width: 70%;
- padding: 12px 16px;
- border-radius: 6px;
- margin: 5px 0;
- line-height: 1.4;
- color: var(--text-primary);
- word-wrap: break-word;
- overflow-wrap: break-word;
- overflow-x: auto;
-}
-
-/* Styles for formatted text blocks */
-.sql-line, .array-line, .plain-line {
- word-wrap: break-word;
- overflow-wrap: break-word;
- white-space: pre-wrap;
- margin: 2px 0;
-}
-
-.bot-message {
- background: color-mix(in srgb, var(--falkor-tertiary) 33%, transparent);
-}
-
-.user-message {
- background: var(--falkor-quaternary);
- font-weight: 500;
-}
-
-.followup-message {
- background: color-mix(in srgb, var(--falkor-tertiary) 20%, transparent);
- border-left: 3px solid var(--falkor-tertiary);
-}
-
-.final-result-message {
- background: color-mix(in srgb, var(--falkor-primary) 15%, transparent);
- border-left: 3px solid var(--falkor-primary);
-}
-
-.chat-input {
- display: flex;
- padding: 16px 20px;
- background: var(--falkor-secondary);
- gap: 20px;
-}
-
-.input-container {
- position: relative;
- display: flex;
- flex-direction: row;
- align-items: center;
- gap: 5px;
- flex-grow: 1;
- padding: 10px;
- border-radius: 6px;
- box-shadow: 0 0 8px 1px var(--falkor-primary);
- border: 1px solid var(--border-color);
-}
-
-.input-container.loading {
- animation: shadow-fade 1.2s infinite ease-in-out;
-}
-
-#message-input {
- color: var(--text-primary);
- flex-grow: 1;
- background-color: transparent;
- border: none;
- font-size: 18px !important;
- font-weight: 500 !important;
- resize: none;
- min-height: 24px;
- height: 24px;
- max-height: calc(24px * 5);
- overflow-y: auto;
- line-height: 24px;
- scrollbar-width: none;
- -ms-overflow-style: none;
-}
-
-#message-input::-webkit-scrollbar {
- display: none;
-}
-
-#message-input:focus {
- outline: none;
-}
-
-#message-input::placeholder {
- font-size: 18px !important;
- font-weight: 500 !important;
- color: var(--text-primary);
- opacity: 0.7;
-}
-
-#pause-button {
- display: none;
- color: var(--text-primary);
-}
-
-#reset-button {
- position: absolute;
- right: -60px;
- top: 50%;
- transform: translateY(-50%);
-}
-
-#reset-button svg {
- width: 20px;
- height: 20px;
-}
-
-#reset-button:disabled {
- opacity: 0.5;
- cursor: not-allowed;
-}
diff --git a/app/public/css/fonts/fira_code.ttf b/app/public/css/fonts/fira_code.ttf
deleted file mode 100644
index 5655ed51..00000000
Binary files a/app/public/css/fonts/fira_code.ttf and /dev/null differ
diff --git a/app/public/css/fonts/inter.ttf b/app/public/css/fonts/inter.ttf
deleted file mode 100644
index e31b51e3..00000000
Binary files a/app/public/css/fonts/inter.ttf and /dev/null differ
diff --git a/app/public/css/layout.css b/app/public/css/layout.css
deleted file mode 100644
index 21d1c2d7..00000000
--- a/app/public/css/layout.css
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Main Layout Components */
-
-#container {
- height: calc(100% - 40px);
- width: calc(100% - 40px);
- display: flex;
- flex-direction: row;
- position: relative;
- margin-left: 40px;
-}
-
-.logo {
- height: 6rem;
- width: auto;
-}
-
-.chat-container {
- flex: 1 1 0;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- position: relative;
- z-index: 1;
- padding-right: 20%;
- padding-left: 20%;
- padding-top: 20px;
- padding-bottom: 20px;
- transition: margin-left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-.vertical-separator {
- width: 2px;
- height: 80%;
- background-color: var(--text-tertiary);
-}
-
-.horizontal-separator {
- width: 80%;
- height: 2px;
- background-color: var(--text-tertiary);
-}
diff --git a/app/public/css/main.css b/app/public/css/main.css
deleted file mode 100644
index 8c34c5d9..00000000
--- a/app/public/css/main.css
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Main CSS Entry Point - Imports all modular CSS files */
-
-/* CSS Variables and Theme System */
-@import url('variables.css');
-
-/* Base styles and reset */
-@import url('base.css');
-
-/* Layout components */
-@import url('layout.css');
-
-/* Chat-specific components */
-@import url('chat-components.css');
-
-/* Menu and navigation */
-@import url('menu.css');
-
-/* Buttons and interactive elements */
-@import url('buttons.css');
-
-/* Modals and popups */
-@import url('modals.css');
-
-/* Responsive styles */
-@import url('responsive.css');
-
-/* Animations and keyframes */
-@import url('animations.css');
-
-/* Theme-specific overrides */
-@import url('themes.css');
diff --git a/app/public/css/menu.css b/app/public/css/menu.css
deleted file mode 100644
index 462ee805..00000000
--- a/app/public/css/menu.css
+++ /dev/null
@@ -1,538 +0,0 @@
-/* Menu and Navigation Components */
-
-.sidebar-container {
- width: 0;
- min-width: 0;
- max-width: 50ddvw;
- overflow: hidden;
- padding: 20px 0;
- display: flex;
- flex-direction: column;
- gap: 20px;
- background: var(--falkor-quaternary);
- transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s cubic-bezier(0.4, 0, 0.2, 1);
- z-index: 1;
- position: relative;
- visibility: hidden;
- pointer-events: none;
-}
-
-.sidebar-container.open {
- width: 50%;
- padding: 20px;
- visibility: visible;
- pointer-events: auto;
-}
-
-.sidebar-container.resizing {
- transition: none; /* Disable transitions while resizing */
-}
-
-/* Resize handle styles */
-.resize-handle {
- width: 6px;
- background: transparent;
- cursor: col-resize;
- position: relative;
- z-index: 10;
- opacity: 0;
- transition: opacity 0.2s ease, background-color 0.2s ease;
- flex-shrink: 0;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.resize-handle::before {
- content: '';
- width: 3px;
- height: 40px;
- background: var(--falkor-border-primary);
- border-radius: 2px;
- transition: background-color 0.2s ease;
- opacity: 0.6;
-}
-
-.resize-handle:hover::before,
-.resize-handle.resizing::before {
- background: var(--falkor-primary);
- opacity: 1;
-}
-
-.resize-handle:hover,
-.resize-handle.resizing {
- opacity: 1;
-}
-
-/* Show resize handles only when sidebars are open */
-.sidebar-container.open + .resize-handle {
- opacity: 0.7;
-}
-
-.sidebar-container.open + .resize-handle:hover,
-.sidebar-container.open + .resize-handle.resizing {
- opacity: 1;
-}
-
-/* Hide resize handles when sidebars are closed */
-.sidebar-container:not(.open) + .resize-handle {
- opacity: 0;
- pointer-events: none;
- width: 0;
-}
-
-#menu-content {
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 20px;
-}
-
-.menu-item {
- overflow: hidden;
- flex: 1 1 auto;
- width: 100%;
- display: flex;
- flex-direction: column;
- gap: 8px;
-}
-
-#conf-container {
- flex-grow: 0;
- height: fit-content;
- flex-direction: row;
- justify-content: space-between;
- width: 100%;
- gap: 16px;
-}
-
-.menu-value {
- flex: 1 1 0;
- border: 1px solid var(--falkor-border-primary);
- width: 100%;
- background: var(--falkor-secondary);
- padding: 4px;
- border-radius: 6px;
- color: var(--text-primary);
- overflow-y: auto;
-}
-
-#conf-value {
- flex: 0 0 auto;
- overflow: hidden;
- min-height: 0;
- width: fit-content;
- min-width: 50px;
- padding: 8px;
-}
-
-#info-value,
-#amb-value {
- border-color: var(--falkor-border-secondary);
-}
-
-#instructions-textarea {
- resize: none;
-}
-
-#instructions-textarea:focus {
- outline: none;
- border: 1px solid var(--falkor-border-tertiary);
-}
-
-.button-container {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- gap: 10px;
-}
-
-.header-button {
- height: 100%;
- padding: 8px 16px;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- font-size: 14px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- cursor: pointer;
- transition: all 0.2s ease;
-}
-
-.header-button:hover:not(:disabled) {
- background: var(--falkor-primary);
- color: white;
-}
-
-.header-button:disabled {
- background: var(--bg-tertiary);
- color: var(--text-secondary);
- cursor: not-allowed;
- border-color: var(--text-secondary);
-}
-
-#graph-select-refresh {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-#graph-select-refresh.loading svg {
- animation: spin 0.5s linear infinite;
- opacity: 0.5;
-}
-
-#graph-select-refresh svg {
- height: 20px;
- width: 20px;
-}
-
-#query-final-result-table {
- border-collapse: collapse;
-}
-
-#query-final-result-table th,
-#query-final-result-table td {
- padding: 4px 8px;
-}
-
-#query-final-result-table th:not(:first-child),
-#query-final-result-table td:not(:first-child) {
- border-left: 1px solid var(--text-primary);
-}
-
-#query-final-result-table td {
- border-top: 1px solid var(--text-primary);
-}
-
-#schema-graph {
- width: 100%;
- height: 100%;
-}
-
-#schema-content {
- position: relative;
- width: 100%;
- height: 100%;
-}
-
-#schema-controls {
- position: absolute;
- padding: 10px;
- bottom: 0px;
- left: 0px;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- gap: 10px;
- z-index: 10;
- pointer-events: none;
-}
-
-#schema-controls button {
- display: flex;
- align-items: center;
- justify-content: center;
- color: var(--text-primary);
- background-color: transparent;
- pointer-events: auto;
- border: none;
- cursor: pointer;
-}
-
-#graph-select:focus {
- outline: none;
- border-color: var(--falkor-border-primary);
-}
-
-#custom-file-upload {
- height: 100%;
- padding: 8px 12px;
- border-radius: 6px;
- border: 1px solid var(--text-primary);
- font-size: 14px;
- background-color: var(--falkor-secondary);
- color: var(--text-primary);
- transition: border-color 0.2s;
- min-width: 180px;
- appearance: none;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 4px;
-}
-
-#open-pg-modal {
- height: 100%;
- padding: 8px 12px;
- border-radius: 6px;
- border: 1px solid var(--text-primary);
- font-size: 14px;
- background-color: var(--falkor-secondary);
- color: var(--text-primary);
- transition: border-color 0.2s;
- min-width: 180px;
- appearance: none;
- background-position: calc(100% - 20px) center, calc(100% - 15px) center;
- background-size: 5px 5px, 5px 5px;
- background-repeat: no-repeat;
- cursor: pointer;
- display: inline-block;
- margin-bottom: 0;
- margin-right: 0;
- margin-left: 0;
-}
-
-#schema-upload:disabled+label {
- opacity: 0.5;
- cursor: not-allowed;
-}
-
-#custom-file-upload:focus {
- outline: none;
- border-color: var(--falkor-border-primary);
-}
-
-/* Custom Dropdown Styles */
-.header-button {
- position: relative;
- display: inline-block;
- min-width: 140px;
-}
-
-.dropdown-selected {
- height: 100%;
- padding: 8px 12px;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- font-size: 14px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- cursor: pointer;
- transition: all 0.2s ease;
- display: flex;
- align-items: center;
- justify-content: space-between;
- user-select: none;
-}
-
-.dropdown-selected:hover {
- border-color: var(--falkor-primary);
-}
-
-.dropdown-selected.active {
- border-color: var(--falkor-primary);
- box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
-}
-
-.dropdown-text {
- flex: 1;
- display: flex;
- align-items: center;
- gap: 8px;
-}
-
-.dropdown-arrow {
- font-size: 10px;
- transition: transform 0.2s ease;
-}
-
-.dropdown-options {
- position: absolute;
- top: 100%;
- left: 0;
- right: 0;
- background: var(--falkor-secondary);
- border: 1px solid var(--border-color);
- border-radius: 6px;
- border-top: none;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
- z-index: 1000;
- max-height: 200px;
- overflow-y: auto;
- display: none;
-}
-
-/* Show dropdown options when parent has .open */
-.custom-dropdown {
- position: relative;
- display: inline-block;
-}
-
-.custom-dropdown.open .dropdown-options {
- display: block;
-}
-
-.custom-dropdown.open .dropdown-arrow {
- transform: rotate(180deg);
-}
-
-/* Make the database-type dropdown match the input width and add gap */
-#database-type-dropdown {
- display: block;
- /* behave like a block element so width:100% applies */
- width: 100%;
- box-sizing: border-box;
- margin: 0 0 12px 0;
- /* gap between dropdown and input; prevent horizontal centering */
-}
-
-#database-type-dropdown .dropdown-selected {
- width: 100%;
- /* keep flex layout so text and arrow align on one line */
- display: flex;
- align-items: center;
- justify-content: space-between;
-}
-
-/* Match modal input sizing for a consistent look */
-#database-type-dropdown .dropdown-selected {
- padding: 0.6em;
- font-size: 1em;
- border-radius: 6px;
-}
-
-#database-type-dropdown .dropdown-options {
- left: 0;
- right: 0;
- /* ensure options fill the same width */
-}
-
-.dropdown-option {
- padding: 8px 12px;
- cursor: pointer;
- display: flex;
- align-items: center;
- gap: 8px;
- transition: background-color 0.2s ease;
-}
-
-.dropdown-option:hover {
- background: var(--bg-tertiary);
-}
-
-.dropdown-option:first-child {
- border-top-left-radius: 0;
- border-top-right-radius: 0;
-}
-
-.dropdown-option:last-child {
- border-bottom-left-radius: 5px;
- border-bottom-right-radius: 5px;
-}
-
-.db-icon {
- width: 16px;
- height: 16px;
- flex-shrink: 0;
-}
-
-/* Graph custom dropdown (moved from chat_header.j2 inline styles) */
-.graph-header-button {
- position: relative;
- display: inline-block;
- width: 180px;
- margin-left: 8px;
-}
-
-.graph-selected {
- height: 100%;
- padding: 8px 14px;
- border-radius: 6px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- cursor: pointer;
- border: 1px solid var(--border-color);
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- min-width: 160px;
- box-sizing: border-box;
- font-size: 14px;
- gap: 4px;
-}
-
-.graph-options {
- position: absolute;
- top: 100%;
- left: -20%;
- right: -20%;
- background: var(--falkor-secondary);
- border: 1px solid var(--border-color);
- border-radius: 6px;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
- max-height: 260px;
- overflow: auto;
- display: none;
- z-index: 50;
-}
-
-.graph-custom-dropdown {
- height: 100%;
- position: relative;
-}
-
-.dropdown-option {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- padding: 8px 12px;
- gap: 8px;
- color: var(--text-primary);
- cursor: pointer;
-}
-
-.dropdown-option:hover {
- background: var(--bg-tertiary);
-}
-
-.dropdown-option span {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.dropdown-option .delete-btn {
- background: transparent;
- border: none;
- color: #ff6b6b;
- opacity: 0;
- cursor: pointer;
- width: 28px;
- height: 28px;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-left: auto;
-}
-
-.dropdown-option:hover .delete-btn {
- opacity: 1;
-}
-
-.dropdown-option .delete-btn svg {
- width: 16px;
- height: 16px;
-}
-
-.dropdown-option .delete-btn:disabled {
- color: #999;
- cursor: not-allowed;
- opacity: 0;
-}
-
-.dropdown-option:hover .delete-btn:disabled {
- opacity: 1;
-}
-
-.graph-options.open {
- display: block;
-}
\ No newline at end of file
diff --git a/app/public/css/modals.css b/app/public/css/modals.css
deleted file mode 100644
index 64739afb..00000000
--- a/app/public/css/modals.css
+++ /dev/null
@@ -1,642 +0,0 @@
-/* Modal and Popup Components */
-
-#db-modal {
- display: none;
- position: fixed;
- top: 0;
- left: 0;
- width: 100dvw;
- height: 100dvh;
- background: rgba(0,0,0,0.5);
- z-index: 3000;
- align-items: center;
- justify-content: center;
-}
-
-.db-modal-content {
- background: var(--falkor-secondary);
- padding: 2em 5em;
- border-radius: 10px;
- box-shadow: 0 2px 16px rgba(0,0,0,0.2);
- text-align: center;
- min-width: 680px;
-}
-
-.db-modal-title {
- margin-bottom: 1em;
- color: var(--text-primary);
-}
-
-.db-modal-input {
- width: 100%;
- padding: 0.6em;
- font-size: 1em;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- margin: 0 0 12px 0; /* consistent gap under elements */
- color: var(--text-primary);
- background: var(--falkor-quaternary);
-}
-
-.db-modal-input:disabled {
- background: var(--bg-tertiary);
- color: var(--text-secondary);
- cursor: not-allowed;
-}
-
-.db-modal-actions {
- display: flex;
- justify-content: space-between;
- gap: 1em;
-}
-
-.db-modal-btn {
- flex: 1;
- padding: 0.5em 0;
- border: none;
- border-radius: 6px;
- font-size: 1em;
- font-weight: bold;
- cursor: pointer;
- transition: background 0.2s;
-}
-
-.db-modal-connect {
- background: #4285F4;
- color: #fff;
-}
-
-.db-modal-connect:hover {
- background: #3367d6;
-}
-
-.db-modal-connect:disabled {
- background: #6c8db8;
- cursor: not-allowed;
-}
-
-.db-modal-loading-spinner {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 8px;
-}
-
-.spinner {
- width: 16px;
- height: 16px;
- border: 2px solid #ffffff40;
- border-top: 2px solid #ffffff;
- border-radius: 50%;
- animation: spin 1s linear infinite;
-}
-
-.db-modal-cancel {
- background: var(--bg-tertiary);
- color: var(--text-primary);
- border: 1px solid var(--border-color);
-}
-
-.db-modal-cancel:hover {
- background: var(--border-color);
-}
-
-.db-modal-cancel:disabled {
- background: var(--bg-tertiary);
- color: var(--text-secondary);
- cursor: not-allowed;
- border: 1px solid var(--text-secondary);
-}
-
-.login-modal {
- display: none;
- position: fixed;
- top: 0;
- left: 0;
- width: 100dvw;
- height: 100dvh;
- background: rgba(0,0,0,0.6);
- z-index: 1000;
- align-items: center;
- justify-content: center;
-}
-
-.login-modal-content {
- background: var(--falkor-secondary);
- padding: 2em 3em;
- border-radius: 10px;
- box-shadow: 0 2px 16px rgba(0,0,0,0.2);
- text-align: center;
- color: var(--text-primary);
-}
-
-.login-modal-content h2 {
- color: var(--text-primary);
- margin-bottom: 0.5em;
- font-size: 1.5em;
-}
-
-.login-modal-content p {
- color: var(--text-secondary);
- margin-bottom: 1em;
- font-size: 1em;
-}
-
-/* Email Authentication Styles */
-.auth-divider {
- margin: 1.5em 0;
- position: relative;
- text-align: center;
-}
-
-.auth-divider::before {
- content: '';
- position: absolute;
- top: 50%;
- left: 0;
- right: 0;
- height: 1px;
- background: var(--border-color);
-}
-
-.auth-divider span {
- background: var(--falkor-secondary);
- color: var(--text-secondary);
- padding: 0 1em;
- font-size: 0.9em;
-}
-
-.email-auth-form {
- display: flex;
- flex-direction: column;
- gap: 1em;
- margin-top: 1em;
-}
-
-.auth-input {
- width: 100%;
- padding: 0.75em;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- font-size: 1em;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- box-sizing: border-box;
-}
-
-.auth-input:focus {
- outline: none;
- border-color: #4285F4;
- box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
-}
-
-.auth-input::placeholder {
- color: var(--text-secondary);
-}
-
-.email-login-btn, .email-signup-btn {
- width: 100%;
- padding: 0.75em;
- border: none;
- border-radius: 6px;
- font-size: 1.1em;
- font-weight: 500;
- cursor: pointer;
- transition: background 0.2s;
- margin-top: 0.5em;
-}
-
-.email-login-btn {
- background: #5B6BC0;
- color: #fff;
-}
-
-.email-login-btn:hover {
- background: #4F5BA7;
-}
-
-.email-signup-btn {
- background: #5B6BC0;
- color: #fff;
-}
-
-.email-signup-btn:hover {
- background: #4F5BA7;
-}
-
-.email-login-btn:disabled, .email-signup-btn:disabled {
- background: #cccccc;
- color: #888888;
- cursor: not-allowed;
-}
-
-.auth-footer {
- margin-top: 1.5em;
- text-align: center;
- color: var(--text-secondary);
- font-size: 0.9em;
-}
-
-.signup-link {
- color: #4285F4;
- text-decoration: none;
- font-weight: 500;
-}
-
-.signup-link:hover {
- text-decoration: underline;
-}
-
-/* User Profile Dropdown */
-.user-profile-dropdown {
- position: fixed;
- top: 80px;
- right: 30px;
- z-index: 1999;
- background: var(--falkor-secondary);
- border: 1px solid var(--falkor-border-primary);
- border-radius: 6px;
- box-shadow: 0 4px 12px rgba(0,0,0,0.25);
- min-width: 200px;
- display: none;
-}
-
-.user-profile-dropdown.show {
- display: block;
-}
-
-.user-profile-initial {
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: var(--falkor-quaternary);
- color: var(--text-primary);
- font-weight: bold;
-}
-.user-profile-info {
- padding: 15px;
- border-bottom: 1px solid var(--falkor-quaternary);
-}
-
-.user-profile-name {
- color: var(--text-primary);
- font-weight: bold;
- margin-bottom: 5px;
-}
-
-.user-profile-email {
- color: var(--text-secondary);
- font-size: 0.9em;
-}
-
-.user-profile-actions {
- padding: 10px;
- display: flex;
- flex-direction: column;
- gap: 8px; /* space between API Tokens and Logout */
-}
-
-/* Destructive Confirmation Styles */
-.destructive-confirmation-container {
- transition: all 0.3s ease;
-}
-
-.destructive-confirmation-message {
- border: 1px solid #D32F2F;
- border-radius: 6px;
- background: linear-gradient(135deg, var(--bg-tertiary), var(--falkor-quaternary));
-}
-
-.destructive-confirmation {
- padding: 20px;
- transition: all 0.3s ease;
-}
-
-.confirmation-text {
- margin-bottom: 20px;
- line-height: 1.6;
- color: var(--text-primary);
- font-size: 14px;
-}
-
-.confirmation-text strong {
- color: var(--text-primary);
- font-weight: bold;
-}
-
-.confirmation-buttons {
- display: flex;
- gap: 15px;
- justify-content: center;
- margin-top: 20px;
-}
-
-/* Reset Confirmation Modal */
-.reset-confirmation-modal {
- display: none;
- position: fixed;
- top: 0;
- left: 0;
- width: 100dvw;
- height: 100dvh;
- background: rgba(0,0,0,0.6);
- z-index: 2000;
- align-items: center;
- justify-content: center;
-}
-
-.reset-confirmation-modal-content {
- background: var(--falkor-secondary);
- padding: 2em 3em;
- border-radius: 10px;
- box-shadow: 0 2px 16px rgba(0,0,0,0.2);
- text-align: center;
- color: var(--text-primary);
- min-width: 400px;
-}
-
-.reset-confirmation-modal-content h3 {
- color: var(--text-primary);
- margin-bottom: 0.5em;
- font-size: 1.3em;
-}
-
-.reset-confirmation-modal-content p {
- color: var(--text-secondary);
- font-size: 1em;
- line-height: 1.5;
-}
-
-/* Token Management Modal */
-.modal {
- display: none;
- position: fixed;
- top: 0;
- left: 0;
- width: 100dvw;
- height: 100dvh;
- background: rgba(0,0,0,0.6);
- z-index: 3000;
- align-items: center;
- justify-content: center;
-}
-
-.modal .modal-content {
- background: var(--falkor-secondary);
- padding: 0;
- border-radius: 10px;
- box-shadow: 0 2px 16px rgba(0,0,0,0.2);
- color: var(--text-primary);
- min-width: 600px;
- max-width: 90dvw;
- max-height: 90dvh;
- overflow: hidden;
- display: flex;
- flex-direction: column;
-}
-
-.modal .modal-header {
- background: var(--falkor-primary);
- padding: 1.5em 2em;
- border-bottom: 1px solid var(--border-color);
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.modal .modal-header h2 {
- margin: 0;
- color: var(--text-primary);
- font-size: 1.4em;
-}
-
-.modal .close-btn {
- background: none;
- border: none;
- font-size: 3em;
- color: var(--text-secondary);
- cursor: pointer;
- padding: 0;
- line-height: 1;
-}
-
-.modal .close-btn:hover {
- color: var(--text-primary);
-}
-
-.modal .modal-body {
- padding: 2em;
- overflow-y: auto;
- flex: 1;
-}
-
-.tokens-description {
- color: var(--text-secondary);
- margin-bottom: 2em;
- line-height: 1.6;
-}
-
-.tokens-actions {
- margin-bottom: 2em;
-}
-
-.btn {
- padding: 0.8em 1.5em;
- border: none;
- border-radius: 6px;
- cursor: pointer;
- font-size: 0.9em;
- font-weight: 500;
- transition: all 0.2s ease;
- text-decoration: none;
- display: inline-block;
- text-align: center;
-}
-
-.btn:disabled {
- opacity: 0.6;
- cursor: not-allowed;
-}
-
-.btn-primary {
- background: var(--accent-color);
- color: white;
-}
-
-.btn-primary:hover:not(:disabled) {
- background: var(--accent-hover);
-}
-
-.btn-secondary {
- background: var(--bg-tertiary);
- color: var(--text-primary);
- border: 1px solid var(--border-color);
-}
-
-.btn-secondary:hover:not(:disabled) {
- background: var(--bg-secondary);
-}
-
-.btn-danger {
- background: #dc3545;
- color: white;
-}
-
-.btn-danger:hover:not(:disabled) {
- background: #c82333;
-}
-
-.btn-sm {
- padding: 0.5em 1em;
- font-size: 0.8em;
-}
-
-.token-generation-result {
- margin-bottom: 2em;
-}
-
-.token-input-wrap {
- display: flex;
- align-items: center;
- gap: 0.5em;
- width: 100%;
-}
-
-.token-input {
- flex: 1 1 700px; /* allow input to grow, prefer large width */
- min-width: 300px;
- padding: 0.6em 0.8em;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- color: var(--text-primary);
- background: var(--falkor-quaternary);
- overflow-x: auto;
-}
-
-/* Styles for incremental database connection steps shown in the connect modal */
-#db-connection-steps {
- margin: 16px 24px;
- font-size: 14px;
- color: var(--text-primary);
-}
-
-#db-connection-steps-list {
- list-style: none;
- padding: 0;
- margin: 0;
- max-height: 220px;
- overflow: auto;
-}
-
-.db-connection-step {
- display: flex;
- align-items: center;
- margin: 8px 0;
-}
-
-.db-connection-step .step-icon {
- display: inline-flex;
- width: 20px;
- height: 20px;
- margin-right: 8px;
- border-radius: 50%;
- align-items: center;
- justify-content: center;
- font-size: 12px;
- line-height: 20px;
-}
-
-.db-connection-step .step-icon.pending { color: #1f6feb; }
-.db-connection-step .step-icon.success { color: #16a34a; }
-.db-connection-step .step-icon.error { color: #dc2626; }
-
-.alert {
- padding: 1.5em;
- border-radius: 6px;
- margin-bottom: 1em;
-}
-
-.alert-success {
- background: rgba(40, 167, 69, 0.1);
- border: 1px solid rgba(40, 167, 69, 0.3);
- color: var(--text-primary);
-}
-
-.alert h4 {
- margin: 0 0 0.5em 0;
- color: var(--text-primary);
- font-size: 1.1em;
-}
-
-.alert p {
- margin: 0 0 1em 0;
- color: var(--text-secondary);
- line-height: 1.5;
-}
-
-.token-display {
- display: flex;
- gap: 0.5em;
- align-items: center;
-}
-
-.token-input {
- flex: 1;
- padding: 0.8em;
- font-size: 0.9em;
- border: 1px solid var(--border-color);
- border-radius: 6px;
- background: var(--falkor-quaternary);
- color: var(--text-primary);
- word-break: break-all;
-}
-
-.tokens-list h3 {
- margin: 0 0 1.5em 0;
- color: var(--text-primary);
- font-size: 1.2em;
- border-bottom: 1px solid var(--border-color);
- padding-bottom: 0.5em;
-}
-
-.no-tokens {
- color: var(--text-secondary);
- font-style: italic;
- text-align: center;
- padding: 2em;
-}
-
-.tokens-table {
- width: 100%;
- border-collapse: collapse;
- margin-top: 1em;
-}
-
-.tokens-table th,
-.tokens-table td {
- padding: 1em;
- text-align: left;
- border-bottom: 1px solid var(--border-color);
-}
-
-.tokens-table th {
- background: var(--bg-tertiary);
- color: var(--text-primary);
- font-weight: 600;
- font-size: 0.9em;
-}
-
-.tokens-table td {
- color: var(--text-secondary);
-}
-
-.tokens-table tbody tr:hover {
- background: var(--bg-tertiary);
-}
-
-.modal-actions {
- display: flex;
- gap: 1em;
- justify-content: flex-end;
- margin-top: 2em;
-}
diff --git a/app/public/css/responsive.css b/app/public/css/responsive.css
deleted file mode 100644
index 81658784..00000000
--- a/app/public/css/responsive.css
+++ /dev/null
@@ -1,370 +0,0 @@
-/* Mobile Responsive Styles */
-
-/* Hide sidebar close button on desktop */
-@media (min-width: 769px) {
- .sidebar-close-btn {
- display: none !important;
- }
-}
-
-/* Layout Responsive */
-@media (max-width: 768px) {
-
- .github-link {
- height: 40px;
- width: 40px;
- align-items: center;
- justify-content: center;
- }
-
- /* When left toolbar is open, push content to make room */
- body.left-toolbar-open .chat-container {
- max-width: calc(100dvw - 48px);
- }
-
- /* Ensure body doesn't overflow */
- body {
- max-width: 100dvw;
- overflow-x: hidden;
- }
-
- /* Main container mobile adjustments */
- #container {
- width: 100%;
- max-width: 100dvw;
- overflow-x: hidden;
- box-sizing: border-box;
- transition: margin-left 220ms ease;
- margin-left: 0;
- }
-
- .menu-item {
- flex-wrap: wrap;
- }
-
- .menu-item p {
- font-size: 12px;
- }
-
- .db-modal-content {
- min-width: 0px;
- max-width: 90%;
- padding: 40px;
- }
-
- /* Adjust container when toolbar is open */
- body.left-toolbar-open #container {
- width: calc(100% - 48px);
- margin-left: 48px;
- }
-
- /* Prevent any background showing behind the shifted content */
- body.left-toolbar-open {
- background: var(--falkor-secondary);
- }
-
- /* Ensure chat container fills the available space properly */
- body.left-toolbar-open .chat-container {
- background: var(--falkor-secondary);
- border-left: none;
- }
-
- /* Ensure chat header elements are properly positioned when toolbar is open */
- body.left-toolbar-open .chat-header {
- padding-left: 15px;
- /* Add extra padding to prevent overlap */
- width: 100%;
- box-sizing: border-box;
- }
-
- /* Ensure dropdown and buttons in header don't get cut off */
- body.left-toolbar-open .chat-header>* {
- margin-left: 0;
- width: 100%;
- }
-}
-
-/* Mobile: Menu overlays content (no pushing) */
-@media (max-width: 768px) {
- .resize-handle {
- display: none;
- }
-
- .sidebar-container {
- position: fixed;
- top: 0;
- bottom: 33px;
- left: 48px;
- z-index: 10;
- }
-
- .sidebar-container.open {
- min-width: 80ddvw;
- z-index: 10;
- }
-
- #container:has(.sidebar-container.open)::before {
- content: '';
- position: fixed;
- top: 0;
- left: 0;
- width: 100dvw;
- height: 100dvh;
- background: rgba(0, 0, 0, 0.3);
- backdrop-filter: blur(4px);
- -webkit-backdrop-filter: blur(4px);
- z-index: 9;
- pointer-events: auto;
- }
-
- /* Sidebar close button - only visible on mobile */
- .sidebar-close-btn {
- display: block;
- position: absolute;
- top: 15px;
- right: 15px;
- width: 32px;
- height: 32px;
- background: var(--falkor-primary);
- border: none;
- border-radius: 6px;
- color: white;
- cursor: pointer;
- z-index: 15;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: background-color 0.2s ease;
- }
-
- .sidebar-close-btn:hover {
- background: var(--falkor-primary-hover, #0056b3);
- }
-
- .sidebar-close-btn svg {
- width: 18px;
- height: 18px;
- }
-}
-
-/* Chat Messages Responsive */
-@media (max-width: 768px) {
- .message {
- max-width: 85%;
- padding: 10px 12px;
- font-size: 14px;
- }
-
- .chat-header h1 {
- font-size: 18px;
- }
-
- #message-input {
- font-size: 16px !important;
- }
-
- #message-input::placeholder {
- font-size: 16px !important;
- }
-}
-
-/* Button Container Responsive */
-@media (max-width: 768px) {
- .chat-header .button-container {
- width: 100%;
- max-width: 100%;
- padding: 0 10px;
- margin: 0;
- box-sizing: border-box;
- gap: 8px;
- flex-wrap: nowrap;
- }
-
- /* Hide vertical separators on mobile */
- .vertical-separator {
- display: none;
- }
-
- /* Make selectors and buttons fit screen width */
- #custom-file-upload {
- flex: 1;
- min-width: 0;
- padding: 8px 6px;
- font-size: 13px;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- height: 40px;
- box-sizing: border-box;
- max-width: 35%;
- text-align: center;
- display: none;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- }
-
- .dropdown-selected {
- padding: 8px 6px;
- font-size: 13px;
- height: 100%;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-
- .dropdown-text {
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- flex: 1;
- }
-
- .dropdown-arrow {
- margin-left: 4px;
- flex-shrink: 0;
- }
-}
-
-@media (max-width: 480px) {
- .chat-header .button-container {
- padding: 0;
- gap: 5px;
- }
-
- #custom-file-upload {
- padding: 6px 4px;
- font-size: 12px;
- height: 36px;
- }
-
- .dropdown-selected {
- padding: 6px 4px;
- font-size: 12px;
- }
-}
-
-/* Input Button Responsive */
-@media (max-width: 768px) {
- .input-button {
- width: 40px;
- height: 40px;
- }
-}
-
-/* Reset Button Responsive */
-@media (max-width: 768px) {
- #reset-button {
- position: relative;
- right: auto;
- top: auto;
- transform: none;
- margin-left: 10px;
- }
-
- #reset-button svg {
- width: 18px;
- height: 18px;
- }
-
- .chat-input {
- padding: 0px;
- gap: 8px;
- /* Ensure it fits within viewport width */
- margin: 0;
- box-sizing: border-box;
- }
-
- .input-container {
- /* Reduce padding on mobile to maximize input space */
- padding: 8px;
- gap: 4px;
- min-width: 0;
- /* Allow container to shrink */
- flex-shrink: 1;
- }
-
- #message-input {
- font-size: 16px !important;
- /* Prevent zoom on iOS */
- min-width: 0;
- /* Allow input to shrink */
- }
-
- #message-input::placeholder {
- font-size: 16px !important;
- }
-
- /* Ensure buttons don't overflow */
- .input-button {
- width: 40px;
- height: 40px;
- flex-shrink: 0;
- /* Prevent buttons from shrinking */
- }
-}
-
-/* Action Buttons Responsive */
-@media (max-width: 768px) {
- .action-button {
- width: 40px;
- height: 40px;
- }
-}
-
-/* User Profile and Navigation Responsive */
-@media (max-width: 768px) {
- .user-profile-btn {
- top: 15px;
- right: 15px;
- width: 40px;
- height: 40px;
- }
-
- #github-link-btn {
- top: 15px;
- right: 60px;
- padding: 6px 8px;
- font-size: 12px;
- height: 40px;
- }
-
- /* Hide star icon and text on mobile, show only GitHub icon */
- .github-star-icon,
- .github-stars-text {
- display: none;
- }
-
- .theme-icon {
- width: 18px;
- height: 18px;
- }
-}
-
-/* User Profile Dropdown Responsive */
-@media (max-width: 768px) {
- .user-profile-dropdown {
- top: 65px;
- right: 15px;
- min-width: 180px;
- }
-}
-
-/* Modal Responsive */
-@media (max-width: 768px) {
- .pg-modal-content {
- padding: 1.5em 2em;
- min-width: 90dvw;
- margin: 0 5dvw;
- }
-}
-
-/* Reset Modal Responsive */
-@media (max-width: 768px) {
- .reset-confirmation-modal-content {
- padding: 1.5em 2em;
- min-width: 90dvw;
- margin: 0 5dvw;
- }
-}
\ No newline at end of file
diff --git a/app/public/css/themes.css b/app/public/css/themes.css
deleted file mode 100644
index 7683eb34..00000000
--- a/app/public/css/themes.css
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Theme-specific Styles and Overrides */
-
-/* Theme icon states */
-[data-theme="dark"] .theme-icon .sun,
-[data-theme="system"] .theme-icon .sun {
- display: none;
-}
-
-[data-theme="dark"] .theme-icon .moon {
- display: block;
-}
-
-[data-theme="dark"] .theme-icon .system,
-[data-theme="light"] .theme-icon .system {
- display: none;
-}
-
-[data-theme="light"] .theme-icon .sun {
- display: block;
-}
-
-[data-theme="light"] .theme-icon .moon,
-[data-theme="system"] .theme-icon .moon {
- display: none;
-}
-
-[data-theme="system"] .theme-icon .system {
- display: block;
-}
-
-[data-theme="system"] .theme-icon .sun {
- display: none;
-}
diff --git a/app/public/css/variables.css b/app/public/css/variables.css
deleted file mode 100644
index 693f1bb5..00000000
--- a/app/public/css/variables.css
+++ /dev/null
@@ -1,91 +0,0 @@
-/* CSS Custom Properties and Theme Variables */
-
-:root {
- /* Professional color palette - muted and business-appropriate */
- --falkor-primary: #5B6BC0;
- /* Muted indigo - professional primary */
- --falkor-secondary: #1A1A1A;
- /* Dark charcoal - main background */
- --falkor-tertiary: #B39DDB;
- /* Muted lavender - subtle tertiary */
- --falkor-quaternary: #424242;
- /* Medium gray - quaternary */
- --dark-bg: #0F0F0F;
- /* Deep dark for surfaces */
- --falkor-accent: #26A69A;
- /* Professional teal - subdued accent */
- --falkor-border-primary: #5B6BC0;
- /* Primary border color*/
- --falkor-border-secondary: #90A4AE;
- /* Muted blue-gray - professional secondary border */
- --falkor-border-tertiary: #E0E0E0;
- /* Light gray border */
- --text-primary: #F5F5F5;
- /* Soft white text */
- --text-secondary: #B0BEC5;
- /* Muted blue-gray text */
- --text-tertiary: #616161;
- /* Medium gray text */
- --falkor-highlight: #4DB6AC;
- /* Subtle teal highlight */
- --accent-green: #66BB6A;
- /* Professional green */
- --icon-filter: invert(1);
- /* Dark theme - invert icons for white appearance */
- --bg-tertiary: #2E2E2E;
- /* Professional dark gray */
- --border-color: #616161;
- /* Subtle border color */
-}
-
-/* Light theme variables */
-[data-theme="light"] {
- --falkor-primary: #5B6BC0;
- --falkor-secondary: #FAFAFA;
- --falkor-tertiary: #B39DDB;
- --falkor-quaternary: #F5F5F5;
- --dark-bg: #FFFFFF;
- --falkor-accent: #26A69A;
- --falkor-border-primary: #5B6BC0;
- --falkor-border-secondary: #90A4AE;
- --falkor-border-tertiary: #424242;
- --text-primary: #212121;
- --text-secondary: #616161;
- --text-tertiary: #9E9E9E;
- --falkor-highlight: #4DB6AC;
- --accent-green: #388E3C;
- /* Professional dark green for light theme */
- --icon-filter: invert(0);
- /* Light theme - no inversion for dark icons */
- --bg-tertiary: #F8F8F8;
- /* Very light gray background */
- --border-color: #E0E0E0;
- /* Light border color */
-}
-
-/* System theme detection */
-@media (prefers-color-scheme: light) {
- [data-theme="system"] {
- --falkor-primary: #5B6BC0;
- --falkor-secondary: #FAFAFA;
- --falkor-tertiary: #B39DDB;
- --falkor-quaternary: #F5F5F5;
- --dark-bg: #FFFFFF;
- --falkor-accent: #26A69A;
- --falkor-border-primary: #5B6BC0;
- --falkor-border-secondary: #90A4AE;
- --falkor-border-tertiary: #424242;
- --text-primary: #212121;
- --text-secondary: #616161;
- --text-tertiary: #9E9E9E;
- --falkor-highlight: #4DB6AC;
- --accent-green: #388E3C;
- /* Professional dark green for light theme */
- --icon-filter: invert(0);
- /* Light theme - no inversion for dark icons */
- --bg-tertiary: #F8F8F8;
- /* Very light gray background */
- --border-color: #E0E0E0;
- /* Light border color */
- }
-}
diff --git a/app/public/placeholder.svg b/app/public/placeholder.svg
new file mode 100644
index 00000000..e763910b
--- /dev/null
+++ b/app/public/placeholder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/public/robots.txt b/app/public/robots.txt
new file mode 100644
index 00000000..6018e701
--- /dev/null
+++ b/app/public/robots.txt
@@ -0,0 +1,14 @@
+User-agent: Googlebot
+Allow: /
+
+User-agent: Bingbot
+Allow: /
+
+User-agent: Twitterbot
+Allow: /
+
+User-agent: facebookexternalhit
+Allow: /
+
+User-agent: *
+Allow: /
diff --git a/app/src/App.tsx b/app/src/App.tsx
new file mode 100644
index 00000000..82d179e3
--- /dev/null
+++ b/app/src/App.tsx
@@ -0,0 +1,31 @@
+import { Toaster } from "@/components/ui/toaster";
+import { TooltipProvider } from "@/components/ui/tooltip";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import { AuthProvider } from "@/contexts/AuthContext";
+import { DatabaseProvider } from "@/contexts/DatabaseContext";
+import Index from "./pages/Index";
+import NotFound from "./pages/NotFound";
+
+const queryClient = new QueryClient();
+
+const App = () => (
+
+
+
+
+
+
+
+ } />
+ {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
+ } />
+
+
+
+
+
+
+);
+
+export default App;
diff --git a/app/src/components/SuggestionCards.tsx b/app/src/components/SuggestionCards.tsx
new file mode 100644
index 00000000..90014780
--- /dev/null
+++ b/app/src/components/SuggestionCards.tsx
@@ -0,0 +1,39 @@
+import { Card, CardContent } from "@/components/ui/card";
+
+interface SuggestionCardsProps {
+ suggestions: string[];
+ onSelect: (suggestion: string) => void;
+ disabled?: boolean;
+}
+
+const SuggestionCards = ({ suggestions, onSelect, disabled = false }: SuggestionCardsProps) => {
+ return (
+
+ {suggestions.map((suggestion) => (
+
onSelect(suggestion)}
+ role="button"
+ tabIndex={disabled ? -1 : 0}
+ aria-disabled={disabled}
+ onKeyDown={(e) => {
+ if (disabled) return;
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ onSelect(suggestion);
+ }
+ }}
+ >
+
+
+ {suggestion}
+
+
+
+ ))}
+
+ );
+};
+
+export default SuggestionCards;
diff --git a/app/src/components/chat/ChatInterface.tsx b/app/src/components/chat/ChatInterface.tsx
new file mode 100644
index 00000000..60679654
--- /dev/null
+++ b/app/src/components/chat/ChatInterface.tsx
@@ -0,0 +1,556 @@
+import { useState, useEffect, useRef } from "react";
+import { cn } from "@/lib/utils";
+import { useToast } from "@/components/ui/use-toast";
+import { useDatabase } from "@/contexts/DatabaseContext";
+import { useAuth } from "@/contexts/AuthContext";
+import LoadingSpinner from "@/components/ui/loading-spinner";
+import { Skeleton } from "@/components/ui/skeleton";
+import ChatMessage from "./ChatMessage";
+import QueryInput from "./QueryInput";
+import SuggestionCards from "../SuggestionCards";
+import { ChatService } from "@/services/chat";
+import type { ConversationMessage } from "@/types/api";
+
+interface ChatMessageData {
+ id: string;
+ type: 'user' | 'ai' | 'ai-steps' | 'sql-query' | 'query-result' | 'confirmation';
+ content: string;
+ steps?: Array<{
+ icon: 'search' | 'database' | 'code' | 'message';
+ text: string;
+ }>;
+ queryData?: any[]; // For table data
+ analysisInfo?: {
+ confidence?: number;
+ missing?: string;
+ ambiguities?: string;
+ explanation?: string;
+ isValid?: boolean;
+ };
+ confirmationData?: {
+ sqlQuery: string;
+ operationType: string;
+ message: string;
+ chatHistory: string[];
+ };
+ timestamp: Date;
+}
+
+export interface ChatInterfaceProps {
+ className?: string;
+ disabled?: boolean; // when true, block interactions
+ onProcessingChange?: (isProcessing: boolean) => void; // callback to notify parent of processing state
+}
+
+const ChatInterface = ({ className, disabled = false, onProcessingChange }: ChatInterfaceProps) => {
+ const { toast } = useToast();
+ const { selectedGraph } = useDatabase();
+ const [isProcessing, setIsProcessing] = useState(false);
+ const messagesEndRef = useRef(null);
+ const chatContainerRef = useRef(null);
+ const conversationHistory = useRef([]);
+
+ // Auto-scroll to bottom function
+ const scrollToBottom = () => {
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
+ };
+
+ // Loading message component using skeleton
+ const LoadingMessage = () => (
+
+ );
+
+ const { user } = useAuth();
+ const [messages, setMessages] = useState([
+ {
+ id: "1",
+ type: "ai",
+ content: "Hello! Describe what you'd like to ask your database",
+ timestamp: new Date(),
+ }
+ ]);
+
+ const suggestions = [
+ "Show me five customers",
+ "Show me the top customers by revenue",
+ "What are the pending orders?"
+ ];
+
+ // Reset conversation when the selected graph changes to avoid leaking
+ // conversation history between different databases.
+ useEffect(() => {
+ // Clear in-memory conversation history and reset messages to the greeting
+ conversationHistory.current = [];
+ setMessages([
+ {
+ id: "1",
+ type: "ai",
+ content: "Hello! Describe what you'd like to ask your database",
+ timestamp: new Date(),
+ }
+ ]);
+ }, [selectedGraph?.id]);
+
+ // Scroll to bottom whenever messages change
+ useEffect(() => {
+ scrollToBottom();
+ }, [messages, isProcessing]);
+
+ // Notify parent component of processing state changes
+ useEffect(() => {
+ onProcessingChange?.(isProcessing);
+ }, [isProcessing, onProcessingChange]);
+
+ const handleSendMessage = async (query: string) => {
+ if (isProcessing || disabled) return; // Prevent multiple submissions or when disabled by parent
+
+ if (!selectedGraph) {
+ toast({
+ title: "No Database Available",
+ description: "Please upload a database schema first, or start the QueryWeaver backend to use real databases.",
+ variant: "destructive",
+ });
+ return;
+ }
+
+ // Snapshot history before adding the current user message so the backend
+ // sees only prior turns in `history` and the current query in `query`.
+ const historySnapshot = [...conversationHistory.current];
+
+ setIsProcessing(true);
+
+ // Add user message
+ const userMessage: ChatMessageData = {
+ id: Date.now().toString(),
+ type: "user",
+ content: query,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, userMessage]);
+ conversationHistory.current.push({ role: 'user', content: query });
+
+ // Scroll to bottom immediately after adding user message
+ setTimeout(() => scrollToBottom(), 100);
+
+ // Show processing toast
+ toast({
+ title: "Processing Query",
+ description: "Analyzing your question and generating response...",
+ });
+
+ try {
+ // No need for a steps accumulator message - we'll add each step as a separate AI message
+ let finalContent = "";
+ let sqlQuery = "";
+ let queryResults: any[] | null = null;
+ let analysisInfo: {
+ confidence?: number;
+ missing?: string;
+ ambiguities?: string;
+ explanation?: string;
+ isValid?: boolean;
+ } = {};
+
+ // Stream the query
+ for await (const message of ChatService.streamQuery({
+ query,
+ database: selectedGraph.id,
+ history: historySnapshot,
+ })) {
+
+ if (message.type === 'status' || message.type === 'reasoning' || message.type === 'reasoning_step') {
+ // Add each reasoning step as a separate AI message (like the old UI)
+ const stepText = message.content || message.message || '';
+
+ const stepMessage: ChatMessageData = {
+ id: `step-${Date.now()}-${Math.random()}`,
+ type: "ai",
+ content: stepText,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => {
+ const newMessages = [...prev, stepMessage];
+ return newMessages;
+ });
+ } else if (message.type === 'sql_query') {
+ // Store SQL query to display - backend sends it in 'data' field
+ sqlQuery = message.data || message.content || message.message || '';
+ // Also capture analysis information
+ analysisInfo = {
+ confidence: message.conf,
+ missing: message.miss,
+ ambiguities: message.amb,
+ explanation: message.exp,
+ isValid: message.is_valid
+ };
+
+ } else if (message.type === 'query_result') {
+ // Store query results to display as table - backend sends it in 'data' field
+ queryResults = message.data || [];
+ } else if (message.type === 'ai_response') {
+ // AI-generated response - this is what we show to the user
+ const responseContent = (message.message || message.content || '').trim();
+ finalContent = responseContent;
+ } else if (message.type === 'followup_questions') {
+ // Follow-up questions when query is unclear or off-topic
+ const followupContent = (message.message || message.content || '').trim();
+ finalContent = followupContent;
+ } else if (message.type === 'error') {
+ // Handle error
+ toast({
+ title: "Query Failed",
+ description: message.content,
+ variant: "destructive",
+ });
+ finalContent = `Error: ${message.content}`;
+ } else if (message.type === 'confirmation' || message.type === 'destructive_confirmation') {
+ // Handle destructive operation confirmation - add inline confirmation message
+ const confirmationMessage: ChatMessageData = {
+ id: `confirm-${Date.now()}`,
+ type: 'confirmation',
+ content: message.message || message.content || '',
+ confirmationData: {
+ sqlQuery: message.sql_query || '',
+ operationType: message.operation_type || 'UNKNOWN',
+ message: message.message || message.content || '',
+ chatHistory: conversationHistory.current.map(m => m.content),
+ },
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, confirmationMessage]);
+
+ // Don't set finalContent - we want the confirmation to be standalone
+ finalContent = "";
+ } else {
+ console.warn('Unknown message type received:', message.type, message);
+ }
+
+ setTimeout(() => scrollToBottom(), 50);
+ }
+
+ // Add SQL query message with analysis info (even if SQL is empty)
+ if (sqlQuery !== undefined || Object.keys(analysisInfo).length > 0) {
+ const sqlMessage: ChatMessageData = {
+ id: (Date.now() + 2).toString(),
+ type: "sql-query",
+ content: sqlQuery,
+ analysisInfo: analysisInfo,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, sqlMessage]);
+ }
+
+ // Add query results table if available
+ if (queryResults && queryResults.length > 0) {
+ const resultsMessage: ChatMessageData = {
+ id: (Date.now() + 3).toString(),
+ type: "query-result",
+ content: "Query Results",
+ queryData: queryResults,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, resultsMessage]);
+ }
+
+ // Add AI final response if we have one
+ if (finalContent) {
+ const finalResponse: ChatMessageData = {
+ id: (Date.now() + 4).toString(),
+ type: "ai",
+ content: finalContent,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, finalResponse]);
+ conversationHistory.current.push({ role: 'assistant', content: finalContent });
+ }
+
+ // Show success toast
+ toast({
+ title: "Query Complete",
+ description: "Successfully processed your database query!",
+ });
+ } catch (error) {
+ console.error('Query failed:', error);
+
+ const errorMessage: ChatMessageData = {
+ id: (Date.now() + 2).toString(),
+ type: "ai",
+ content: `Failed to process query: ${error instanceof Error ? error.message : 'Unknown error'}`,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, errorMessage]);
+
+ toast({
+ title: "Query Failed",
+ description: error instanceof Error ? error.message : "Failed to process query",
+ variant: "destructive",
+ });
+ } finally {
+ setIsProcessing(false);
+ setTimeout(() => scrollToBottom(), 100);
+ }
+ };
+
+ const handleConfirmDestructive = async (messageId: string) => {
+ if (!selectedGraph) return;
+
+ // Find the confirmation message to get the data
+ const confirmMessage = messages.find(m => m.id === messageId && m.type === 'confirmation');
+ if (!confirmMessage?.confirmationData) return;
+
+ setIsProcessing(true);
+
+ // Remove the confirmation message and replace with "Executing..." message
+ setMessages(prev => prev.filter(m => m.id !== messageId));
+
+ const executingMessage: ChatMessageData = {
+ id: `executing-${Date.now()}`,
+ type: 'ai',
+ content: 'Executing confirmed operation...',
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, executingMessage]);
+
+ // Show processing toast
+ toast({
+ title: "Executing Operation",
+ description: "Processing your confirmed operation...",
+ });
+
+ try {
+ let finalContent = "";
+ let queryResults: any[] | null = null;
+
+ // Stream the confirmation response
+ for await (const message of ChatService.streamConfirmOperation(
+ selectedGraph.id,
+ {
+ sql_query: confirmMessage.confirmationData.sqlQuery,
+ confirmation: 'CONFIRM',
+ chat: confirmMessage.confirmationData.chatHistory,
+ }
+ )) {
+ if (message.type === 'status' || message.type === 'reasoning' || message.type === 'reasoning_step') {
+ // Add reasoning steps
+ const stepText = message.content || message.message || '';
+ const stepMessage: ChatMessageData = {
+ id: `step-${Date.now()}-${Math.random()}`,
+ type: "ai",
+ content: stepText,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, stepMessage]);
+ } else if (message.type === 'query_result') {
+ // Store query results
+ queryResults = message.data || [];
+ } else if (message.type === 'ai_response') {
+ // AI-generated response
+ const responseContent = (message.message || message.content || '').trim();
+ finalContent = responseContent;
+ } else if (message.type === 'error') {
+ // Handle error - backend sends 'message' field, not 'content'
+ let errorMsg = message.message || message.content || 'Unknown error occurred';
+
+ // Clean up common database errors to be more user-friendly
+ if (errorMsg.includes('duplicate key value violates unique constraint')) {
+ const match = errorMsg.match(/Key \((\w+)\)=\(([^)]+)\)/);
+ if (match) {
+ const [, field, value] = match;
+ errorMsg = `A record with ${field} "${value}" already exists.`;
+ } else {
+ errorMsg = 'This record already exists in the database.';
+ }
+ } else if (errorMsg.includes('violates foreign key constraint')) {
+ errorMsg = 'Cannot perform this operation due to related records in other tables.';
+ } else if (errorMsg.includes('violates not-null constraint')) {
+ const match = errorMsg.match(/column "(\w+)"/);
+ if (match) {
+ errorMsg = `The field "${match[1]}" cannot be empty.`;
+ } else {
+ errorMsg = 'Required field cannot be empty.';
+ }
+ } else if (errorMsg.includes('PostgreSQL query execution error:') || errorMsg.includes('MySQL query execution error:')) {
+ // Strip the "PostgreSQL/MySQL query execution error:" prefix
+ errorMsg = errorMsg.replace(/^(PostgreSQL|MySQL) query execution error:\s*/i, '');
+ // Remove technical details after newline
+ errorMsg = errorMsg.split('\n')[0];
+ }
+
+ toast({
+ title: "Operation Failed",
+ description: errorMsg,
+ variant: "destructive",
+ });
+ finalContent = `${errorMsg}`;
+ } else if (message.type === 'schema_refresh') {
+ // Schema refresh notification
+ const refreshContent = message.message || message.content || '';
+ const refreshMessage: ChatMessageData = {
+ id: `refresh-${Date.now()}`,
+ type: "ai",
+ content: refreshContent,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, refreshMessage]);
+ }
+
+ setTimeout(() => scrollToBottom(), 50);
+ }
+
+ // Add query results table if available
+ if (queryResults && queryResults.length > 0) {
+ const resultsMessage: ChatMessageData = {
+ id: (Date.now() + 3).toString(),
+ type: "query-result",
+ content: "Query Results",
+ queryData: queryResults,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, resultsMessage]);
+ }
+
+ // Add AI final response if we have one
+ if (finalContent) {
+ const finalResponse: ChatMessageData = {
+ id: (Date.now() + 4).toString(),
+ type: "ai",
+ content: finalContent,
+ timestamp: new Date(),
+ };
+ setMessages(prev => [...prev, finalResponse]);
+ conversationHistory.current.push({ role: 'assistant', content: finalContent });
+ }
+
+ toast({
+ title: "Operation Complete",
+ description: "Successfully executed the operation!",
+ });
+ } catch (error) {
+ console.error('Confirmation error:', error);
+
+ const errorMessage: ChatMessageData = {
+ id: (Date.now() + 2).toString(),
+ type: "ai",
+ content: `Failed to execute operation: ${error instanceof Error ? error.message : 'Unknown error'}`,
+ timestamp: new Date(),
+ };
+
+ setMessages(prev => [...prev, errorMessage]);
+
+ toast({
+ title: "Operation Failed",
+ description: error instanceof Error ? error.message : "Failed to execute operation",
+ variant: "destructive",
+ });
+ } finally {
+ setIsProcessing(false);
+ setTimeout(() => scrollToBottom(), 100);
+ }
+ };
+
+ const handleCancelDestructive = (messageId: string) => {
+ // Remove the confirmation message and add cancellation message
+ setMessages(prev => prev.filter(m => m.id !== messageId));
+
+ setMessages(prev => [
+ ...prev,
+ {
+ id: `cancel-${Date.now()}`,
+ type: 'ai',
+ content: 'Operation cancelled. The destructive SQL query was not executed.',
+ timestamp: new Date(),
+ }
+ ]);
+
+ toast({
+ title: "Operation Cancelled",
+ description: "The destructive operation was not executed.",
+ });
+ };
+
+ const handleSuggestionSelect = (suggestion: string) => {
+ handleSendMessage(suggestion);
+ };
+
+ return (
+
+ {/* Messages Area */}
+
+
+ {messages.map((msg) => (
+
handleConfirmDestructive(msg.id) : undefined}
+ onCancel={msg.type === 'confirmation' ? () => handleCancelDestructive(msg.id) : undefined}
+ />
+ ))}
+ {/* Show loading skeleton when processing */}
+ {isProcessing && }
+ {/* Invisible div to scroll to */}
+
+
+
+
+ {/* Bottom Section with Suggestions and Input */}
+
+
+ {/* Suggestion Cards - Only show for DEMO_CRM database */}
+ {(selectedGraph?.id === 'DEMO_CRM' || selectedGraph?.name === 'DEMO_CRM') && (
+
+ )}
+
+ {/* Query Input */}
+
+
+ {/* Show loading indicator when processing */}
+ {isProcessing && (
+
+
+ Processing your query...
+
+ )}
+
+ {/* Footer */}
+
+
+
+
+ );
+};
+
+export default ChatInterface;
\ No newline at end of file
diff --git a/app/src/components/chat/ChatMessage.tsx b/app/src/components/chat/ChatMessage.tsx
new file mode 100644
index 00000000..bdd82721
--- /dev/null
+++ b/app/src/components/chat/ChatMessage.tsx
@@ -0,0 +1,312 @@
+import React from 'react';
+import { Database, Search, Code, MessageSquare, AlertTriangle } from 'lucide-react';
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
+import { Card, CardContent } from '@/components/ui/card';
+import { Badge } from '@/components/ui/badge';
+import { Progress } from '@/components/ui/progress';
+import { Button } from '@/components/ui/button';
+import type { User as UserType } from '@/types/api';
+
+interface Step {
+ icon: 'search' | 'database' | 'code' | 'message';
+ text: string;
+}
+
+interface ChatMessageProps {
+ type: 'user' | 'ai' | 'ai-steps' | 'sql-query' | 'query-result' | 'confirmation';
+ content: string;
+ steps?: Step[];
+ queryData?: any[]; // For table data
+ analysisInfo?: {
+ confidence?: number;
+ missing?: string;
+ ambiguities?: string;
+ explanation?: string;
+ isValid?: boolean;
+ };
+ confirmationData?: {
+ sqlQuery: string;
+ operationType: string;
+ message: string;
+ };
+ progress?: number; // Progress percentage for AI steps
+ user?: UserType | null; // User info for avatar
+ onConfirm?: () => void;
+ onCancel?: () => void;
+}
+
+const ChatMessage = ({ type, content, steps, queryData, analysisInfo, confirmationData, progress, user, onConfirm, onCancel }: ChatMessageProps) => {
+ if (type === 'confirmation') {
+ const operationType = (confirmationData?.operationType ?? 'UNKNOWN').toUpperCase();
+ const isHighRisk = ['DELETE', 'DROP', 'TRUNCATE'].includes(operationType);
+
+ return (
+
+
+
+
+ QW
+
+
+
+
+
+
+
+
+ Destructive Operation Detected
+
+
+
+
+
+
+ This operation will perform a {operationType} query:
+
+ {confirmationData?.sqlQuery && (
+
+
+ {confirmationData.sqlQuery}
+
+
+ )}
+
+
+
+
+ {isHighRisk ? (
+ <>
+ ⚠️ WARNING: This operation may be irreversible and will permanently modify your database.
+ >
+ ) : (
+ <>This operation will make changes to your database. Please review carefully before confirming.>
+ )}
+
+
+
+
+
+ Cancel
+
+
+ Confirm {operationType}
+
+
+
+
+
+
+
+
+ );
+ }
+
+ if (type === 'user') {
+ return (
+
+
+
+
+
+
+ {(user?.name || user?.email || 'U').charAt(0).toUpperCase()}
+
+
+
+
+ );
+ }
+
+ if (type === 'sql-query') {
+ const hasSQL = content && content.trim().length > 0;
+ const isValid = analysisInfo?.isValid !== false; // Default to true if not specified
+
+ return (
+
+
+
+
+ QW
+
+
+
+
+
+
+
+
+ {hasSQL ? 'Generated SQL Query' : 'Query Analysis'}
+
+
+
+ {hasSQL && (
+
+ )}
+
+ {!isValid && (
+
+ {analysisInfo?.explanation && (
+
+
Explanation:
+
{analysisInfo.explanation}
+
+ )}
+ {analysisInfo?.missing && (
+
+
Missing Information:
+
{analysisInfo.missing}
+
+ )}
+ {analysisInfo?.ambiguities && (
+
+
Ambiguities:
+
{analysisInfo.ambiguities}
+
+ )}
+
+ )}
+
+
+
+
+
+ );
+ }
+
+ if (type === 'query-result') {
+ return (
+
+
+
+
+ QW
+
+
+
+
+
+
+
+ Query Results
+
+ {queryData?.length || 0} rows
+
+
+ {queryData && queryData.length > 0 && (
+
+
+
+
+
+ {Object.keys(queryData[0]).map((column) => (
+
+ {column}
+
+ ))}
+
+
+
+ {queryData.map((row, index) => (
+
+ {Object.values(row).map((value: any, cellIndex) => (
+
+ {String(value)}
+
+ ))}
+
+ ))}
+
+
+
+
+ )}
+
+
+
+
+
+ );
+ }
+
+ if (type === 'ai') {
+ return (
+
+ );
+ }
+
+ if (type === 'ai-steps') {
+ return (
+
+
+
+
+ QW
+
+
+
+
+
+
+ {steps?.map((step, index) => (
+
+
+ {step.icon === 'search' && }
+ {step.icon === 'database' && }
+ {step.icon === 'code' && }
+ {step.icon === 'message' && }
+
+ {step.text}
+
+ ))}
+ {progress !== undefined && (
+
+
+
{progress}% complete
+
+ )}
+
+
+
+
+
+
+ );
+ }
+
+ return null;
+};
+
+export default ChatMessage;
diff --git a/app/src/components/chat/QueryInput.tsx b/app/src/components/chat/QueryInput.tsx
new file mode 100644
index 00000000..670dd20b
--- /dev/null
+++ b/app/src/components/chat/QueryInput.tsx
@@ -0,0 +1,53 @@
+import React, { useState } from 'react';
+import { Button } from "@/components/ui/button";
+import { Textarea } from "@/components/ui/textarea";
+import { Send } from "lucide-react";
+
+interface QueryInputProps {
+ onSubmit: (query: string) => void;
+ placeholder?: string;
+ disabled?: boolean;
+}
+
+const QueryInput = ({ onSubmit, placeholder = "Ask me anything about your database...", disabled = false }: QueryInputProps) => {
+ const [query, setQuery] = useState('');
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (query.trim() && !disabled) {
+ onSubmit(query.trim());
+ setQuery('');
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default QueryInput;
diff --git a/app/src/components/layout/Header.tsx b/app/src/components/layout/Header.tsx
new file mode 100644
index 00000000..bfd2fffa
--- /dev/null
+++ b/app/src/components/layout/Header.tsx
@@ -0,0 +1,107 @@
+import { useState, useEffect } from "react";
+import { ChevronDown, Star } from "lucide-react";
+import { Button } from "@/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+
+interface HeaderProps {
+ onConnectDatabase: () => void;
+ onUploadSchema: () => void;
+}
+
+const Header = ({ onConnectDatabase, onUploadSchema }: HeaderProps) => {
+ const [githubStars, setGithubStars] = useState('-');
+
+ useEffect(() => {
+ const controller = new AbortController();
+
+ fetch('https://api.github.com/repos/FalkorDB/QueryWeaver', {
+ signal: controller.signal,
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`GitHub API responded with status ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (typeof data.stargazers_count === "number") {
+ setGithubStars(data.stargazers_count.toLocaleString());
+ }
+ })
+ .catch(error => {
+ if (error.name !== 'AbortError') {
+ console.warn('Failed to fetch GitHub stars:', error);
+ }
+ });
+
+ return () => controller.abort();
+ }, []);
+
+ return (
+
+
+ {/* Database Selector */}
+
+
+
+ Select Database
+
+
+
+
+
+ No databases connected
+
+
+
+
+ {/* Upload Schema */}
+
+ e.preventDefault()}
+ >
+ Upload Schema
+
+
+
+
+ {/* Connect Database Button */}
+
+ Connect Database
+
+
+
+ {/* GitHub Stars Link */}
+
+
+
+
+
+ {githubStars}
+
+
+ );
+};
+
+export default Header;
\ No newline at end of file
diff --git a/app/src/components/layout/Sidebar.tsx b/app/src/components/layout/Sidebar.tsx
new file mode 100644
index 00000000..2a74c46e
--- /dev/null
+++ b/app/src/components/layout/Sidebar.tsx
@@ -0,0 +1,135 @@
+import React from 'react';
+import { useIsMobile } from '@/hooks/use-mobile';
+import { Link } from 'react-router-dom';
+import {
+ PanelLeft,
+ BookOpen,
+ LifeBuoy,
+ Waypoints,
+} from 'lucide-react';
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from '@/components/ui/tooltip';
+import { Separator } from '@/components/ui/separator';
+import { cn } from "@/lib/utils";
+import ThemeToggle from '@/components/ui/theme-toggle';
+
+interface SidebarProps {
+ className?: string;
+ onSchemaClick?: () => void;
+ isSchemaOpen?: boolean;
+ isCollapsed?: boolean;
+ onToggleCollapse?: () => void;
+}
+
+const SidebarIcon = ({ icon: Icon, label, active, onClick, href, testId }: {
+ icon: React.ElementType,
+ label: string,
+ active?: boolean,
+ onClick?: () => void,
+ href?: string,
+ testId?: string
+}) => (
+
+
+
+ {onClick ? (
+
+
+ {label}
+
+ ) : href ? (
+
+
+ {label}
+
+ ) : (
+
+
+ {label}
+
+ )}
+
+ {label}
+
+
+);
+
+
+const Sidebar = ({ className, onSchemaClick, isSchemaOpen, isCollapsed = false, onToggleCollapse }: SidebarProps) => {
+ const isMobile = useIsMobile();
+ return (
+ <>
+
+
+ {isMobile && (
+
+
+ Toggle Sidebar
+
+ )}
+
+ {/* */}
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+ >
+ );
+};
+
+export default Sidebar;
\ No newline at end of file
diff --git a/app/src/components/modals/AuthModal.tsx b/app/src/components/modals/AuthModal.tsx
new file mode 100644
index 00000000..950cf8cd
--- /dev/null
+++ b/app/src/components/modals/AuthModal.tsx
@@ -0,0 +1,93 @@
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { Github } from "lucide-react";
+import { useToast } from "@/components/ui/use-toast";
+import { AuthService } from "@/services/auth";
+
+interface AuthModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+const AuthModal = ({ open, onOpenChange }: AuthModalProps) => {
+ const { toast } = useToast();
+
+ const handleGoogleSignIn = async () => {
+ try {
+ // Redirect to Google OAuth
+ await AuthService.loginWithGoogle();
+ } catch (error) {
+ toast({
+ title: "Authentication Error",
+ description: error instanceof Error ? error.message : "Failed to sign in with Google",
+ variant: "destructive",
+ });
+ }
+ };
+
+ const handleGithubSignIn = async () => {
+ try {
+ // Redirect to GitHub OAuth
+ await AuthService.loginWithGithub();
+ } catch (error) {
+ toast({
+ title: "Authentication Error",
+ description: error instanceof Error ? error.message : "Failed to sign in with GitHub",
+ variant: "destructive",
+ });
+ }
+ };
+
+ return (
+
+
+
+
+ Welcome to QueryWeaver
+
+
+ Sign in to save your databases and queries
+
+
+
+
+ {/* OAuth buttons - Try to use them, gracefully fall back if not configured */}
+
+
+
+
+
+
+
+ Sign in with Google
+
+
+
+
+ Sign in with GitHub
+
+
+
+
+ );
+};
+
+export default AuthModal;
\ No newline at end of file
diff --git a/app/src/components/modals/DatabaseModal.tsx b/app/src/components/modals/DatabaseModal.tsx
new file mode 100644
index 00000000..e02e6e3d
--- /dev/null
+++ b/app/src/components/modals/DatabaseModal.tsx
@@ -0,0 +1,408 @@
+import { useState } from "react";
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { Input } from "@/components/ui/input";
+import { Label } from "@/components/ui/label";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { useDatabase } from "@/contexts/DatabaseContext";
+import { useToast } from "@/components/ui/use-toast";
+import { Loader2, CheckCircle2, XCircle } from "lucide-react";
+import { buildApiUrl, API_CONFIG } from "@/config/api";
+
+interface DatabaseModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+interface ConnectionStep {
+ message: string;
+ status: 'pending' | 'success' | 'error';
+}
+
+const DatabaseModal = ({ open, onOpenChange }: DatabaseModalProps) => {
+ const [connectionMode, setConnectionMode] = useState<'url' | 'manual'>('url');
+ const [selectedDatabase, setSelectedDatabase] = useState("");
+ const [connectionUrl, setConnectionUrl] = useState("");
+ const [host, setHost] = useState("localhost");
+ const [port, setPort] = useState("");
+ const [database, setDatabase] = useState("");
+ const [username, setUsername] = useState("");
+ const [password, setPassword] = useState("");
+ const [isConnecting, setIsConnecting] = useState(false);
+ const [connectionSteps, setConnectionSteps] = useState([]);
+ const { refreshGraphs } = useDatabase();
+ const { toast } = useToast();
+
+ const addStep = (message: string, status: 'pending' | 'success' | 'error' = 'pending') => {
+ setConnectionSteps(prev => {
+ // If adding a new pending step, mark the previous pending step as success
+ if (status === 'pending' && prev.length > 0) {
+ const lastStep = prev[prev.length - 1];
+ if (lastStep.status === 'pending') {
+ const updated = [...prev];
+ updated[updated.length - 1] = { ...lastStep, status: 'success' };
+ return [...updated, { message, status }];
+ }
+ }
+
+ // If updating status (success/error), update the last pending step instead of adding new
+ if (status !== 'pending' && prev.length > 0) {
+ const lastStep = prev[prev.length - 1];
+ if (lastStep.status === 'pending') {
+ const updated = [...prev];
+ updated[updated.length - 1] = { ...lastStep, status };
+ return updated;
+ }
+ }
+
+ // Default: just add the new step
+ return [...prev, { message, status }];
+ });
+ };
+
+ const handleConnect = async () => {
+ // Validate based on connection mode
+ if (connectionMode === 'url') {
+ if (!connectionUrl || !selectedDatabase) {
+ toast({
+ title: "Missing Information",
+ description: "Please select database type and enter connection URL",
+ variant: "destructive",
+ });
+ return;
+ }
+ } else {
+ if (!selectedDatabase || !host || !port || !database || !username) {
+ toast({
+ title: "Missing Information",
+ description: "Please fill in all required fields",
+ variant: "destructive",
+ });
+ return;
+ }
+ }
+
+ setIsConnecting(true);
+ setConnectionSteps([]); // Clear previous steps
+
+ try {
+ // Build the connection URL
+ let dbUrl = connectionUrl;
+ if (connectionMode === 'manual') {
+ const protocol = selectedDatabase === 'mysql' ? 'mysql' : 'postgresql';
+ const builtUrl = new URL(`${protocol}://${host}:${port}/${database}`);
+ builtUrl.username = username;
+ builtUrl.password = password;
+ dbUrl = builtUrl.toString();
+ }
+
+ // Make streaming request
+ const response = await fetch(buildApiUrl('/database'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ url: dbUrl }),
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ throw new Error(`Network response was not ok (${response.status})`);
+ }
+
+ // Process streaming response
+ if (!response.body) {
+ throw new Error('Streaming response has no body');
+ }
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = '';
+ const delimiter = API_CONFIG.STREAM_BOUNDARY;
+
+ const processChunk = (text: string) => {
+ if (!text || !text.trim()) return;
+
+ let obj: any = null;
+ try {
+ obj = JSON.parse(text);
+ } catch (e) {
+ console.error('Failed to parse chunk as JSON', e, text);
+ return;
+ }
+
+ if (obj.type === 'reasoning_step') {
+ // Show incremental step
+ addStep(obj.message || 'Working...', 'pending');
+ } else if (obj.type === 'final_result') {
+ // Mark last step as success/error and finish
+ addStep(obj.message || 'Completed', obj.success ? 'success' : 'error');
+ setIsConnecting(false);
+
+ if (obj.success) {
+ toast({
+ title: "Connected Successfully",
+ description: "Database connection established!",
+ });
+ setTimeout(async () => {
+ await refreshGraphs();
+ onOpenChange(false);
+ // Reset form
+ setConnectionMode('url');
+ setSelectedDatabase("");
+ setConnectionUrl("");
+ setHost("localhost");
+ setPort("");
+ setDatabase("");
+ setUsername("");
+ setPassword("");
+ setConnectionSteps([]);
+ }, 1000);
+ } else {
+ toast({
+ title: "Connection Failed",
+ description: obj.message || 'Unknown error',
+ variant: "destructive",
+ });
+ }
+ } else if (obj.type === 'error') {
+ addStep(obj.message || 'Error', 'error');
+ setIsConnecting(false);
+ toast({
+ title: "Connection Error",
+ description: obj.message || 'Unknown error',
+ variant: "destructive",
+ });
+ }
+ };
+
+ const pump = async (): Promise => {
+ const { done, value } = await reader.read();
+
+ if (done) {
+ if (buffer.length > 0) {
+ processChunk(buffer);
+ }
+ setIsConnecting(false);
+ return;
+ }
+
+ buffer += decoder.decode(value, { stream: true });
+ const parts = buffer.split(delimiter);
+ // Last piece is possibly incomplete
+ buffer = parts.pop() || '';
+ for (const part of parts) {
+ processChunk(part);
+ }
+
+ return pump();
+ };
+
+ await pump();
+
+ } catch (error) {
+ setIsConnecting(false);
+ toast({
+ title: "Connection Failed",
+ description: error instanceof Error ? error.message : "Failed to connect to database",
+ variant: "destructive",
+ });
+ }
+ };
+
+ return (
+
+
+
+
+ Connect to Database
+
+
+ Connect to PostgreSQL or MySQL database using a connection URL or manual entry
+
+
+
+
+ {/* Database Type Selection */}
+
+
+ Database Type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Connection Mode Toggle */}
+ {selectedDatabase && (
+
+ setConnectionMode('url')}
+ data-testid="connection-mode-url"
+ >
+ Connection URL
+
+ setConnectionMode('manual')}
+ data-testid="connection-mode-manual"
+ >
+ Manual Entry
+
+
+ )}
+
+ {selectedDatabase && connectionMode === 'url' && (
+
+
+ Connection URL
+
+
setConnectionUrl(e.target.value)}
+ className="bg-muted border-border font-mono text-sm"
+ />
+
+ Enter your database connection string
+
+
+ )}
+
+ {selectedDatabase && connectionMode === 'manual' && (
+ <>
+
+ Host
+ setHost(e.target.value)}
+ className="bg-muted border-border"
+ />
+
+
+
+ Port
+ setPort(e.target.value)}
+ className="bg-muted border-border"
+ />
+
+
+
+ Database Name
+ setDatabase(e.target.value)}
+ className="bg-muted border-border"
+ />
+
+
+
+ Username
+ setUsername(e.target.value)}
+ className="bg-muted border-border"
+ />
+
+
+
+ Password
+ setPassword(e.target.value)}
+ className="bg-muted border-border"
+ />
+
+ >
+ )}
+
+ {/* Connection Progress Steps */}
+ {connectionSteps.length > 0 && (
+
+ {connectionSteps.map((step, index) => (
+
+ {step.status === 'pending' && (
+
+ )}
+ {step.status === 'success' && (
+
+ )}
+ {step.status === 'error' && (
+
+ )}
+
+ {step.message}
+
+
+ ))}
+
+ )}
+
+
+
+ onOpenChange(false)}
+ disabled={isConnecting}
+ data-testid="cancel-database-button"
+ >
+ Cancel
+
+
+ {isConnecting ? "Connecting..." : "Connect"}
+
+
+
+
+ );
+};
+
+export default DatabaseModal;
\ No newline at end of file
diff --git a/app/src/components/modals/DeleteDatabaseModal.tsx b/app/src/components/modals/DeleteDatabaseModal.tsx
new file mode 100644
index 00000000..f82bcf8a
--- /dev/null
+++ b/app/src/components/modals/DeleteDatabaseModal.tsx
@@ -0,0 +1,91 @@
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { AlertTriangle } from "lucide-react";
+
+interface DeleteDatabaseModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ databaseName: string;
+ onConfirm: () => void;
+ isDemo?: boolean;
+}
+
+const DeleteDatabaseModal = ({
+ open,
+ onOpenChange,
+ databaseName,
+ onConfirm,
+ isDemo = false,
+}: DeleteDatabaseModalProps) => {
+ const handleConfirm = () => {
+ onConfirm();
+ onOpenChange(false);
+ };
+
+ return (
+
+
+
+
+
+ Delete Database
+
+
+ {isDemo ? (
+
+
Demo databases cannot be deleted.
+
+ Demo databases are read-only and shared across all users.
+ Only databases you've created can be deleted.
+
+
+ ) : (
+
+
+ Are you sure you want to delete "{databaseName}"?
+
+
+ This action cannot be undone. All data and schema information
+ for this database will be permanently removed.
+
+
+ )}
+
+
+
+
+ onOpenChange(false)}
+ className="bg-gray-800 border-gray-600 text-gray-300 hover:bg-gray-700"
+ data-testid="delete-modal-cancel"
+ >
+ Cancel
+
+ {!isDemo && (
+
+ Delete Database
+
+ )}
+
+
+
+ );
+};
+
+export default DeleteDatabaseModal;
diff --git a/app/src/components/modals/LoginModal.tsx b/app/src/components/modals/LoginModal.tsx
new file mode 100644
index 00000000..65c8a389
--- /dev/null
+++ b/app/src/components/modals/LoginModal.tsx
@@ -0,0 +1,98 @@
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { buildApiUrl, API_CONFIG } from "@/config/api";
+
+interface LoginModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ canClose?: boolean; // Whether user can close the modal (false for required login)
+}
+
+const LoginModal = ({ open, onOpenChange, canClose = true }: LoginModalProps) => {
+ const handleGoogleLogin = () => {
+ window.location.href = buildApiUrl(API_CONFIG.ENDPOINTS.LOGIN_GOOGLE);
+ };
+
+ const handleGithubLogin = () => {
+ window.location.href = buildApiUrl(API_CONFIG.ENDPOINTS.LOGIN_GITHUB);
+ };
+
+ return (
+
+ {
+ if (!canClose) {
+ e.preventDefault();
+ }
+ }}
+ onEscapeKeyDown={(e) => {
+ if (!canClose) {
+ e.preventDefault();
+ }
+ }}
+ data-testid="login-modal"
+ >
+
+
+ Welcome to QueryWeaver
+
+
+ Sign in to access your databases and start querying
+
+
+
+
+
+
+
+
+
+
+
+ Continue with Google
+
+
+
+
+
+
+ Continue with GitHub
+
+
+
+ {canClose && (
+
+
By signing in, you agree to our Terms of Service and Privacy Policy
+
+ )}
+
+
+ );
+};
+
+export default LoginModal;
diff --git a/app/src/components/modals/TokensModal.tsx b/app/src/components/modals/TokensModal.tsx
new file mode 100644
index 00000000..46d66aa7
--- /dev/null
+++ b/app/src/components/modals/TokensModal.tsx
@@ -0,0 +1,304 @@
+import React, { useState, useEffect } from 'react';
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from '@/components/ui/dialog';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from '@/components/ui/table';
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from '@/components/ui/alert-dialog';
+import { Alert, AlertDescription } from '@/components/ui/alert';
+import { useToast } from '@/components/ui/use-toast';
+import { TokenService, type Token } from '@/services/tokens';
+import { Copy, Eye, EyeOff, Trash2, AlertCircle } from 'lucide-react';
+
+interface TokensModalProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+const TokensModal: React.FC = ({ open, onOpenChange }) => {
+ const [tokens, setTokens] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [generating, setGenerating] = useState(false);
+ const [newToken, setNewToken] = useState(null);
+ const [showToken, setShowToken] = useState(false);
+ const [deleteTokenId, setDeleteTokenId] = useState(null);
+ const [deleting, setDeleting] = useState(false);
+ const { toast } = useToast();
+
+ const loadTokens = async () => {
+ try {
+ setLoading(true);
+ const data = await TokenService.listTokens();
+ setTokens(data.tokens);
+ } catch (error) {
+ console.error('Error loading tokens:', error);
+ toast({
+ title: 'Error',
+ description: 'Failed to load tokens. Please try again.',
+ variant: 'destructive',
+ });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ if (open) {
+ loadTokens();
+ setNewToken(null);
+ setShowToken(false);
+ }
+ }, [open]);
+
+ const handleGenerateToken = async () => {
+ try {
+ setGenerating(true);
+ const token = await TokenService.generateToken();
+ setNewToken(token.token_id);
+ setShowToken(false);
+ await loadTokens();
+ toast({
+ title: 'Success',
+ description: 'Token generated successfully',
+ });
+ } catch (error) {
+ console.error('Error generating token:', error);
+ toast({
+ title: 'Error',
+ description: 'Failed to generate token. Please try again.',
+ variant: 'destructive',
+ });
+ } finally {
+ setGenerating(false);
+ }
+ };
+
+ const handleCopyToken = async () => {
+ if (!newToken) return;
+ try {
+ await navigator.clipboard.writeText(newToken);
+ toast({
+ title: 'Copied!',
+ description: 'Token copied to clipboard',
+ });
+ } catch (error) {
+ console.error('Error copying token:', error);
+ toast({
+ title: 'Copy failed',
+ description: 'We could not copy the token. Please copy it manually.',
+ variant: 'destructive',
+ });
+ }
+ };
+
+ const handleDeleteToken = async () => {
+ if (!deleteTokenId) return;
+
+ try {
+ setDeleting(true);
+ await TokenService.deleteToken(deleteTokenId);
+ await loadTokens();
+ setDeleteTokenId(null);
+ toast({
+ title: 'Success',
+ description: 'Token deleted successfully',
+ });
+ } catch (error) {
+ console.error('Error deleting token:', error);
+ toast({
+ title: 'Error',
+ description: 'Failed to delete token. Please try again.',
+ variant: 'destructive',
+ });
+ } finally {
+ setDeleting(false);
+ }
+ };
+
+ const formatDate = (timestamp: number): string => {
+ if (!timestamp) return '';
+
+ // Convert to milliseconds if timestamp is in seconds
+ const ms = timestamp < 1e12 ? timestamp * 1000 : timestamp;
+ const date = new Date(ms);
+
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {
+ hour: '2-digit',
+ minute: '2-digit'
+ });
+ };
+
+ return (
+ <>
+
+
+
+ API Tokens
+
+ API tokens allow you to authenticate with the QueryWeaver API without using OAuth.
+ Keep your tokens secure and don't share them publicly.
+
+
+
+
+ {/* Generate Token Button */}
+
+
+ {generating ? 'Generating...' : 'Generate New Token'}
+
+
+
+ {/* New Token Display */}
+ {newToken && (
+
+
+
+ Token Generated Successfully!
+
+ Important: This is the only time you'll see this token. Copy it now and store it securely.
+
+
+
+
+ setShowToken(!showToken)}
+ className="bg-gray-700 border-gray-600 text-gray-200 hover:bg-gray-600 flex-shrink-0"
+ data-testid="toggle-token-visibility"
+ >
+ {showToken ? : }
+
+
+
+
+ Copy
+
+
+
+
+ )}
+
+ {/* Tokens List */}
+
+
Your Tokens
+ {loading ? (
+
Loading tokens...
+ ) : tokens.length === 0 ? (
+
You don't have any API tokens yet.
+ ) : (
+
+
+
+
+ Token
+ Created
+ Actions
+
+
+
+ {tokens.map((token) => (
+
+
+ ****{token.token_id}
+
+
+ {formatDate(token.created_at)}
+
+
+ setDeleteTokenId(token.token_id)}
+ className="bg-red-600 hover:bg-red-700 h-8 px-2 sm:px-3"
+ data-testid={`delete-token-btn-${token.token_id}`}
+ >
+
+ Delete
+
+
+
+ ))}
+
+
+
+ )}
+
+
+
+
+
+ {/* Delete Confirmation Dialog */}
+ !open && setDeleteTokenId(null)}>
+
+
+ Delete Token
+
+ Are you sure you want to delete this token? This action cannot be undone.
+
+
+ Token ending in: {deleteTokenId?.slice(-6)}
+
+
+
+
+ Cancel
+
+
+ {deleting ? 'Deleting...' : 'Delete Token'}
+
+
+
+
+ >
+ );
+};
+
+export default TokensModal;
diff --git a/app/src/components/schema/SchemaViewer.tsx b/app/src/components/schema/SchemaViewer.tsx
new file mode 100644
index 00000000..fb5fb575
--- /dev/null
+++ b/app/src/components/schema/SchemaViewer.tsx
@@ -0,0 +1,532 @@
+import { useEffect, useRef, useState, useMemo } from 'react';
+import ForceGraph2D from 'react-force-graph-2d';
+import { forceCollide, forceCenter, forceManyBody } from 'd3-force';
+import { ZoomIn, ZoomOut, Locate, X, GripVertical } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { useDatabase } from '@/contexts/DatabaseContext';
+import { DatabaseService } from '@/services/database';
+import { useToast } from '@/components/ui/use-toast';
+
+interface SchemaNode {
+ id?: string;
+ name: string;
+ columns: Array;
+ height?: number;
+ x?: number;
+ y?: number;
+}
+
+interface SchemaLink {
+ source: string | SchemaNode;
+ target: string | SchemaNode;
+}
+
+interface SchemaData {
+ nodes: SchemaNode[];
+ links: SchemaLink[];
+}
+
+interface SchemaViewerProps {
+ isOpen: boolean;
+ onClose: () => void;
+ onWidthChange?: (width: number) => void;
+ sidebarWidth?: number;
+}
+
+const SchemaViewer = ({ isOpen, onClose, onWidthChange, sidebarWidth = 64 }: SchemaViewerProps) => {
+ const containerRef = useRef(null);
+ const graphRef = useRef(null);
+ const resizeRef = useRef(null);
+ const [schemaData, setSchemaData] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const { selectedGraph } = useDatabase();
+ const { toast } = useToast();
+
+ // Track if forces have been configured to prevent reconfiguration on resize
+ const forcesConfiguredRef = useRef(false);
+
+ // Track current theme for canvas colors
+ const [theme, setTheme] = useState(() => {
+ return document.documentElement.getAttribute('data-theme') || 'dark';
+ });
+
+ // Listen for theme changes
+ useEffect(() => {
+ const observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
+ if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
+ const newTheme = document.documentElement.getAttribute('data-theme') || 'dark';
+ setTheme(newTheme);
+ // Force graph redraw when theme changes
+ if (graphRef.current) {
+ graphRef.current.refresh();
+ }
+ }
+ });
+ });
+
+ observer.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['data-theme']
+ });
+
+ return () => observer.disconnect();
+ }, []);
+
+ const NODE_WIDTH = 160;
+ const MIN_WIDTH = 300;
+ const MAX_WIDTH_PERCENT = 0.6;
+ const DEFAULT_WIDTH_PERCENT = 0.5;
+
+ // Force configuration constants (from FalkorDB browser, adjusted for smaller graphs)
+ const REFERENCE_NODE_COUNT = 2000;
+ const BASE_LINK_DISTANCE = 20;
+ const BASE_LINK_STRENGTH = 0.5;
+ const BASE_CHARGE_STRENGTH = -1;
+ const BASE_CENTER_STRENGTH = 0.1;
+
+ // Scaling factors for small graphs (inverse scaling)
+ const MIN_LINK_DISTANCE = 80; // Minimum distance for small graphs
+ const MAX_LINK_DISTANCE = 300; // Maximum distance for very small graphs
+ const MIN_CHARGE_STRENGTH = -50; // Minimum charge for small graphs
+ const MAX_CHARGE_STRENGTH = -800; // Maximum charge for very small graphs
+
+ const [width, setWidth] = useState(() => {
+ const initialWidth = Math.floor(window.innerWidth * DEFAULT_WIDTH_PERCENT);
+ return initialWidth;
+ });
+ const [isResizing, setIsResizing] = useState(false);
+
+ // Notify parent of width changes
+ useEffect(() => {
+ if (onWidthChange) {
+ onWidthChange(width);
+ }
+ }, [width, onWidthChange]);
+
+ useEffect(() => {
+ if (isOpen && selectedGraph) {
+ loadSchemaData();
+ // Reset forces configured flag when loading new data
+ forcesConfiguredRef.current = false;
+ }
+ }, [isOpen, selectedGraph]);
+
+ // Configure forces when schema data changes
+ useEffect(() => {
+ if (!schemaData?.nodes?.length || !graphRef.current) return;
+
+ // Skip if forces already configured (prevents reconfiguration on resize)
+ if (forcesConfiguredRef.current) {
+ console.log('Forces already configured, skipping reconfiguration');
+ return;
+ }
+
+ const graph = graphRef.current;
+
+ // Wait for d3 to be available - it's not immediately accessible on mount
+ const configureForces = () => {
+ const d3 = graph.d3Force;
+
+ if (!d3) {
+ console.log('d3 not yet available, retrying...');
+ setTimeout(configureForces, 100);
+ return;
+ }
+
+ const nodeCount = schemaData.nodes.length;
+
+ console.log(`Configuring forces for ${nodeCount} nodes`);
+
+ // For small graphs, we need STRONGER forces, not weaker
+ // Inverse scaling: fewer nodes = stronger repulsion and larger distances
+ let linkDistance: number;
+ let chargeStrength: number;
+
+ if (nodeCount < 50) {
+ // Small graphs: use strong forces with inverse scaling
+ const smallGraphScale = Math.max(0.1, Math.min(1, nodeCount / 50));
+ linkDistance = MAX_LINK_DISTANCE - (MAX_LINK_DISTANCE - MIN_LINK_DISTANCE) * smallGraphScale;
+ chargeStrength = MAX_CHARGE_STRENGTH - (MAX_CHARGE_STRENGTH - MIN_CHARGE_STRENGTH) * smallGraphScale;
+ } else {
+ // Large graphs: use the original FalkorDB scaling
+ const scale = Math.sqrt(nodeCount / REFERENCE_NODE_COUNT);
+ linkDistance = Math.max(
+ Math.min(BASE_LINK_DISTANCE * scale, 120),
+ BASE_LINK_DISTANCE
+ );
+ chargeStrength = Math.min(
+ Math.max(BASE_CHARGE_STRENGTH * scale, -80),
+ BASE_CHARGE_STRENGTH
+ );
+ }
+
+ console.log(`Link distance: ${linkDistance}`);
+ console.log(`Charge strength: ${chargeStrength}`);
+
+ // Configure all forces
+ d3('link')
+ ?.id((d: SchemaNode) => d.name)
+ .distance(linkDistance)
+ .strength(BASE_LINK_STRENGTH);
+
+ // Use actual node width for collision detection to prevent overlap
+ d3('collision', forceCollide(NODE_WIDTH / 2 + 20).strength(1.0).iterations(2));
+ d3('center', forceCenter(0, 0).strength(BASE_CENTER_STRENGTH));
+ d3('charge', forceManyBody().strength(chargeStrength));
+
+ console.log('Forces configured, reheating simulation');
+ graph.d3ReheatSimulation();
+
+ // Mark forces as configured to prevent reconfiguration
+ forcesConfiguredRef.current = true;
+ };
+
+ configureForces();
+ }, [schemaData]); // Handle resize
+ useEffect(() => {
+ const handleMouseMove = (e: MouseEvent) => {
+ if (!isResizing) return;
+
+ const newWidth = e.clientX - sidebarWidth;
+ const maxWidth = Math.floor(window.innerWidth * MAX_WIDTH_PERCENT);
+
+ if (newWidth >= MIN_WIDTH && newWidth <= maxWidth) {
+ setWidth(newWidth);
+ }
+ };
+
+ const handleMouseUp = () => {
+ setIsResizing(false);
+ };
+
+ if (isResizing) {
+ document.addEventListener('mousemove', handleMouseMove);
+ document.addEventListener('mouseup', handleMouseUp);
+ document.body.style.cursor = 'ew-resize';
+ document.body.style.userSelect = 'none';
+ }
+
+ return () => {
+ document.removeEventListener('mousemove', handleMouseMove);
+ document.removeEventListener('mouseup', handleMouseUp);
+ document.body.style.cursor = '';
+ document.body.style.userSelect = '';
+ };
+ }, [isResizing, sidebarWidth]);
+
+ const loadSchemaData = async () => {
+ if (!selectedGraph) return;
+
+ setLoading(true);
+ try {
+ const data = await DatabaseService.getGraphData(selectedGraph.id);
+ console.log('Schema data received:', data);
+ console.log('Nodes:', data.nodes);
+ console.log('Links:', data.links);
+
+ setSchemaData(data);
+ } catch (error) {
+ console.error('Failed to load schema:', error);
+ toast({
+ title: 'Failed to Load Schema',
+ description: error instanceof Error ? error.message : 'Unknown error occurred',
+ variant: 'destructive',
+ });
+ setSchemaData({ nodes: [], links: [] });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleZoomIn = () => {
+ if (graphRef.current) {
+ const currentZoom = graphRef.current.zoom();
+ graphRef.current.zoom(currentZoom * 1.1, 200);
+ }
+ };
+
+ const handleZoomOut = () => {
+ if (graphRef.current) {
+ const currentZoom = graphRef.current.zoom();
+ graphRef.current.zoom(currentZoom * 0.9, 200);
+ }
+ };
+
+ const handleCenter = () => {
+ if (graphRef.current && containerRef.current) {
+ const rect = containerRef.current.getBoundingClientRect();
+ const minDimension = Math.min(rect.width, rect.height);
+ const padding = minDimension * 0.1;
+ graphRef.current.zoomToFit(500, padding);
+ }
+ };
+
+ const nodeCanvasObject = (node: any, ctx: CanvasRenderingContext2D) => {
+ const lineHeight = 14;
+ const padding = 8;
+ const headerHeight = 20;
+ const fontSize = 12;
+
+ // Theme-aware colors
+ const isLight = theme === 'light';
+ const textColor = isLight ? '#111' : '#f5f5f5';
+ const fillColor = isLight ? '#ffffff' : '#1f2937';
+ const strokeColor = isLight ? '#d1d5db' : '#374151';
+ const columnTextColor = isLight ? '#111' : '#e5e7eb';
+ const typeTextColor = isLight ? '#6b7280' : '#9ca3af';
+
+ if (!node.height) {
+ node.height = headerHeight + (node.columns?.length || 0) * lineHeight + padding * 2;
+ }
+
+ ctx.fillStyle = fillColor;
+ ctx.strokeStyle = strokeColor;
+ ctx.lineWidth = 1;
+ ctx.fillRect(
+ node.x - NODE_WIDTH / 2,
+ node.y - node.height / 2,
+ NODE_WIDTH,
+ node.height
+ );
+ ctx.strokeRect(
+ node.x - NODE_WIDTH / 2,
+ node.y - node.height / 2,
+ NODE_WIDTH,
+ node.height
+ );
+
+ ctx.fillStyle = textColor;
+ ctx.font = `bold ${fontSize}px Arial`;
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+ ctx.fillText(
+ node.name,
+ node.x,
+ node.y - node.height / 2 + headerHeight / 2 + padding / 2
+ );
+
+ ctx.font = `${fontSize - 2}px Arial`;
+ ctx.textAlign = 'left';
+ const startX = node.x - NODE_WIDTH / 2 + padding;
+ let colY = node.y - node.height / 2 + headerHeight + padding;
+ (node.columns || []).forEach((col: any) => {
+ let name = col;
+ let type = null;
+ if (typeof col === 'object') {
+ name = col.name || '';
+ type = col.type || col.dataType || null;
+ }
+
+ ctx.textAlign = 'left';
+ ctx.fillStyle = columnTextColor;
+ ctx.fillText(name, startX, colY);
+
+ if (type) {
+ ctx.fillStyle = typeTextColor;
+ const nameWidth = ctx.measureText(name).width;
+ const available = NODE_WIDTH - padding * 2 - nameWidth - 8;
+ let typeText = String(type);
+ if (available > 0) {
+ if (ctx.measureText(typeText).width > available) {
+ while (
+ typeText.length > 0 &&
+ ctx.measureText(typeText + '…').width > available
+ ) {
+ typeText = typeText.slice(0, -1);
+ }
+ typeText = typeText + '…';
+ }
+ ctx.textAlign = 'right';
+ ctx.fillText(typeText, node.x + NODE_WIDTH / 2 - padding, colY);
+ }
+ ctx.fillStyle = columnTextColor;
+ ctx.textAlign = 'left';
+ }
+
+ colY += lineHeight;
+ });
+ };
+
+ const nodePointerAreaPaint = (node: any, color: string, ctx: CanvasRenderingContext2D) => {
+ ctx.fillStyle = color;
+ const padding = 5;
+ ctx.fillRect(
+ node.x - NODE_WIDTH / 2 - padding,
+ node.y - node.height / 2 - padding,
+ NODE_WIDTH + padding * 2,
+ node.height + padding * 2
+ );
+ };
+
+ // Memoize graphData to prevent recreation on every render (especially during resize)
+ const memoizedGraphData = useMemo(() => {
+ if (!schemaData) return { nodes: [], links: [] };
+
+ console.log('Schema data received:', schemaData);
+ console.log('Nodes:', schemaData.nodes);
+ console.log('Links:', schemaData.links);
+
+ schemaData.nodes.forEach(node => {
+ console.log('Node:', node.name, 'id:', node.id, 'columns:', node.columns?.length);
+ });
+
+ schemaData.links.forEach(link => {
+ console.log('Link:', link.source, '->', link.target);
+ });
+
+ return {
+ nodes: schemaData.nodes,
+ links: schemaData.links
+ };
+ }, [schemaData]);
+
+ // Get theme-aware colors
+ const getBackgroundColor = () => {
+ return theme === 'light' ? '#ffffff' : '#030712';
+ };
+
+ const getLinkColor = () => {
+ return theme === 'light' ? '#9ca3af' : '#4b5563';
+ };
+
+ if (!isOpen) return null;
+
+ return (
+ <>
+ {/* Mobile overlay backdrop */}
+
+
+ {/* Schema Viewer */}
+ = 768 ? {
+ left: `${sidebarWidth}px`,
+ width: `${width}px`
+ } : {})
+ }}
+ >
+ {/* Header */}
+
+
Database Schema
+
+
+
+
+
+ {/* Controls */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Graph Container */}
+
+ {loading && (
+
+ )}
+ {!loading && schemaData && schemaData.nodes && schemaData.nodes.length > 0 && (
+
+
+
+ )}
+ {!loading && (!schemaData || !schemaData.nodes || schemaData.nodes.length === 0) && (
+
+
+
No schema data available
+
+ {!selectedGraph ? 'Select a database first' : 'This database has no schema data'}
+
+
+
+ )}
+
+
+ {/* Resize Handle */}
+
{
+ e.preventDefault();
+ e.stopPropagation();
+ setIsResizing(true);
+ }}
+ >
+
+
+
+
+
+ >
+ );
+};
+
+export default SchemaViewer;
diff --git a/app/src/components/schema/index.ts b/app/src/components/schema/index.ts
new file mode 100644
index 00000000..f749166a
--- /dev/null
+++ b/app/src/components/schema/index.ts
@@ -0,0 +1,2 @@
+export { default } from './SchemaViewer';
+export { default as SchemaViewer } from './SchemaViewer';
diff --git a/app/src/components/ui/alert-dialog.tsx b/app/src/components/ui/alert-dialog.tsx
new file mode 100644
index 00000000..95f7859c
--- /dev/null
+++ b/app/src/components/ui/alert-dialog.tsx
@@ -0,0 +1,106 @@
+import * as React from "react";
+import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
+
+import { cn } from "@/lib/utils";
+import { buttonVariants } from "@/components/ui/button";
+
+const AlertDialog = AlertDialogPrimitive.Root;
+
+const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
+
+const AlertDialogPortal = AlertDialogPrimitive.Portal;
+
+const AlertDialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
+
+const AlertDialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+));
+AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
+
+const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+AlertDialogHeader.displayName = "AlertDialogHeader";
+
+const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+AlertDialogFooter.displayName = "AlertDialogFooter";
+
+const AlertDialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
+
+const AlertDialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
+
+const AlertDialogAction = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
+
+const AlertDialogCancel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
+
+export {
+ AlertDialog,
+ AlertDialogPortal,
+ AlertDialogOverlay,
+ AlertDialogTrigger,
+ AlertDialogContent,
+ AlertDialogHeader,
+ AlertDialogFooter,
+ AlertDialogTitle,
+ AlertDialogDescription,
+ AlertDialogAction,
+ AlertDialogCancel,
+};
diff --git a/app/src/components/ui/alert.tsx b/app/src/components/ui/alert.tsx
new file mode 100644
index 00000000..610e087a
--- /dev/null
+++ b/app/src/components/ui/alert.tsx
@@ -0,0 +1,43 @@
+import * as React from "react";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const alertVariants = cva(
+ "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
+ {
+ variants: {
+ variant: {
+ default: "bg-background text-foreground",
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
+
+const Alert = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & VariantProps
+>(({ className, variant, ...props }, ref) => (
+
+));
+Alert.displayName = "Alert";
+
+const AlertTitle = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+AlertTitle.displayName = "AlertTitle";
+
+const AlertDescription = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+AlertDescription.displayName = "AlertDescription";
+
+export { Alert, AlertTitle, AlertDescription };
diff --git a/app/src/components/ui/avatar.tsx b/app/src/components/ui/avatar.tsx
new file mode 100644
index 00000000..68d21bbf
--- /dev/null
+++ b/app/src/components/ui/avatar.tsx
@@ -0,0 +1,38 @@
+import * as React from "react";
+import * as AvatarPrimitive from "@radix-ui/react-avatar";
+
+import { cn } from "@/lib/utils";
+
+const Avatar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
+
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/app/src/components/ui/badge.tsx b/app/src/components/ui/badge.tsx
new file mode 100644
index 00000000..0853c441
--- /dev/null
+++ b/app/src/components/ui/badge.tsx
@@ -0,0 +1,29 @@
+import * as React from "react";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const badgeVariants = cva(
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ {
+ variants: {
+ variant: {
+ default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
+ outline: "text-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
+
+export interface BadgeProps extends React.HTMLAttributes, VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return
;
+}
+
+export { Badge, badgeVariants };
diff --git a/app/src/components/ui/button.tsx b/app/src/components/ui/button.tsx
new file mode 100644
index 00000000..cdedd4f4
--- /dev/null
+++ b/app/src/components/ui/button.tsx
@@ -0,0 +1,47 @@
+import * as React from "react";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return ;
+ },
+);
+Button.displayName = "Button";
+
+export { Button, buttonVariants };
diff --git a/app/src/components/ui/card.tsx b/app/src/components/ui/card.tsx
new file mode 100644
index 00000000..95dcbe39
--- /dev/null
+++ b/app/src/components/ui/card.tsx
@@ -0,0 +1,43 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Card = React.forwardRef>(({ className, ...props }, ref) => (
+
+));
+Card.displayName = "Card";
+
+const CardHeader = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+CardHeader.displayName = "CardHeader";
+
+const CardTitle = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+CardTitle.displayName = "CardTitle";
+
+const CardDescription = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+CardDescription.displayName = "CardDescription";
+
+const CardContent = React.forwardRef>(
+ ({ className, ...props }, ref) =>
,
+);
+CardContent.displayName = "CardContent";
+
+const CardFooter = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+CardFooter.displayName = "CardFooter";
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
diff --git a/app/src/components/ui/dialog.tsx b/app/src/components/ui/dialog.tsx
new file mode 100644
index 00000000..17069031
--- /dev/null
+++ b/app/src/components/ui/dialog.tsx
@@ -0,0 +1,95 @@
+import * as React from "react";
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { X } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const Dialog = DialogPrimitive.Root;
+
+const DialogTrigger = DialogPrimitive.Trigger;
+
+const DialogPortal = DialogPrimitive.Portal;
+
+const DialogClose = DialogPrimitive.Close;
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+));
+DialogContent.displayName = DialogPrimitive.Content.displayName;
+
+const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+DialogHeader.displayName = "DialogHeader";
+
+const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => (
+
+);
+DialogFooter.displayName = "DialogFooter";
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogTitle.displayName = DialogPrimitive.Title.displayName;
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DialogDescription.displayName = DialogPrimitive.Description.displayName;
+
+export {
+ Dialog,
+ DialogPortal,
+ DialogOverlay,
+ DialogClose,
+ DialogTrigger,
+ DialogContent,
+ DialogHeader,
+ DialogFooter,
+ DialogTitle,
+ DialogDescription,
+};
diff --git a/app/src/components/ui/dropdown-menu.tsx b/app/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 00000000..ddabcfdd
--- /dev/null
+++ b/app/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,179 @@
+import * as React from "react";
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
+import { Check, ChevronRight, Circle } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const DropdownMenu = DropdownMenuPrimitive.Root;
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group;
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub;
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+));
+DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+));
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, ...props }, ref) => (
+
+));
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+));
+DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+));
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean;
+ }
+>(({ className, inset, ...props }, ref) => (
+
+));
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
+
+const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes) => {
+ return ;
+};
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+};
diff --git a/app/src/components/ui/input.tsx b/app/src/components/ui/input.tsx
new file mode 100644
index 00000000..09700f60
--- /dev/null
+++ b/app/src/components/ui/input.tsx
@@ -0,0 +1,22 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Input = React.forwardRef>(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ );
+ },
+);
+Input.displayName = "Input";
+
+export { Input };
diff --git a/app/src/components/ui/label.tsx b/app/src/components/ui/label.tsx
new file mode 100644
index 00000000..80e30eec
--- /dev/null
+++ b/app/src/components/ui/label.tsx
@@ -0,0 +1,17 @@
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & VariantProps
+>(({ className, ...props }, ref) => (
+
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/app/src/components/ui/loading-spinner.tsx b/app/src/components/ui/loading-spinner.tsx
new file mode 100644
index 00000000..76a8504b
--- /dev/null
+++ b/app/src/components/ui/loading-spinner.tsx
@@ -0,0 +1,26 @@
+import { cn } from "@/lib/utils";
+
+interface LoadingSpinnerProps {
+ className?: string;
+ size?: "sm" | "md" | "lg";
+}
+
+const LoadingSpinner = ({ className, size = "md" }: LoadingSpinnerProps) => {
+ const sizeClasses = {
+ sm: "w-4 h-4",
+ md: "w-6 h-6",
+ lg: "w-8 h-8"
+ };
+
+ return (
+
+ );
+};
+
+export default LoadingSpinner;
\ No newline at end of file
diff --git a/app/src/components/ui/progress.tsx b/app/src/components/ui/progress.tsx
new file mode 100644
index 00000000..f9f131e9
--- /dev/null
+++ b/app/src/components/ui/progress.tsx
@@ -0,0 +1,23 @@
+import * as React from "react";
+import * as ProgressPrimitive from "@radix-ui/react-progress";
+
+import { cn } from "@/lib/utils";
+
+const Progress = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, value, ...props }, ref) => (
+
+
+
+));
+Progress.displayName = ProgressPrimitive.Root.displayName;
+
+export { Progress };
diff --git a/app/src/components/ui/select.tsx b/app/src/components/ui/select.tsx
new file mode 100644
index 00000000..6f252546
--- /dev/null
+++ b/app/src/components/ui/select.tsx
@@ -0,0 +1,143 @@
+import * as React from "react";
+import * as SelectPrimitive from "@radix-ui/react-select";
+import { Check, ChevronDown, ChevronUp } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const Select = SelectPrimitive.Root;
+
+const SelectGroup = SelectPrimitive.Group;
+
+const SelectValue = SelectPrimitive.Value;
+
+const SelectTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+ span]:line-clamp-1",
+ className,
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+
+));
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
+
+const SelectScrollUpButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
+
+const SelectScrollDownButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
+
+const SelectContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, position = "popper", ...props }, ref) => (
+
+
+
+
+ {children}
+
+
+
+
+));
+SelectContent.displayName = SelectPrimitive.Content.displayName;
+
+const SelectLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SelectLabel.displayName = SelectPrimitive.Label.displayName;
+
+const SelectItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+
+ {children}
+
+));
+SelectItem.displayName = SelectPrimitive.Item.displayName;
+
+const SelectSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
+
+export {
+ Select,
+ SelectGroup,
+ SelectValue,
+ SelectTrigger,
+ SelectContent,
+ SelectLabel,
+ SelectItem,
+ SelectSeparator,
+ SelectScrollUpButton,
+ SelectScrollDownButton,
+};
diff --git a/app/src/components/ui/separator.tsx b/app/src/components/ui/separator.tsx
new file mode 100644
index 00000000..e20c3f4c
--- /dev/null
+++ b/app/src/components/ui/separator.tsx
@@ -0,0 +1,20 @@
+import * as React from "react";
+import * as SeparatorPrimitive from "@radix-ui/react-separator";
+
+import { cn } from "@/lib/utils";
+
+const Separator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
+
+));
+Separator.displayName = SeparatorPrimitive.Root.displayName;
+
+export { Separator };
diff --git a/app/src/components/ui/skeleton.tsx b/app/src/components/ui/skeleton.tsx
new file mode 100644
index 00000000..6690a131
--- /dev/null
+++ b/app/src/components/ui/skeleton.tsx
@@ -0,0 +1,7 @@
+import { cn } from "@/lib/utils";
+
+function Skeleton({ className, ...props }: React.HTMLAttributes) {
+ return
;
+}
+
+export { Skeleton };
diff --git a/app/src/components/ui/table.tsx b/app/src/components/ui/table.tsx
new file mode 100644
index 00000000..991cdbf3
--- /dev/null
+++ b/app/src/components/ui/table.tsx
@@ -0,0 +1,72 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Table = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+Table.displayName = "Table";
+
+const TableHeader = React.forwardRef>(
+ ({ className, ...props }, ref) => ,
+);
+TableHeader.displayName = "TableHeader";
+
+const TableBody = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+TableBody.displayName = "TableBody";
+
+const TableFooter = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+ tr]:last:border-b-0", className)} {...props} />
+ ),
+);
+TableFooter.displayName = "TableFooter";
+
+const TableRow = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+TableRow.displayName = "TableRow";
+
+const TableHead = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+TableHead.displayName = "TableHead";
+
+const TableCell = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+TableCell.displayName = "TableCell";
+
+const TableCaption = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ ),
+);
+TableCaption.displayName = "TableCaption";
+
+export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
diff --git a/app/src/components/ui/textarea.tsx b/app/src/components/ui/textarea.tsx
new file mode 100644
index 00000000..4a5643e8
--- /dev/null
+++ b/app/src/components/ui/textarea.tsx
@@ -0,0 +1,21 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+export interface TextareaProps extends React.TextareaHTMLAttributes {}
+
+const Textarea = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+
+ );
+});
+Textarea.displayName = "Textarea";
+
+export { Textarea };
diff --git a/app/src/components/ui/theme-toggle.tsx b/app/src/components/ui/theme-toggle.tsx
new file mode 100644
index 00000000..2a8d6d72
--- /dev/null
+++ b/app/src/components/ui/theme-toggle.tsx
@@ -0,0 +1,64 @@
+import { useEffect, useState } from "react";
+import { Sun, Moon } from "lucide-react";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+
+type Theme = "light" | "dark";
+
+const ThemeToggle = () => {
+ const [theme, setTheme] = useState(() => {
+ try {
+ const savedTheme = localStorage.getItem("theme") as Theme;
+ return savedTheme || "dark";
+ } catch {
+ return "dark";
+ }
+ });
+
+ useEffect(() => {
+ const root = document.documentElement;
+ root.setAttribute("data-theme", theme);
+ try {
+ localStorage.setItem("theme", theme);
+ } catch (error) {
+ console.warn("Failed to persist theme preference:", error);
+ }
+ }, [theme]);
+
+ const toggleTheme = () => {
+ setTheme((current) => (current === "dark" ? "light" : "dark"));
+ };
+
+ const getIcon = () => {
+ return theme === "light" ? : ;
+ };
+
+ const getTooltipText = () => {
+ return theme === "dark" ? "Switch to Light Mode" : "Switch to Dark Mode";
+ };
+
+ return (
+
+
+
+
+ {getIcon()}
+ {getTooltipText()}
+
+
+ {getTooltipText()}
+
+
+ );
+};
+
+export default ThemeToggle;
diff --git a/app/src/components/ui/toast.tsx b/app/src/components/ui/toast.tsx
new file mode 100644
index 00000000..0699548f
--- /dev/null
+++ b/app/src/components/ui/toast.tsx
@@ -0,0 +1,111 @@
+import * as React from "react";
+import * as ToastPrimitives from "@radix-ui/react-toast";
+import { cva, type VariantProps } from "class-variance-authority";
+import { X } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const ToastProvider = ToastPrimitives.Provider;
+
+const ToastViewport = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
+
+const toastVariants = cva(
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
+ {
+ variants: {
+ variant: {
+ default: "border bg-background text-foreground",
+ destructive: "destructive group border-destructive bg-destructive text-destructive-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
+
+const Toast = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & VariantProps
+>(({ className, variant, ...props }, ref) => {
+ return ;
+});
+Toast.displayName = ToastPrimitives.Root.displayName;
+
+const ToastAction = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastAction.displayName = ToastPrimitives.Action.displayName;
+
+const ToastClose = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+ToastClose.displayName = ToastPrimitives.Close.displayName;
+
+const ToastTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastTitle.displayName = ToastPrimitives.Title.displayName;
+
+const ToastDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+ToastDescription.displayName = ToastPrimitives.Description.displayName;
+
+type ToastProps = React.ComponentPropsWithoutRef;
+
+type ToastActionElement = React.ReactElement;
+
+export {
+ type ToastProps,
+ type ToastActionElement,
+ ToastProvider,
+ ToastViewport,
+ Toast,
+ ToastTitle,
+ ToastDescription,
+ ToastClose,
+ ToastAction,
+};
diff --git a/app/src/components/ui/toaster.tsx b/app/src/components/ui/toaster.tsx
new file mode 100644
index 00000000..2553c80e
--- /dev/null
+++ b/app/src/components/ui/toaster.tsx
@@ -0,0 +1,24 @@
+import { useToast } from "@/hooks/use-toast";
+import { Toast, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from "@/components/ui/toast";
+
+export function Toaster() {
+ const { toasts } = useToast();
+
+ return (
+
+ {toasts.map(function ({ id, title, description, action, ...props }) {
+ return (
+
+
+ {title && {title} }
+ {description && {description} }
+
+ {action}
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/app/src/components/ui/tooltip.tsx b/app/src/components/ui/tooltip.tsx
new file mode 100644
index 00000000..8490d748
--- /dev/null
+++ b/app/src/components/ui/tooltip.tsx
@@ -0,0 +1,29 @@
+import * as React from "react";
+import * as TooltipPrimitive from "@radix-ui/react-tooltip";
+
+import { cn } from "@/lib/utils";
+
+const TooltipProvider = TooltipPrimitive.Provider;
+
+const Tooltip = TooltipPrimitive.Root;
+
+const TooltipTrigger = TooltipPrimitive.Trigger;
+
+const TooltipContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+ e.preventDefault()}
+ className={cn(
+ "!z-[9999] overflow-hidden rounded-md bg-gray-800 border border-gray-600 px-3 py-2 text-sm text-gray-100 shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+ className,
+ )}
+ {...props}
+ />
+));
+TooltipContent.displayName = TooltipPrimitive.Content.displayName;
+
+export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
diff --git a/app/src/components/ui/use-toast.ts b/app/src/components/ui/use-toast.ts
new file mode 100644
index 00000000..b0aef21b
--- /dev/null
+++ b/app/src/components/ui/use-toast.ts
@@ -0,0 +1,3 @@
+import { useToast, toast } from "@/hooks/use-toast";
+
+export { useToast, toast };
diff --git a/app/src/config/api.ts b/app/src/config/api.ts
new file mode 100644
index 00000000..f4671e21
--- /dev/null
+++ b/app/src/config/api.ts
@@ -0,0 +1,44 @@
+// API Configuration
+export const API_CONFIG = {
+ // Base URL for the QueryWeaver backend API
+ // When served from backend (port 5000): use empty string (same origin)
+ // When using Vite dev server (port 8080): use /api prefix for proxy
+ // For production: use environment variable or empty string
+ BASE_URL: import.meta.env.VITE_API_URL || (
+ // If running on Vite dev server (port 8080), use /api proxy
+ window.location.port === '8080' ? '/api' : ''
+ ),
+
+ // Streaming boundary marker used by QueryWeaver backend
+ STREAM_BOUNDARY: '|||FALKORDB_MESSAGE_BOUNDARY|||',
+
+ // Endpoints
+ ENDPOINTS: {
+ // Authentication
+ AUTH_STATUS: '/auth-status',
+ LOGIN_GOOGLE: '/login/google',
+ LOGIN_GITHUB: '/login/github',
+ LOGOUT: '/logout',
+
+ // Graph/Database management
+ GRAPHS: '/graphs',
+ GRAPH_BY_ID: (id: string) => `/graphs/${id}`,
+ UPLOAD_SCHEMA: '/upload',
+ DELETE_GRAPH: (id: string) => `/graphs/${id}`,
+ CONNECT_DATABASE: '/database',
+
+ // Chat/Query
+ CHAT: '/chat',
+ CONFIRM: '/confirm',
+
+ // User
+ USER: '/user',
+ },
+};
+
+// Helper to build full API URL
+export const buildApiUrl = (endpoint: string): string => {
+ return `${API_CONFIG.BASE_URL}${endpoint}`;
+};
+
+
diff --git a/app/src/contexts/AuthContext.tsx b/app/src/contexts/AuthContext.tsx
new file mode 100644
index 00000000..53e41d78
--- /dev/null
+++ b/app/src/contexts/AuthContext.tsx
@@ -0,0 +1,73 @@
+import React, { createContext, useContext, useState, useEffect } from 'react';
+import { AuthService } from '@/services/auth';
+import type { User } from '@/types/api';
+
+interface AuthContextType {
+ user: User | null;
+ isAuthenticated: boolean;
+ isLoading: boolean;
+ login: {
+ google: () => Promise;
+ github: () => Promise;
+ };
+ logout: () => Promise;
+ refreshAuth: () => Promise;
+}
+
+const AuthContext = createContext(undefined);
+
+export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [user, setUser] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+
+ const checkAuth = async () => {
+ try {
+ setIsLoading(true);
+ const status = await AuthService.checkAuthStatus();
+ setUser(status.user || null);
+ } catch (error) {
+ console.log('Backend not available - running in demo mode');
+ // Silently fail - this is expected when backend isn't running
+ setUser(null);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ checkAuth();
+ }, []);
+
+ const handleLogout = async () => {
+ try {
+ await AuthService.logout();
+ setUser(null);
+ } catch (error) {
+ console.error('Logout failed:', error);
+ throw error;
+ }
+ };
+
+ const value: AuthContextType = {
+ user,
+ isAuthenticated: !!user,
+ isLoading,
+ login: {
+ google: AuthService.loginWithGoogle,
+ github: AuthService.loginWithGithub,
+ },
+ logout: handleLogout,
+ refreshAuth: checkAuth,
+ };
+
+ return {children} ;
+};
+
+export const useAuth = () => {
+ const context = useContext(AuthContext);
+ if (context === undefined) {
+ throw new Error('useAuth must be used within an AuthProvider');
+ }
+ return context;
+};
+
diff --git a/app/src/contexts/DatabaseContext.tsx b/app/src/contexts/DatabaseContext.tsx
new file mode 100644
index 00000000..2bd67fe8
--- /dev/null
+++ b/app/src/contexts/DatabaseContext.tsx
@@ -0,0 +1,110 @@
+import React, { createContext, useContext, useState, useEffect } from 'react';
+import { DatabaseService } from '@/services/database';
+import type { Graph } from '@/types/api';
+
+interface DatabaseContextType {
+ graphs: Graph[];
+ selectedGraph: Graph | null;
+ isLoading: boolean;
+ selectGraph: (graphId: string) => void;
+ refreshGraphs: () => Promise;
+ uploadSchema: (file: File, databaseName?: string) => Promise;
+ deleteGraph: (graphId: string) => Promise;
+}
+
+const DatabaseContext = createContext(undefined);
+
+export const DatabaseProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [graphs, setGraphs] = useState([]);
+ const [selectedGraph, setSelectedGraph] = useState(null);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const fetchGraphs = async () => {
+ try {
+ setIsLoading(true);
+ const fetchedGraphs = await DatabaseService.getGraphs();
+ setGraphs(fetchedGraphs);
+
+ // Auto-select first graph if none selected (using functional update to avoid stale closure)
+ setSelectedGraph(current => {
+ if (!current && fetchedGraphs.length > 0) {
+ return fetchedGraphs[0];
+ }
+ return current;
+ });
+ } catch (error) {
+ console.log('Backend not available - running in demo mode without saved databases');
+ // Silently fail - this is expected when backend isn't running
+ setGraphs([]);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ fetchGraphs();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []); // Only run on mount - fetchGraphs is stable
+
+ const selectGraph = (graphId: string) => {
+ const graph = graphs.find(g => g.id === graphId);
+ if (graph) {
+ setSelectedGraph(graph);
+ }
+ };
+
+ const uploadSchema = async (file: File, databaseName?: string) => {
+ try {
+ setIsLoading(true);
+ await DatabaseService.uploadSchema({
+ file,
+ database_name: databaseName,
+ });
+ await fetchGraphs();
+ } catch (error) {
+ console.error('Failed to upload schema:', error);
+ throw error;
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const deleteGraph = async (graphId: string) => {
+ try {
+ setIsLoading(true);
+ await DatabaseService.deleteGraph(graphId);
+
+ // Clear selection if deleted graph was selected
+ if (selectedGraph?.id === graphId) {
+ setSelectedGraph(null);
+ }
+
+ await fetchGraphs();
+ } catch (error) {
+ console.error('Failed to delete graph:', error);
+ throw error;
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const value: DatabaseContextType = {
+ graphs,
+ selectedGraph,
+ isLoading,
+ selectGraph,
+ refreshGraphs: fetchGraphs,
+ uploadSchema,
+ deleteGraph,
+ };
+
+ return {children} ;
+};
+
+export const useDatabase = () => {
+ const context = useContext(DatabaseContext);
+ if (context === undefined) {
+ throw new Error('useDatabase must be used within a DatabaseProvider');
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/app/src/hooks/use-mobile.tsx b/app/src/hooks/use-mobile.tsx
new file mode 100644
index 00000000..dd537ec9
--- /dev/null
+++ b/app/src/hooks/use-mobile.tsx
@@ -0,0 +1,19 @@
+import * as React from "react";
+
+const MOBILE_BREAKPOINT = 768;
+
+export function useIsMobile() {
+ const [isMobile, setIsMobile] = React.useState(undefined);
+
+ React.useEffect(() => {
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
+ const onChange = () => {
+ setIsMobile(mql.matches);
+ };
+ mql.addEventListener("change", onChange);
+ setIsMobile(mql.matches);
+ return () => mql.removeEventListener("change", onChange);
+ }, []);
+
+ return !!isMobile;
+}
diff --git a/app/src/hooks/use-toast.ts b/app/src/hooks/use-toast.ts
new file mode 100644
index 00000000..5e79a0e3
--- /dev/null
+++ b/app/src/hooks/use-toast.ts
@@ -0,0 +1,186 @@
+import * as React from "react";
+
+import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
+
+const TOAST_LIMIT = 1;
+const TOAST_REMOVE_DELAY = 5000; // 5 seconds
+
+type ToasterToast = ToastProps & {
+ id: string;
+ title?: React.ReactNode;
+ description?: React.ReactNode;
+ action?: ToastActionElement;
+};
+
+const actionTypes = {
+ ADD_TOAST: "ADD_TOAST",
+ UPDATE_TOAST: "UPDATE_TOAST",
+ DISMISS_TOAST: "DISMISS_TOAST",
+ REMOVE_TOAST: "REMOVE_TOAST",
+} as const;
+
+let count = 0;
+
+function genId() {
+ count = (count + 1) % Number.MAX_SAFE_INTEGER;
+ return count.toString();
+}
+
+type ActionType = typeof actionTypes;
+
+type Action =
+ | {
+ type: ActionType["ADD_TOAST"];
+ toast: ToasterToast;
+ }
+ | {
+ type: ActionType["UPDATE_TOAST"];
+ toast: Partial;
+ }
+ | {
+ type: ActionType["DISMISS_TOAST"];
+ toastId?: ToasterToast["id"];
+ }
+ | {
+ type: ActionType["REMOVE_TOAST"];
+ toastId?: ToasterToast["id"];
+ };
+
+interface State {
+ toasts: ToasterToast[];
+}
+
+const toastTimeouts = new Map>();
+
+const addToRemoveQueue = (toastId: string) => {
+ if (toastTimeouts.has(toastId)) {
+ return;
+ }
+
+ const timeout = setTimeout(() => {
+ toastTimeouts.delete(toastId);
+ dispatch({
+ type: "REMOVE_TOAST",
+ toastId: toastId,
+ });
+ }, TOAST_REMOVE_DELAY);
+
+ toastTimeouts.set(toastId, timeout);
+};
+
+export const reducer = (state: State, action: Action): State => {
+ switch (action.type) {
+ case "ADD_TOAST":
+ return {
+ ...state,
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
+ };
+
+ case "UPDATE_TOAST":
+ return {
+ ...state,
+ toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
+ };
+
+ case "DISMISS_TOAST": {
+ const { toastId } = action;
+
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
+ // but I'll keep it here for simplicity
+ if (toastId) {
+ addToRemoveQueue(toastId);
+ } else {
+ state.toasts.forEach((toast) => {
+ addToRemoveQueue(toast.id);
+ });
+ }
+
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === toastId || toastId === undefined
+ ? {
+ ...t,
+ open: false,
+ }
+ : t,
+ ),
+ };
+ }
+ case "REMOVE_TOAST":
+ if (action.toastId === undefined) {
+ return {
+ ...state,
+ toasts: [],
+ };
+ }
+ return {
+ ...state,
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
+ };
+ }
+};
+
+const listeners: Array<(state: State) => void> = [];
+
+let memoryState: State = { toasts: [] };
+
+function dispatch(action: Action) {
+ memoryState = reducer(memoryState, action);
+ listeners.forEach((listener) => {
+ listener(memoryState);
+ });
+}
+
+type Toast = Omit;
+
+function toast({ ...props }: Toast) {
+ const id = genId();
+
+ const update = (props: ToasterToast) =>
+ dispatch({
+ type: "UPDATE_TOAST",
+ toast: { ...props, id },
+ });
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
+
+ dispatch({
+ type: "ADD_TOAST",
+ toast: {
+ ...props,
+ id,
+ open: true,
+ onOpenChange: (open) => {
+ if (!open) dismiss();
+ },
+ },
+ });
+
+ return {
+ id: id,
+ dismiss,
+ update,
+ };
+}
+
+function useToast() {
+ const [state, setState] = React.useState(memoryState);
+
+ React.useEffect(() => {
+ listeners.push(setState);
+ return () => {
+ const index = listeners.indexOf(setState);
+ if (index > -1) {
+ listeners.splice(index, 1);
+ }
+ };
+ }, [state]);
+
+ return {
+ ...state,
+ toast,
+ dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
+ };
+}
+
+export { useToast, toast };
diff --git a/app/src/index.css b/app/src/index.css
new file mode 100644
index 00000000..af96b885
--- /dev/null
+++ b/app/src/index.css
@@ -0,0 +1,376 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Fira+Code:wght@400;500;600&display=swap');
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/* Definition of the design system. All colors, gradients, fonts, etc should be defined here.
+All colors MUST be HSL.
+*/
+
+@layer base {
+ :root {
+ /* QueryWeaver Dark Theme */
+ --background: 222 84% 5%;
+ --foreground: 210 40% 98%;
+
+ --card: 224 71% 8%;
+ --card-foreground: 210 40% 98%;
+
+ --popover: 224 71% 8%;
+ --popover-foreground: 210 40% 98%;
+
+ /* Purple primary matching QueryWeaver branding */
+ --primary: 262 83% 58%;
+ --primary-foreground: 210 40% 98%;
+
+ --primary-glow: 262 83% 70%;
+ --primary-dark: 262 83% 45%;
+
+ --secondary: 215 28% 17%;
+ --secondary-foreground: 210 40% 98%;
+
+ --muted: 215 28% 17%;
+ --muted-foreground: 215 20% 65%;
+
+ --accent: 216 34% 17%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 84% 60%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 215 28% 17%;
+ --input: 215 28% 17%;
+ --ring: 262 83% 58%;
+
+ /* QueryWeaver specific colors */
+ --sidebar-bg: 222 84% 4%;
+ --chat-bg: 220 13% 18%;
+ --modal-overlay: 222 84% 4% / 0.8;
+
+ /* Button specific colors */
+ --google-blue: 217 91% 60%;
+ --github-dark: 210 11% 15%;
+
+ --radius: 0.5rem;
+
+ --sidebar-background: 0 0% 98%;
+
+ --sidebar-foreground: 240 5.3% 26.1%;
+
+ --sidebar-primary: 240 5.9% 10%;
+
+ --sidebar-primary-foreground: 0 0% 98%;
+
+ --sidebar-accent: 240 4.8% 95.9%;
+
+ --sidebar-accent-foreground: 240 5.9% 10%;
+
+ --sidebar-border: 220 13% 91%;
+
+ --sidebar-ring: 217.2 91.2% 59.8%;
+ }
+
+ .dark {
+ /* Keep dark theme consistent */
+ --background: 222 84% 5%;
+ --foreground: 210 40% 98%;
+ --card: 224 71% 8%;
+ --card-foreground: 210 40% 98%;
+ --popover: 224 71% 8%;
+ --popover-foreground: 210 40% 98%;
+ --primary: 262 83% 58%;
+ --primary-foreground: 210 40% 98%;
+ --secondary: 215 28% 17%;
+ --secondary-foreground: 210 40% 98%;
+ --muted: 215 28% 17%;
+ --muted-foreground: 215 20% 65%;
+ --accent: 216 34% 17%;
+ --accent-foreground: 210 40% 98%;
+ --destructive: 0 84% 60%;
+ --destructive-foreground: 210 40% 98%;
+ --border: 215 28% 17%;
+ --input: 215 28% 17%;
+ --ring: 262 83% 58%;
+ }
+
+ /* Light Theme */
+ [data-theme="light"] {
+ --background: 0 0% 100%;
+ --foreground: 222 84% 5%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222 84% 5%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222 84% 5%;
+
+ --primary: 262 83% 58%;
+ --primary-foreground: 210 40% 98%;
+
+ --primary-glow: 262 83% 70%;
+ --primary-dark: 262 83% 45%;
+
+ --secondary: 210 40% 96%;
+ --secondary-foreground: 222 84% 5%;
+
+ --muted: 210 40% 96%;
+ --muted-foreground: 215 20% 35%;
+
+ --accent: 210 40% 96%;
+ --accent-foreground: 222 84% 5%;
+
+ --destructive: 0 84% 60%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 214 32% 91%;
+ --input: 214 32% 91%;
+ --ring: 262 83% 58%;
+
+ --sidebar-bg: 0 0% 98%;
+ --chat-bg: 0 0% 95%;
+ --modal-overlay: 0 0% 0% / 0.5;
+ }
+
+ /* System Theme - follows OS preference */
+ [data-theme="system"] {
+ /* Use dark as default, will be overridden by media query */
+ --background: 222 84% 5%;
+ --foreground: 210 40% 98%;
+ --card: 224 71% 8%;
+ --card-foreground: 210 40% 98%;
+ --popover: 224 71% 8%;
+ --popover-foreground: 210 40% 98%;
+ --primary: 262 83% 58%;
+ --primary-foreground: 210 40% 98%;
+ --secondary: 215 28% 17%;
+ --secondary-foreground: 210 40% 98%;
+ --muted: 215 28% 17%;
+ --muted-foreground: 215 20% 65%;
+ --accent: 216 34% 17%;
+ --accent-foreground: 210 40% 98%;
+ --destructive: 0 84% 60%;
+ --destructive-foreground: 210 40% 98%;
+ --border: 215 28% 17%;
+ --input: 215 28% 17%;
+ --ring: 262 83% 58%;
+ }
+
+ /* System theme in light mode */
+ @media (prefers-color-scheme: light) {
+ [data-theme="system"] {
+ --background: 0 0% 100%;
+ --foreground: 222 84% 5%;
+ --card: 0 0% 100%;
+ --card-foreground: 222 84% 5%;
+ --popover: 0 0% 100%;
+ --popover-foreground: 222 84% 5%;
+ --primary: 262 83% 58%;
+ --primary-foreground: 210 40% 98%;
+ --secondary: 210 40% 96%;
+ --secondary-foreground: 222 84% 5%;
+ --muted: 210 40% 96%;
+ --muted-foreground: 215 20% 35%;
+ --accent: 210 40% 96%;
+ --accent-foreground: 222 84% 5%;
+ --destructive: 0 84% 60%;
+ --destructive-foreground: 210 40% 98%;
+ --border: 214 32% 91%;
+ --input: 214 32% 91%;
+ --ring: 262 83% 58%;
+ --sidebar-bg: 0 0% 98%;
+ --chat-bg: 0 0% 95%;
+ --modal-overlay: 0 0% 0% / 0.5;
+ }
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+
+ body {
+ @apply bg-background text-foreground font-sans;
+ }
+
+ /* Theme-specific body background overrides */
+ [data-theme="dark"] body {
+ background-color: hsl(222 84% 5%);
+ color: hsl(210 40% 98%);
+ }
+
+ [data-theme="light"] body {
+ background-color: hsl(0 0% 100%);
+ color: hsl(222 84% 5%);
+ }
+
+ [data-theme="system"] body {
+ background-color: hsl(222 84% 5%);
+ color: hsl(210 40% 98%);
+ }
+
+ @media (prefers-color-scheme: light) {
+ [data-theme="system"] body {
+ background-color: hsl(0 0% 100%);
+ color: hsl(222 84% 5%);
+ }
+ }
+
+ /* Override gray backgrounds for light theme */
+ [data-theme="light"] .bg-gray-900,
+ [data-theme="light"] [class*="bg-gray-9"] {
+ background-color: hsl(0 0% 100%) !important;
+ }
+
+ [data-theme="light"] .bg-gray-800,
+ [data-theme="light"] [class*="bg-gray-8"] {
+ background-color: hsl(0 0% 98%) !important;
+ }
+
+ [data-theme="light"] .bg-gray-700 {
+ background-color: hsl(210 40% 96%) !important;
+ }
+
+ [data-theme="light"] .text-gray-100,
+ [data-theme="light"] .text-white {
+ color: hsl(222 84% 5%) !important;
+ }
+
+ [data-theme="light"] .text-gray-200 {
+ color: hsl(222 84% 10%) !important;
+ }
+
+ [data-theme="light"] .text-gray-300 {
+ color: hsl(215 20% 25%) !important;
+ }
+
+ [data-theme="light"] .text-gray-400 {
+ color: hsl(215 20% 35%) !important;
+ }
+
+ [data-theme="light"] .border-gray-700,
+ [data-theme="light"] .border-gray-600 {
+ border-color: hsl(214 32% 91%) !important;
+ }
+
+ /* System theme with light preference */
+ @media (prefers-color-scheme: light) {
+ [data-theme="system"] .bg-gray-900,
+ [data-theme="system"] [class*="bg-gray-9"] {
+ background-color: hsl(0 0% 100%) !important;
+ }
+
+ [data-theme="system"] .bg-gray-800,
+ [data-theme="system"] [class*="bg-gray-8"] {
+ background-color: hsl(0 0% 98%) !important;
+ }
+
+ [data-theme="system"] .bg-gray-700 {
+ background-color: hsl(210 40% 96%) !important;
+ }
+
+ [data-theme="system"] .text-gray-100,
+ [data-theme="system"] .text-white {
+ color: hsl(222 84% 5%) !important;
+ }
+
+ [data-theme="system"] .text-gray-200 {
+ color: hsl(222 84% 10%) !important;
+ }
+
+ [data-theme="system"] .text-gray-300 {
+ color: hsl(215 20% 25%) !important;
+ }
+
+ [data-theme="system"] .text-gray-400 {
+ color: hsl(215 20% 35%) !important;
+ }
+
+ [data-theme="system"] .border-gray-700,
+ [data-theme="system"] .border-gray-600 {
+ border-color: hsl(214 32% 91%) !important;
+ }
+ }
+}
+
+/* Hide scrollbar utilities */
+@layer utilities {
+ .scrollbar-hide {
+ /* Hide scrollbar for IE, Edge and Firefox */
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ }
+
+ .scrollbar-hide::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+ }
+
+ .scrollbar-hide::-webkit-scrollbar-track {
+ background: transparent;
+ }
+
+ .scrollbar-hide::-webkit-scrollbar-thumb {
+ background: transparent;
+ }
+
+ .scrollbar-visible {
+ /* Firefox */
+ scrollbar-width: auto;
+ }
+
+ /* Light mode scrollbar colors */
+ .scrollbar-visible {
+ scrollbar-color: #D1D5DB #F3F4F6;
+ }
+
+ .scrollbar-visible::-webkit-scrollbar {
+ width: 12px;
+ height: 12px;
+ }
+
+ .scrollbar-visible::-webkit-scrollbar-track {
+ background: #F3F4F6;
+ border-radius: 6px;
+ margin: 2px;
+ }
+
+ .scrollbar-visible::-webkit-scrollbar-thumb {
+ background: #D1D5DB;
+ border-radius: 6px;
+ border: 2px solid #F3F4F6;
+ }
+
+ .scrollbar-visible::-webkit-scrollbar-thumb:hover {
+ background: #9CA3AF;
+ }
+
+ .scrollbar-visible::-webkit-scrollbar-corner {
+ background: #F3F4F6;
+ }
+
+ /* Dark mode scrollbar colors */
+ .dark .scrollbar-visible {
+ scrollbar-color: #6B7280 #374151;
+ }
+
+ .dark .scrollbar-visible::-webkit-scrollbar-track {
+ background: #374151;
+ border: 2px solid #374151;
+ }
+
+ .dark .scrollbar-visible::-webkit-scrollbar-thumb {
+ background: #6B7280;
+ border-radius: 6px;
+ border: 2px solid #374151;
+ }
+
+ .dark .scrollbar-visible::-webkit-scrollbar-thumb:hover {
+ background: #9CA3AF;
+ }
+
+ .dark .scrollbar-visible::-webkit-scrollbar-corner {
+ background: #374151;
+ }
+}
diff --git a/app/src/lib/utils.ts b/app/src/lib/utils.ts
new file mode 100644
index 00000000..a5ef1935
--- /dev/null
+++ b/app/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/app/src/main.tsx b/app/src/main.tsx
new file mode 100644
index 00000000..53280ea9
--- /dev/null
+++ b/app/src/main.tsx
@@ -0,0 +1,17 @@
+import { createRoot } from "react-dom/client";
+import App from "./App.tsx";
+import "./index.css";
+
+// Initialize theme on page load
+try {
+ const savedTheme = localStorage.getItem("theme") || "dark";
+ document.documentElement.setAttribute("data-theme", savedTheme);
+} catch {
+ document.documentElement.setAttribute("data-theme", "dark");
+}
+
+const rootElement = document.getElementById("root");
+if (!rootElement) {
+ throw new Error("Failed to find the root element. Make sure index.html contains a div with id='root'.");
+}
+createRoot(rootElement).render( );
diff --git a/app/src/pages/Index.tsx b/app/src/pages/Index.tsx
new file mode 100644
index 00000000..8a4d50b5
--- /dev/null
+++ b/app/src/pages/Index.tsx
@@ -0,0 +1,643 @@
+import { useState, useRef, useEffect } from "react";
+import { Button } from "@/components/ui/button";
+import { Badge } from "@/components/ui/badge";
+import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
+import { Trash2, Star, RefreshCw, PanelLeft } from "lucide-react";
+import Sidebar from "@/components/layout/Sidebar";
+import ChatInterface from "@/components/chat/ChatInterface";
+import LoginModal from "@/components/modals/LoginModal";
+import DatabaseModal from "@/components/modals/DatabaseModal";
+import DeleteDatabaseModal from "@/components/modals/DeleteDatabaseModal";
+import TokensModal from "@/components/modals/TokensModal";
+import SchemaViewer from "@/components/schema";
+import LoadingSpinner from "@/components/ui/loading-spinner";
+import { useAuth } from "@/contexts/AuthContext";
+import { useDatabase } from "@/contexts/DatabaseContext";
+import { DatabaseService } from "@/services/database";
+import { useToast } from "@/components/ui/use-toast";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+ DropdownMenuSeparator,
+} from "@/components/ui/dropdown-menu";
+
+const Index = () => {
+ const { isAuthenticated, isLoading: authLoading, logout, user } = useAuth();
+ const { selectedGraph, graphs, selectGraph, uploadSchema } = useDatabase();
+ const { toast } = useToast();
+ const [showDatabaseModal, setShowDatabaseModal] = useState(false);
+ const [showLoginModal, setShowLoginModal] = useState(false);
+ const [showDeleteModal, setShowDeleteModal] = useState(false);
+ const [showSchemaViewer, setShowSchemaViewer] = useState(false);
+ const [showTokensModal, setShowTokensModal] = useState(false);
+ const [isRefreshingSchema, setIsRefreshingSchema] = useState(false);
+ const [isChatProcessing, setIsChatProcessing] = useState(false);
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(() =>
+ typeof window !== 'undefined' ? window.innerWidth < 768 : false
+ );
+ const [schemaViewerWidth, setSchemaViewerWidth] = useState(() =>
+ typeof window !== "undefined" ? Math.floor(window.innerWidth * 0.4) : 0,
+ );
+ const [githubStars, setGithubStars] = useState('-');
+ const [databaseToDelete, setDatabaseToDelete] = useState<{ id: string; name: string; isDemo: boolean } | null>(null);
+ const [windowWidth, setWindowWidth] = useState(typeof window !== 'undefined' ? window.innerWidth : 1024);
+ const fileInputRef = useRef(null);
+
+ // Handle window resize to update layout
+ useEffect(() => {
+ const handleResize = () => {
+ setWindowWidth(window.innerWidth);
+ };
+
+ window.addEventListener('resize', handleResize);
+ return () => window.removeEventListener('resize', handleResize);
+ }, []);
+
+ // Auto-collapse sidebar when switching to mobile view
+ useEffect(() => {
+ const isMobile = windowWidth < 768;
+ if (isMobile) {
+ setSidebarCollapsed(true);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [windowWidth]); // Only run when windowWidth changes, not on manual toggle
+
+ // Calculate sidebar width based on collapsed state
+ // On desktop: sidebar is always visible (64px), on mobile: can be collapsed (0px)
+ const getSidebarWidth = () => {
+ const isMobile = windowWidth < 768;
+ if (isMobile) {
+ return sidebarCollapsed ? 0 : 64;
+ }
+ return 64; // Always visible on desktop
+ };
+
+ const sidebarWidth = getSidebarWidth();
+
+ // Calculate main content margin and width
+ // On mobile: ignore schema viewer (it's an overlay), only account for sidebar
+ // On desktop: account for both sidebar and schema viewer
+ const getMainContentStyles = () => {
+ const isMobile = windowWidth < 768;
+
+ if (isMobile) {
+ return {
+ marginLeft: `${sidebarWidth}px`,
+ width: `calc(100% - ${sidebarWidth}px)`
+ };
+ }
+
+ // Desktop
+ const totalOffset = showSchemaViewer ? schemaViewerWidth + sidebarWidth : sidebarWidth;
+ return {
+ marginLeft: `${totalOffset}px`,
+ width: `calc(100% - ${totalOffset}px)`
+ };
+ };
+
+ // Fetch GitHub stars
+ useEffect(() => {
+ fetch('https://api.github.com/repos/FalkorDB/QueryWeaver')
+ .then(response => response.json())
+ .then(data => {
+ if (typeof data.stargazers_count === 'number') {
+ setGithubStars(data.stargazers_count.toLocaleString());
+ }
+ })
+ .catch(error => {
+ console.log('Failed to fetch GitHub stars:', error);
+ });
+ }, []);
+
+ // Show login modal when not authenticated after loading completes
+ useEffect(() => {
+ // Only auto-open the login modal once per user/session to avoid locking
+ // the SPA when the backend is down or in demo mode. Allow users to
+ // dismiss it and remember that choice in sessionStorage.
+ if (!authLoading && !isAuthenticated) {
+ const dismissed = sessionStorage.getItem('loginModalDismissed');
+ if (!dismissed) {
+ setShowLoginModal(true);
+ }
+ }
+ }, [authLoading, isAuthenticated]);
+
+ const handleConnectDatabase = () => {
+ if (isRefreshingSchema || isChatProcessing) return;
+ setShowDatabaseModal(true);
+ };
+
+ const handleUploadSchema = () => {
+ fileInputRef.current?.click();
+ };
+
+ const handleFileSelect = async (event: React.ChangeEvent) => {
+ const file = event.target.files?.[0];
+ if (!file) return;
+
+ try {
+ await uploadSchema(file, file.name.replace(/\.[^/.]+$/, ""));
+ toast({
+ title: "Schema Uploaded",
+ description: "Database schema uploaded successfully!",
+ });
+ } catch (error) {
+ toast({
+ title: "Upload Failed",
+ description: error instanceof Error ? error.message : "Failed to upload schema",
+ variant: "destructive",
+ });
+ }
+
+ // Reset file input
+ if (fileInputRef.current) {
+ fileInputRef.current.value = '';
+ }
+ };
+
+ const handleDeleteGraph = async (graphId: string, graphName: string, event: React.MouseEvent) => {
+ event.stopPropagation(); // Prevent dropdown from closing/selecting
+
+ // Check if this is a demo database
+ const isDemo = graphId.startsWith('general_');
+
+ if (isRefreshingSchema) return;
+ // Show the delete confirmation modal
+ setDatabaseToDelete({ id: graphId, name: graphName, isDemo });
+ setShowDeleteModal(true);
+ };
+
+ const confirmDeleteGraph = async () => {
+ if (!databaseToDelete) return;
+
+ try {
+ await DatabaseService.deleteGraph(databaseToDelete.id);
+
+ toast({
+ title: "Database Deleted",
+ description: `Successfully deleted "${databaseToDelete.name}"`,
+ });
+
+ // Close modal before refresh
+ setShowDeleteModal(false);
+ setDatabaseToDelete(null);
+
+ // Refresh the graphs list (can be replaced with a context refresh later)
+ window.location.reload();
+ } catch (error) {
+ toast({
+ title: "Delete Failed",
+ description: error instanceof Error ? error.message : "Failed to delete database",
+ variant: "destructive",
+ });
+ }
+ };
+
+ const handleLogout = async () => {
+ try {
+ await logout();
+ toast({
+ title: "Logged Out",
+ description: "You have been successfully logged out",
+ });
+ // Refresh to reset state
+ window.location.reload();
+ } catch (error) {
+ toast({
+ title: "Logout Failed",
+ description: error instanceof Error ? error.message : "Failed to logout",
+ variant: "destructive",
+ });
+ }
+ };
+
+ const handleRefreshSchema = async () => {
+ if (!selectedGraph) {
+ toast({
+ title: "No Database Selected",
+ description: "Please select a database first",
+ variant: "destructive",
+ });
+ return;
+ }
+
+ if (isChatProcessing) {
+ toast({
+ title: "Chat is Processing",
+ description: "Please wait for the current query to complete",
+ variant: "destructive",
+ });
+ return;
+ }
+
+ try {
+ setIsRefreshingSchema(true);
+ const response = await fetch(`/graphs/${selectedGraph.id}/refresh`, {
+ method: 'POST',
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({ error: 'Failed to refresh schema' }));
+ throw new Error(errorData.error || `Server error: ${response.status}`);
+ }
+
+ // Process streaming response
+ const reader = response.body?.getReader();
+ if (!reader) {
+ throw new Error('No response body');
+ }
+
+ const decoder = new TextDecoder();
+ let buffer = '';
+ let hasError = false;
+ const delimiter = '|||FALKORDB_MESSAGE_BOUNDARY|||';
+
+ while (true) {
+ const { done, value } = await reader.read();
+
+ if (done) break;
+
+ const chunk = decoder.decode(value, { stream: true });
+ buffer += chunk;
+
+ // Process complete messages
+ const parts = buffer.split(delimiter);
+ buffer = parts.pop() || ''; // Keep incomplete part in buffer
+
+ for (const part of parts) {
+ const trimmed = part.trim();
+ if (!trimmed) continue;
+
+ try {
+ const message = JSON.parse(trimmed);
+ if (message.type === 'error') {
+ hasError = true;
+ throw new Error(message.message || 'Schema refresh failed');
+ }
+ } catch (e) {
+ if (e instanceof SyntaxError) {
+ console.error('Failed to parse message:', trimmed);
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ if (hasError) {
+ return; // Error already thrown and caught
+ }
+
+ toast({
+ title: "Schema Refreshed",
+ description: "Database schema refreshed successfully!",
+ });
+
+ // Reload to show updated schema
+ window.location.reload();
+ } catch (error) {
+ console.error('Refresh error:', error);
+ toast({
+ title: "Refresh Failed",
+ description: error instanceof Error ? error.message : "Failed to refresh schema",
+ variant: "destructive",
+ });
+ }
+ finally {
+ setIsRefreshingSchema(false);
+ }
+ };
+
+ return (
+
+ {/* Hidden file input for schema upload */}
+
+
+ {/* Left Sidebar */}
+
{ if (!isRefreshingSchema) setShowSchemaViewer(!showSchemaViewer); }}
+ isSchemaOpen={showSchemaViewer}
+ isCollapsed={sidebarCollapsed}
+ onToggleCollapse={() => setSidebarCollapsed(!sidebarCollapsed)}
+ />
+
+ {/* Schema Viewer */}
+ setShowSchemaViewer(false)}
+ onWidthChange={setSchemaViewerWidth}
+ sidebarWidth={sidebarWidth}
+ />
+
+ {/* Main Content */}
+
+ {/* Header */}
+
+
+ {/* Sub-header for controls */}
+
+
+
+ {isRefreshingSchema ? : }
+
+
+
+
+ {selectedGraph?.name || 'Select Database'}
+
+
+
+ {graphs.map((graph) => {
+ const isDemo = graph.id.startsWith('general_');
+ return (
+ { if (!isRefreshingSchema && !isChatProcessing) selectGraph(graph.id); }}
+ disabled={isRefreshingSchema || isChatProcessing}
+ data-testid={`database-option-${graph.id}`}
+ >
+ {graph.name}
+ { if (isDemo || isRefreshingSchema || isChatProcessing) return; handleDeleteGraph(graph.id, graph.name, e); }}
+ disabled={isDemo || isRefreshingSchema}
+ title={isDemo ? 'Demo databases cannot be deleted' : (isRefreshingSchema ? 'Refreshing schema...' : `Delete ${graph.name}`)}
+ data-testid={`delete-graph-btn-${graph.id}`}
+ >
+
+
+
+ );
+ })}
+ {graphs.length === 0 && (
+
+ No databases available
+
+ )}
+
+
+
+ Connect to Database
+ Connect DB
+
+ e.preventDefault()}
+ data-testid="upload-schema-btn"
+ >
+ Upload Schema
+
+
+
+
+ {/* Chat Interface - Full remaining height */}
+
+
+
+ {/* Modals */}
+ {
+ setShowLoginModal(open);
+ if (!open) {
+ // Remember dismissal for this session to avoid pinning the modal
+ sessionStorage.setItem('loginModalDismissed', '1');
+ }
+ }}
+ canClose={true}
+ />
+
+
+
+
+ );
+};
+
+export default Index;
diff --git a/app/src/pages/NotFound.tsx b/app/src/pages/NotFound.tsx
new file mode 100644
index 00000000..5aff64c0
--- /dev/null
+++ b/app/src/pages/NotFound.tsx
@@ -0,0 +1,24 @@
+import { useLocation, Link } from "react-router-dom";
+import { useEffect } from "react";
+
+const NotFound = () => {
+ const location = useLocation();
+
+ useEffect(() => {
+ console.error("404 Error: User attempted to access non-existent route:", location.pathname);
+ }, [location.pathname]);
+
+ return (
+
+
+
404
+
Oops! Page not found
+
+ Return to Home
+
+
+
+ );
+};
+
+export default NotFound;
diff --git a/app/src/services/auth.ts b/app/src/services/auth.ts
new file mode 100644
index 00000000..24a3d787
--- /dev/null
+++ b/app/src/services/auth.ts
@@ -0,0 +1,124 @@
+import { API_CONFIG, buildApiUrl } from '@/config/api';
+import type { AuthStatus, User } from '@/types/api';
+
+/**
+ * Authentication Service
+ * Handles OAuth authentication with Google and GitHub
+ */
+
+export class AuthService {
+ /**
+ * Check current authentication status
+ */
+ static async checkAuthStatus(): Promise {
+ try {
+ const response = await fetch(buildApiUrl(API_CONFIG.ENDPOINTS.AUTH_STATUS), {
+ credentials: 'include', // Important: include cookies for session
+ });
+
+ // 403 = Not authenticated (normal state - user can still use the app)
+ if (response.status === 403) {
+ console.log('Not authenticated - you can still use QueryWeaver, sign in to save databases');
+ return { authenticated: false };
+ }
+
+ if (!response.ok) {
+ return { authenticated: false };
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ // Backend not available - return unauthenticated for demo mode
+ console.log('Backend not available for auth - using demo mode');
+ return { authenticated: false };
+ }
+ }
+
+ /**
+ * Check if backend is available
+ */
+ static async checkBackendAvailable(): Promise {
+ try {
+ await fetch(buildApiUrl('/health').replace('/health', ''), {
+ method: 'HEAD',
+ mode: 'no-cors'
+ });
+ return true;
+ } catch (error) {
+ return false;
+ }
+ }
+
+ /**
+ * Initiate Google OAuth login
+ * Redirects to Google OAuth flow
+ */
+ static async loginWithGoogle(): Promise {
+ try {
+ // First check if backend is available
+ const url = buildApiUrl(API_CONFIG.ENDPOINTS.LOGIN_GOOGLE);
+ console.log('Redirecting to Google OAuth:', url);
+
+ // Just redirect - let the backend handle the OAuth flow
+ window.location.href = url;
+ } catch (error) {
+ console.error('Failed to initiate Google login:', error);
+ throw new Error('Failed to connect to authentication service. Please ensure the backend is running and OAuth is configured.');
+ }
+ }
+
+ /**
+ * Initiate GitHub OAuth login
+ * Redirects to GitHub OAuth flow
+ */
+ static async loginWithGithub(): Promise {
+ try {
+ const url = buildApiUrl(API_CONFIG.ENDPOINTS.LOGIN_GITHUB);
+ console.log('Redirecting to GitHub OAuth:', url);
+
+ // Just redirect - let the backend handle the OAuth flow
+ window.location.href = url;
+ } catch (error) {
+ console.error('Failed to initiate GitHub login:', error);
+ throw new Error('Failed to connect to authentication service. Please ensure the backend is running and OAuth is configured.');
+ }
+ }
+
+ /**
+ * Logout current user
+ */
+ static async logout(): Promise {
+ try {
+ await fetch(buildApiUrl(API_CONFIG.ENDPOINTS.LOGOUT), {
+ method: 'POST',
+ credentials: 'include',
+ });
+ } catch (error) {
+ console.error('Failed to logout:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get current user information
+ */
+ static async getCurrentUser(): Promise {
+ try {
+ const response = await fetch(buildApiUrl(API_CONFIG.ENDPOINTS.USER), {
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ return null;
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error('Failed to get current user:', error);
+ return null;
+ }
+ }
+}
+
diff --git a/app/src/services/chat.ts b/app/src/services/chat.ts
new file mode 100644
index 00000000..445c9b2d
--- /dev/null
+++ b/app/src/services/chat.ts
@@ -0,0 +1,276 @@
+import { API_CONFIG, buildApiUrl } from '@/config/api';
+import type { ChatRequest, StreamMessage, ConfirmRequest } from '@/types/api';
+
+/**
+ * Chat/Query Service
+ * Handles streaming chat queries to the QueryWeaver backend
+ */
+
+export class ChatService {
+ /**
+ * Send a chat query and receive streaming responses
+ * Returns an async generator that yields StreamMessage objects
+ */
+ static async *streamQuery(request: ChatRequest): AsyncGenerator {
+ try {
+ // The backend expects POST /graphs/{database_id}
+ const endpoint = `/graphs/${encodeURIComponent(request.database)}`;
+
+ // Transform conversation history to backend format
+ // Backend expects: chat: ["user msg", "ai msg", "user msg", ...]
+ const chatHistory: string[] = [];
+ if (request.history && request.history.length > 0) {
+ for (const msg of request.history) {
+ chatHistory.push(msg.content);
+ }
+ }
+ // Add current query to the chat array
+ chatHistory.push(request.query);
+
+ const response = await fetch(buildApiUrl(endpoint), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ chat: chatHistory,
+ // Optional fields the backend supports:
+ // result: [], // Previous results if needed
+ // instructions: "" // Additional instructions if needed
+ }),
+ credentials: 'include',
+ });
+
+ console.log('Chat response status:', response.status);
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ console.error('Chat error response:', errorText);
+
+ try {
+ const errorData = JSON.parse(errorText);
+ const errorMessage = errorData.error || errorData.detail || errorData.message || 'Failed to send query';
+ throw new Error(errorMessage);
+ } catch (parseError) {
+ // If JSON parsing fails, use the text directly
+ throw new Error(errorText || `Request failed with status ${response.status}`);
+ }
+ }
+
+ if (!response.body) {
+ throw new Error('No response body');
+ }
+
+ // Read the streaming response
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = '';
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+
+ if (done) {
+ console.log('Stream done. Final buffer:', buffer);
+ break;
+ }
+
+ // Decode the chunk and add to buffer
+ const chunk = decoder.decode(value, { stream: true });
+ console.log('Received chunk:', chunk);
+ buffer += chunk;
+
+ // Split by boundary marker
+ const parts = buffer.split(API_CONFIG.STREAM_BOUNDARY);
+ console.log('Split into parts:', parts.length, 'parts');
+
+ // Keep the last part in buffer (might be incomplete)
+ buffer = parts.pop() || '';
+
+ // Process complete messages
+ for (const part of parts) {
+ const trimmed = part.trim();
+ if (!trimmed) continue;
+
+ console.log('Processing message part:', trimmed);
+ try {
+ const message: StreamMessage = JSON.parse(trimmed);
+ console.log('Parsed message:', message);
+ yield message;
+ } catch (e) {
+ console.error('Failed to parse stream message:', trimmed, e);
+ // Yield error message instead of silently failing
+ yield {
+ type: 'error',
+ content: `Failed to parse server response: ${trimmed.substring(0, 100)}...`
+ } as StreamMessage;
+ }
+ }
+ }
+
+ // Process any remaining buffer
+ if (buffer.trim()) {
+ try {
+ const message: StreamMessage = JSON.parse(buffer.trim());
+ yield message;
+ } catch (e) {
+ console.error('Failed to parse final message:', buffer, e);
+ yield {
+ type: 'error',
+ content: `Failed to parse final server response`
+ } as StreamMessage;
+ }
+ }
+ } catch (streamError) {
+ console.error('Stream reading error:', streamError);
+ yield {
+ type: 'error',
+ content: `Stream error: ${streamError instanceof Error ? streamError.message : 'Unknown streaming error'}`
+ } as StreamMessage;
+ }
+ } catch (error) {
+ console.error('Failed to stream query:', error);
+
+ // Yield error message before throwing
+ yield {
+ type: 'error',
+ content: error instanceof Error ? error.message : 'Unknown error occurred'
+ } as StreamMessage;
+
+ throw error;
+ }
+ }
+
+ /**
+ * Confirm a destructive SQL operation and stream results
+ * Used when the backend requires confirmation for INSERT/UPDATE/DELETE
+ */
+ static async *streamConfirmOperation(
+ database: string,
+ request: ConfirmRequest
+ ): AsyncGenerator {
+ try {
+ // The backend expects POST /graphs/{database}/confirm
+ const endpoint = `/graphs/${encodeURIComponent(database)}/confirm`;
+
+ const response = await fetch(buildApiUrl(endpoint), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(request),
+ credentials: 'include',
+ });
+
+ console.log('Confirmation response status:', response.status);
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ console.error('Confirmation error response:', errorText);
+
+ try {
+ const errorData = JSON.parse(errorText);
+ const errorMessage = errorData.error || errorData.detail || errorData.message || 'Failed to confirm operation';
+ throw new Error(errorMessage);
+ } catch (parseError) {
+ throw new Error(errorText || `Request failed with status ${response.status}`);
+ }
+ }
+
+ if (!response.body) {
+ throw new Error('No response body');
+ }
+
+ // Read the streaming response (same logic as streamQuery)
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder();
+ let buffer = '';
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read();
+
+ if (done) {
+ console.log('Confirmation stream done. Final buffer:', buffer);
+ break;
+ }
+
+ const chunk = decoder.decode(value, { stream: true });
+ console.log('Received confirmation chunk:', chunk);
+ buffer += chunk;
+
+ const parts = buffer.split(API_CONFIG.STREAM_BOUNDARY);
+ console.log('Split into parts:', parts.length, 'parts');
+
+ buffer = parts.pop() || '';
+
+ for (const part of parts) {
+ const trimmed = part.trim();
+ if (!trimmed) continue;
+
+ console.log('Processing confirmation message part:', trimmed);
+ try {
+ const message: StreamMessage = JSON.parse(trimmed);
+ console.log('Parsed confirmation message:', message);
+ yield message;
+ } catch (e) {
+ console.error('Failed to parse confirmation stream message:', trimmed, e);
+ yield {
+ type: 'error',
+ content: `Failed to parse server response: ${trimmed.substring(0, 100)}...`
+ } as StreamMessage;
+ }
+ }
+ }
+
+ // Process any remaining buffer
+ if (buffer.trim()) {
+ try {
+ const message: StreamMessage = JSON.parse(buffer.trim());
+ yield message;
+ } catch (e) {
+ console.error('Failed to parse final confirmation message:', buffer, e);
+ yield {
+ type: 'error',
+ content: `Failed to parse final server response`
+ } as StreamMessage;
+ }
+ }
+ } catch (streamError) {
+ console.error('Confirmation stream reading error:', streamError);
+ yield {
+ type: 'error',
+ content: `Stream error: ${streamError instanceof Error ? streamError.message : 'Unknown streaming error'}`
+ } as StreamMessage;
+ }
+ } catch (error) {
+ console.error('Failed to stream confirmation:', error);
+
+ yield {
+ type: 'error',
+ content: error instanceof Error ? error.message : 'Unknown error occurred'
+ } as StreamMessage;
+
+ throw error;
+ }
+ }
+
+ /**
+ * Helper function to consume the stream and collect all messages
+ * Useful for simpler use cases where you want all messages at once
+ */
+ static async executeQuery(request: ChatRequest): Promise {
+ const messages: StreamMessage[] = [];
+
+ try {
+ for await (const message of ChatService.streamQuery(request)) {
+ messages.push(message);
+ }
+ return messages;
+ } catch (error) {
+ console.error('Failed to execute query:', error);
+ throw error;
+ }
+ }
+}
+
diff --git a/app/src/services/database.ts b/app/src/services/database.ts
new file mode 100644
index 00000000..15ca9ceb
--- /dev/null
+++ b/app/src/services/database.ts
@@ -0,0 +1,254 @@
+import { API_CONFIG, buildApiUrl } from '@/config/api';
+import type { Graph, GraphUploadResponse, SchemaUploadRequest } from '@/types/api';
+
+/**
+ * Database/Graph Management Service
+ * Handles database schema uploads and graph management
+ */
+
+export class DatabaseService {
+ /**
+ * Get all graphs/databases for the current user
+ */
+ static async getGraphs(): Promise {
+ try {
+ const url = buildApiUrl(API_CONFIG.ENDPOINTS.GRAPHS);
+ console.log('Fetching graphs from:', url);
+
+ const response = await fetch(url, {
+ credentials: 'include',
+ });
+
+ console.log('Graphs response status:', response.status);
+
+ // 401/403 = Not authenticated - this is normal if user hasn't signed in
+ if (response.status === 401 || response.status === 403) {
+ console.log('Not authenticated - sign in to access saved databases');
+ return [];
+ }
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ console.error('Failed to fetch graphs:', response.status, errorText);
+ throw new Error('Failed to fetch graphs');
+ }
+
+ const data = await response.json();
+ console.log('Graphs data received:', data);
+
+ // Backend returns array of strings like ["northwind", "chinook"]
+ // Transform to Graph objects
+ const graphNames = data.graphs || data || [];
+
+ if (Array.isArray(graphNames) && graphNames.length > 0 && typeof graphNames[0] === 'string') {
+ // Transform string array to Graph objects
+ return graphNames.map((name: string) => ({
+ id: name,
+ name: name,
+ created_at: new Date().toISOString(),
+ updated_at: new Date().toISOString(),
+ }));
+ }
+
+ // If already objects, return as is
+ return graphNames;
+ } catch (error) {
+ // Backend not available - return empty array for demo mode
+ console.log('Backend not available for graphs - using demo mode', error);
+ return [];
+ }
+ }
+
+ /**
+ * Get a specific graph by ID
+ */
+ static async getGraph(id: string): Promise {
+ try {
+ const response = await fetch(
+ buildApiUrl(API_CONFIG.ENDPOINTS.GRAPH_BY_ID(id)),
+ {
+ credentials: 'include',
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error('Failed to fetch graph');
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error('Failed to get graph:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get graph data (nodes and links) for schema visualization
+ */
+ static async getGraphData(id: string): Promise<{ nodes: any[]; links: any[] }> {
+ try {
+ const response = await fetch(
+ buildApiUrl(`/graphs/${encodeURIComponent(id)}/data`),
+ {
+ credentials: 'include',
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error('Failed to fetch graph data');
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error('Failed to get graph data:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Upload database schema file
+ * Accepts SQL files, CSV files, or JSON schema definitions
+ */
+ static async uploadSchema(request: SchemaUploadRequest): Promise {
+ try {
+ const formData = new FormData();
+ formData.append('file', request.file);
+
+ if (request.database_name) {
+ formData.append('database', request.database_name);
+ }
+
+ if (request.description) {
+ formData.append('description', request.description);
+ }
+
+ const response = await fetch(buildApiUrl(API_CONFIG.ENDPOINTS.UPLOAD_SCHEMA), {
+ method: 'POST',
+ body: formData,
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.error || 'Failed to upload schema');
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.log('Backend not available for schema upload - demo mode only');
+ // Check if it's a network error (backend not running)
+ if (error instanceof TypeError && error.message === 'Failed to fetch') {
+ throw new Error('Backend server is not running. Please start the QueryWeaver backend to upload schemas.');
+ }
+ throw error;
+ }
+ }
+
+ /**
+ * Delete a graph/database
+ */
+ static async deleteGraph(id: string): Promise {
+ try {
+ const response = await fetch(
+ buildApiUrl(API_CONFIG.ENDPOINTS.DELETE_GRAPH(id)),
+ {
+ method: 'DELETE',
+ credentials: 'include',
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error('Failed to delete graph');
+ }
+ } catch (error) {
+ console.error('Failed to delete graph:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Connect to an external database using connection URL
+ * Format: postgresql://user:pass@host:port/database or mysql://user:pass@host:port/database
+ */
+ static async connectDatabaseUrl(config: {
+ type: string;
+ connectionUrl: string;
+ }): Promise {
+ try {
+ const response = await fetch(buildApiUrl('/database'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ url: config.connectionUrl,
+ }),
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.error || 'Failed to connect to database');
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.log('Backend not available for database connection - demo mode only');
+ // Check if it's a network error (backend not running)
+ if (error instanceof TypeError && error.message === 'Failed to fetch') {
+ throw new Error('Backend server is not running. Please start the QueryWeaver backend to connect to databases.');
+ }
+ throw error;
+ }
+ }
+
+ /**
+ * Connect to an external database using individual parameters
+ * This would require backend implementation for direct database connections
+ */
+ static async connectDatabase(config: {
+ type: string;
+ host: string;
+ port: number;
+ database: string;
+ username: string;
+ password: string;
+ }): Promise {
+ try {
+ // Build connection URL from individual parameters
+ const protocol = config.type === 'mysql' ? 'mysql' : 'postgresql';
+ const connectionUrl = `${protocol}://${encodeURIComponent(config.username)}:${encodeURIComponent(config.password)}@${config.host}:${config.port}/${encodeURIComponent(config.database)}`;
+
+ const response = await fetch(buildApiUrl('/database'), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ url: connectionUrl,
+ }),
+ credentials: 'include',
+ });
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.error || 'Failed to connect to database');
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.log('Backend not available for database connection - demo mode only');
+ // Check if it's a network error (backend not running)
+ if (error instanceof TypeError && error.message === 'Failed to fetch') {
+ throw new Error('Backend server is not running. Please start the QueryWeaver backend to connect to databases.');
+ }
+ throw error;
+ }
+ }
+}
+
diff --git a/app/src/services/tokens.ts b/app/src/services/tokens.ts
new file mode 100644
index 00000000..61b1125e
--- /dev/null
+++ b/app/src/services/tokens.ts
@@ -0,0 +1,113 @@
+/**
+ * Token management service
+ */
+
+import { buildApiUrl } from '@/config/api';
+
+export interface Token {
+ token_id: string;
+ created_at: number;
+}
+
+export interface TokenListResponse {
+ tokens: Token[];
+}
+
+export class TokenService {
+ /**
+ * Generate a new API token
+ */
+ static async generateToken(): Promise {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
+
+ try {
+ const response = await fetch(buildApiUrl('/tokens/generate'), {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ signal: controller.signal,
+ });
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.message || `Failed to generate token: ${response.statusText}`);
+ }
+
+ return response.json();
+ } catch (error) {
+ clearTimeout(timeoutId);
+ if (error instanceof Error && error.name === 'AbortError') {
+ throw new Error('Request timeout: Failed to generate token');
+ }
+ throw error;
+ }
+ }
+
+ /**
+ * List all tokens for the authenticated user
+ */
+ static async listTokens(): Promise {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
+
+ try {
+ const response = await fetch(buildApiUrl('/tokens/list'), {
+ method: 'GET',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ signal: controller.signal,
+ });
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.message || `Failed to list tokens: ${response.statusText}`);
+ }
+
+ return response.json();
+ } catch (error) {
+ clearTimeout(timeoutId);
+ if (error instanceof Error && error.name === 'AbortError') {
+ throw new Error('Request timeout: Failed to list tokens');
+ }
+ throw error;
+ }
+ }
+
+ /**
+ * Delete a specific token
+ */
+ static async deleteToken(tokenId: string): Promise {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
+
+ try {
+ const response = await fetch(buildApiUrl(`/tokens/${tokenId}`), {
+ method: 'DELETE',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ signal: controller.signal,
+ });
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}));
+ throw new Error(errorData.message || `Failed to delete token: ${response.statusText}`);
+ }
+ } catch (error) {
+ clearTimeout(timeoutId);
+ if (error instanceof Error && error.name === 'AbortError') {
+ throw new Error('Request timeout: Failed to delete token');
+ }
+ throw error;
+ }
+ }
+}
diff --git a/app/src/types/api.ts b/app/src/types/api.ts
new file mode 100644
index 00000000..04e46ede
--- /dev/null
+++ b/app/src/types/api.ts
@@ -0,0 +1,105 @@
+// API Types and Interfaces
+
+// User types
+export interface User {
+ id: string;
+ email: string;
+ name?: string;
+ picture?: string;
+ provider?: 'google' | 'github';
+}
+
+// Authentication types
+export interface AuthStatus {
+ authenticated: boolean;
+ user?: User;
+}
+
+// Graph/Database types
+export interface Graph {
+ id: string;
+ name: string;
+ description?: string;
+ created_at: string;
+ updated_at: string;
+ table_count?: number;
+ schema?: any;
+}
+
+export interface GraphUploadResponse {
+ graph_id: string;
+ message: string;
+ tables?: string[];
+}
+
+// Chat message types
+export interface ChatRequest {
+ query: string;
+ database: string;
+ history?: ConversationMessage[];
+}
+
+export interface ConversationMessage {
+ role: 'user' | 'assistant';
+ content: string;
+}
+
+// Streaming response types
+export type StreamMessageType =
+ | 'reasoning'
+ | 'reasoning_step' // Backend sends this for step updates
+ | 'sql'
+ | 'sql_query' // Backend sends this for SQL queries
+ | 'result'
+ | 'query_result' // Backend sends this for query results
+ | 'ai_response' // Backend sends this for AI-generated responses
+ | 'error'
+ | 'followup'
+ | 'followup_questions' // Backend sends this when query needs clarification
+ | 'confirmation'
+ | 'destructive_confirmation' // Backend sends this for destructive operations
+ | 'schema_refresh' // Backend sends this after schema modifications
+ | 'status';
+
+export interface StreamMessage {
+ type: StreamMessageType;
+ content?: string;
+ message?: string; // Some backend messages use 'message' instead of 'content'
+ data?: any;
+ step?: string;
+ require_confirmation?: boolean;
+ confirmation_id?: string;
+ final_response?: boolean;
+ conf?: number; // Confidence score
+ miss?: string; // Missing information
+ amb?: string; // Ambiguities
+ exp?: string; // Explanation
+ is_valid?: boolean;
+ missing_information?: string; // For followup_questions
+ ambiguities?: string; // For followup_questions
+ sql_query?: string; // For destructive_confirmation
+ operation_type?: string; // For destructive_confirmation
+ refresh_status?: string; // For schema_refresh
+}
+
+// Confirmation types
+export interface ConfirmRequest {
+ sql_query: string; // The SQL query to execute
+ confirmation: string; // "CONFIRM" or "" (empty for cancel)
+ chat: string[]; // Conversation history
+}
+
+// Upload types
+export interface SchemaUploadRequest {
+ file: File;
+ database_name?: string;
+ description?: string;
+}
+
+// API Error
+export interface ApiError {
+ error: string;
+ detail?: string;
+ status?: number;
+}
+
diff --git a/app/tailwind.config.ts b/app/tailwind.config.ts
new file mode 100644
index 00000000..7ef8e59a
--- /dev/null
+++ b/app/tailwind.config.ts
@@ -0,0 +1,102 @@
+import type { Config } from "tailwindcss";
+
+export default {
+ darkMode: ["class"],
+ content: [
+ "./index.html",
+ "./src/**/*.{ts,tsx,js,jsx}",
+ ],
+ prefix: "",
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ fontFamily: {
+ sans: ['Inter', 'system-ui', 'sans-serif'],
+ mono: ['Fira Code', 'monospace'],
+ },
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ glow: "hsl(var(--primary-glow))",
+ dark: "hsl(var(--primary-dark))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ sidebar: {
+ DEFAULT: "hsl(var(--sidebar-background))",
+ foreground: "hsl(var(--sidebar-foreground))",
+ primary: "hsl(var(--sidebar-primary))",
+ "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
+ accent: "hsl(var(--sidebar-accent))",
+ "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
+ border: "hsl(var(--sidebar-border))",
+ ring: "hsl(var(--sidebar-ring))",
+ },
+ "google-blue": "hsl(var(--google-blue))",
+ "github-dark": "hsl(var(--github-dark))",
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: {
+ height: "0",
+ },
+ to: {
+ height: "var(--radix-accordion-content-height)",
+ },
+ },
+ "accordion-up": {
+ from: {
+ height: "var(--radix-accordion-content-height)",
+ },
+ to: {
+ height: "0",
+ },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+} satisfies Config;
diff --git a/app/templates/base.j2 b/app/templates/base.j2
deleted file mode 100644
index 4c9ad1b0..00000000
--- a/app/templates/base.j2
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
- {% block title %}Chatbot Interface{% endblock %}
-
-
- {% block extra_css %}{% endblock %}
- {% if google_tag_manager_id %}
-
-
-
- {% endif %}
-
-
-
-
- {% if google_tag_manager_id %}
-
-
-
- {% endif %}
- {% block toolbar %}{% endblock %}
-
- {% block content %}{% endblock %}
-
- {% block modals %}{% endblock %}
-
-
- Powered by
-
-
-
-{% block scripts %}
- {# Set authentication state for JS #}
-
-{% endblock %}
-
-
diff --git a/app/templates/chat.j2 b/app/templates/chat.j2
deleted file mode 100644
index d39e76c5..00000000
--- a/app/templates/chat.j2
+++ /dev/null
@@ -1,41 +0,0 @@
-{% extends "base.j2" %}
-
-{% block title %}QueryWeaver Chat Interface{% endblock %}
-
-{% block toolbar %}
- {% include 'components/toolbar.j2' %}
-{% endblock %}
-
-{% block content %}
-
- {% include 'components/left_toolbar.j2' %}
- {% include 'components/sidebar_menu.j2' %}
-
- {% include 'components/sidebar_schema.j2' %}
-
-
-
-
- {% include 'components/chat_header.j2' %}
-
-
-
-
- {% include 'components/chat_input.j2' %}
-
-
-{% endblock %}
-
-{% block modals %}
- {% include 'components/login_modal.j2' %}
- {% include 'components/database_modal.j2' %}
- {% include 'components/reset_modal.j2' %}
- {% if is_authenticated %}
- {% include 'components/token_modal.j2' %}
- {% endif %}
-{% endblock %}
-
-{% block scripts %}
- {{ super() }}
- {% include 'components/scripts.j2' %}
-{% endblock %}
diff --git a/app/templates/components/chat_header.j2 b/app/templates/components/chat_header.j2
deleted file mode 100644
index dbdfc829..00000000
--- a/app/templates/components/chat_header.j2
+++ /dev/null
@@ -1,31 +0,0 @@
-{# Chat header with logo, title, and action buttons #}
-
\ No newline at end of file
diff --git a/app/templates/components/chat_input.j2 b/app/templates/components/chat_input.j2
deleted file mode 100644
index 5e909db1..00000000
--- a/app/templates/components/chat_input.j2
+++ /dev/null
@@ -1,32 +0,0 @@
-{# Chat input area with text input and action buttons #}
-
\ No newline at end of file
diff --git a/app/templates/components/database_modal.j2 b/app/templates/components/database_modal.j2
deleted file mode 100644
index 8d08ccac..00000000
--- a/app/templates/components/database_modal.j2
+++ /dev/null
@@ -1,47 +0,0 @@
-{# Database connection modal #}
-
-
-
Connect to Database
-
-
-
-
- -- Select Database --
- ▼
-
-
-
- -- Select Database --
-
-
-
-
PostgreSQL
-
-
-
-
MySQL
-
-
-
-
-
-
-
-
-
-
-
-
-
- Connect
-
-
- Loading Schema...
-
-
- Cancel
-
-
-
diff --git a/app/templates/components/left_toolbar.j2 b/app/templates/components/left_toolbar.j2
deleted file mode 100644
index 133e2d0d..00000000
--- a/app/templates/components/left_toolbar.j2
+++ /dev/null
@@ -1,115 +0,0 @@
-{# Left vertical toolbar to host expandable buttons (keeps future buttons easy to add) #}
-
-
-
-
\ No newline at end of file
diff --git a/app/templates/components/login_modal.j2 b/app/templates/components/login_modal.j2
deleted file mode 100644
index cb67acf9..00000000
--- a/app/templates/components/login_modal.j2
+++ /dev/null
@@ -1,110 +0,0 @@
-{# Login modal for authentication #}
-
-
-
Welcome to QueryWeaver
-
Please login to continue
-
- {# Check if any authentication method is enabled #}
- {% if not (email_auth_enabled or google_auth_enabled or github_auth_enabled) %}
-
-
- No authentication methods configured.
- Please contact your administrator to set up authentication.
-
-
- {% else %}
-
- {# Show OAuth options only if configured #}
- {% if google_auth_enabled %}
-
- Sign in with Google
-
- {% endif %}
-
- {% if github_auth_enabled %}
-
- Sign in with GitHub
-
- {% endif %}
-
- {# Show divider only if we have both OAuth and email auth enabled #}
- {% if email_auth_enabled and (google_auth_enabled or github_auth_enabled) %}
-
- or
-
- {% endif %}
-
- {# Show email auth only if enabled #}
- {% if email_auth_enabled %}
-
-
-
- Sign in with Email
-
-
-
- {% endif %}
-
- {% endif %}
-
-
-
-{# Signup modal #}
-
diff --git a/app/templates/components/menu_analytics.j2 b/app/templates/components/menu_analytics.j2
deleted file mode 100644
index 32202cec..00000000
--- a/app/templates/components/menu_analytics.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-{# Analytics section in sidebar menu #}
-
-
-
-
diff --git a/app/templates/components/menu_instructions.j2 b/app/templates/components/menu_instructions.j2
deleted file mode 100644
index 7a66c5eb..00000000
--- a/app/templates/components/menu_instructions.j2
+++ /dev/null
@@ -1,6 +0,0 @@
-{# Instructions section in sidebar menu #}
-
diff --git a/app/templates/components/reset_modal.j2 b/app/templates/components/reset_modal.j2
deleted file mode 100644
index b450840a..00000000
--- a/app/templates/components/reset_modal.j2
+++ /dev/null
@@ -1,12 +0,0 @@
-{# Reset session confirmation modal #}
-
-
-
Reset Session
-
Are you sure you want to reset the current session?
-
This will clear all chat history and start a new conversation.
-
- Reset Session
- Cancel
-
-
-
diff --git a/app/templates/components/scripts.j2 b/app/templates/components/scripts.j2
deleted file mode 100644
index 34438852..00000000
--- a/app/templates/components/scripts.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-{# JavaScript initialization and imports #}
-
-
diff --git a/app/templates/components/sidebar_menu.j2 b/app/templates/components/sidebar_menu.j2
deleted file mode 100644
index 2165d919..00000000
--- a/app/templates/components/sidebar_menu.j2
+++ /dev/null
@@ -1,15 +0,0 @@
-{# Side menu with instructions and analytics #}
-
diff --git a/app/templates/components/sidebar_schema.j2 b/app/templates/components/sidebar_schema.j2
deleted file mode 100644
index 65fdc537..00000000
--- a/app/templates/components/sidebar_schema.j2
+++ /dev/null
@@ -1,43 +0,0 @@
-{# Side Database Schema view #}
-
\ No newline at end of file
diff --git a/app/templates/components/token_modal.j2 b/app/templates/components/token_modal.j2
deleted file mode 100644
index e2423e3f..00000000
--- a/app/templates/components/token_modal.j2
+++ /dev/null
@@ -1,75 +0,0 @@
-{# Token management modal #}
-
-
-
-
-
-
- API tokens allow you to authenticate with the QueryWeaver API without using OAuth.
- Keep your tokens secure and don't share them publicly.
-
-
-
- Generate New Token
-
-
- {# Token generation success message #}
-
-
-
Token Generated Successfully!
-
Important: This is the only time you'll see this token. Copy it now and store it securely.
-
-
-
-
- {# Token list #}
-
-
Your Tokens
-
-
You don't have any API tokens yet.
-
-
-
-
- Token
- Created
- Actions
-
-
-
-
-
-
-
-
-
-
-
-
-
-{# Token deletion confirmation modal #}
-
-
-
-
-
Are you sure you want to delete this token? This action cannot be undone.
-
Token ending in:
-
- Delete Token
- Cancel
-
-
-
-
\ No newline at end of file
diff --git a/app/templates/components/toolbar.j2 b/app/templates/components/toolbar.j2
deleted file mode 100644
index 9732beef..00000000
--- a/app/templates/components/toolbar.j2
+++ /dev/null
@@ -1,18 +0,0 @@
-{# Top toolbar with theme toggle, GitHub link, and user profile #}
-
-
-
-
-
-
-
-
-
- -
-
-
-{% if is_authenticated and user_info %}
-{% include 'components/user_profile.j2' %}
-{% endif %}
\ No newline at end of file
diff --git a/app/templates/components/user_profile.j2 b/app/templates/components/user_profile.j2
deleted file mode 100644
index 5f54f790..00000000
--- a/app/templates/components/user_profile.j2
+++ /dev/null
@@ -1,19 +0,0 @@
-{# User profile button and dropdown #}
-
- {% if user_info.picture %}
-
- {% else %}
- {{ user_info.name[0] | upper }}
- {% endif %}
-
-
-
-
{{ user_info.name }}
-
{{ user_info.email }}
-
-
- API Tokens
- Logout
-
-
diff --git a/app/ts/app.ts b/app/ts/app.ts
deleted file mode 100644
index c99a01f5..00000000
--- a/app/ts/app.ts
+++ /dev/null
@@ -1,279 +0,0 @@
-/**
- * Main application entry point (TypeScript)
- */
-
-import { DOM } from "./modules/config";
-import { initChat } from "./modules/messages";
-import { sendMessage, pauseRequest } from "./modules/chat";
-import { loadGraphs, handleFileUpload, onGraphChange } from "./modules/graphs";
-import { getSelectedGraph } from "./modules/graph_select";
-import {
- toggleContainer,
- showResetConfirmation,
- hideResetConfirmation,
- handleResetConfirmation,
- setupUserProfileDropdown,
- setupThemeToggle,
- setupToolbar,
- handleWindowResize,
- setupCustomDropdown,
- setupResizeHandles,
-} from "./modules/ui";
-import { setupAuthenticationModal, setupDatabaseModal } from "./modules/modals";
-import { resizeGraph, showGraph } from "./modules/schema";
-import { setupTokenManagement } from "./modules/tokens";
-import { initLeftToolbar } from "./modules/left_toolbar";
-import { setupTextareaAutoResize } from "./modules/input";
-
-async function loadAndShowGraph(selected: string | undefined) {
- if (!selected || selected === "Select Database") return;
- try {
- const resp = await fetch(`/graphs/${encodeURIComponent(selected)}/data`);
- if (!resp.ok) {
- console.error("Failed to load graph data:", resp.status, resp.statusText);
- return;
- }
-
- const data = await resp.json();
-
- if (!data || !Array.isArray(data.nodes) || !Array.isArray(data.links)) {
- console.warn(
- "Graph data returned in unexpected shape, showing empty message",
- data
- );
- return;
- }
-
- const container = document.getElementById("schema-graph");
- if (container) container.innerHTML = "";
-
- showGraph(data);
- } catch (err) {
- console.error("Error fetching graph data:", err);
- }
-}
-
-function updateInputState() {
- const submitButton = DOM.submitButton;
- const messageInput = DOM.messageInput;
- if (!submitButton || !messageInput) return;
-
- const selected = getSelectedGraph();
- const isDatabaseSelected = selected && selected !== "Select Database";
-
- if (isDatabaseSelected) {
- messageInput.disabled = false;
- messageInput.placeholder = "Describe the SQL query you want...";
- // Enable submit button only if there's also text in the input
- if (messageInput.value.trim()) {
- submitButton.disabled = false;
- } else {
- submitButton.disabled = true;
- }
- } else {
- messageInput.disabled = true;
- messageInput.placeholder = "Please select a database first...";
- submitButton.disabled = true;
- }
-}
-
-function initializeApp() {
- initChat();
- setupEventListeners();
- setupUIComponents();
- loadInitialData();
-}
-
-function setupEventListeners() {
- DOM.submitButton?.addEventListener("click", sendMessage);
- DOM.pauseButton?.addEventListener("click", pauseRequest);
- DOM.messageInput?.addEventListener("keydown", (e: KeyboardEvent) => {
- if ((e as KeyboardEvent).key === "Enter" && !e.shiftKey) {
- e.preventDefault();
- sendMessage();
- }
- });
-
- DOM.messageInput?.addEventListener("input", () => {
- updateInputState();
- });
-
- DOM.menuButton?.addEventListener("click", () =>
- toggleContainer(DOM.menuContainer as HTMLElement)
- );
-
- DOM.schemaButton?.addEventListener("click", () => {
- toggleContainer(DOM.schemaContainer as HTMLElement, async () => {
- const selected = getSelectedGraph();
- if (!selected) return;
- loadAndShowGraph(selected);
- setTimeout(resizeGraph, 450);
- });
- });
-
- DOM.graphSelectRefresh?.addEventListener("click", async () => {
- const selected = getSelectedGraph();
- const refreshButton = DOM.graphSelectRefresh;
-
- if (!refreshButton) return;
-
- if (!selected || selected === "Select Database")
- return console.debug("No selected graph");
-
- // Check if selected database is a demo database
- const generalPrefix = (window as any).generalPrefix;
- const isDemo = generalPrefix && selected.startsWith(generalPrefix);
-
- if (isDemo) {
- console.debug("Refresh is disabled for demo databases");
- return;
- }
-
- refreshButton.classList.add("loading");
-
- const result = await fetch(
- `/graphs/${encodeURIComponent(selected)}/refresh`,
- {
- method: "POST",
- }
- );
-
- if (!result.ok) {
- console.error(
- "Failed to refresh graph:",
- result.status,
- result.statusText
- );
- return;
- }
-
- if (result.body) {
- const reader = result.body.getReader();
- const decoder = new TextDecoder();
- let buffer = "";
-
- try {
- while (true) {
- const { done, value } = await reader.read();
- if (done) break;
-
- buffer += decoder.decode(value, { stream: true });
-
- // Process complete messages separated by boundary
- const messages = buffer.split("|||FALKORDB_MESSAGE_BOUNDARY|||");
- buffer = messages.pop() || ""; // Keep incomplete message in buffer
-
- for (const message of messages) {
- if (message.trim()) {
- try {
- const parsed = JSON.parse(message.trim());
-
- if (parsed.type === "reasoning_step") {
- refreshButton.title += ` ${parsed.message}\n`;
- } else if (parsed.type === "final_result") {
- refreshButton.title += ` ${parsed.message}`;
- }
- } catch (e) {
- console.warn("Failed to parse message:", message, e);
- }
- }
- }
- }
- } finally {
- reader.releaseLock();
- }
- }
-
- if (DOM.schemaContainer && DOM.schemaContainer.classList.contains("open")) {
- await loadAndShowGraph(selected);
- setTimeout(resizeGraph, 450);
- }
-
- refreshButton.classList.remove("loading");
- refreshButton.title = "";
- });
-
- DOM.newChatButton?.addEventListener("click", showResetConfirmation);
- DOM.resetConfirmBtn?.addEventListener("click", handleResetConfirmation);
- DOM.resetCancelBtn?.addEventListener("click", hideResetConfirmation);
-
- DOM.resetConfirmationModal?.addEventListener("click", (e) => {
- if (e.target === DOM.resetConfirmationModal) hideResetConfirmation();
- });
-
- document.addEventListener("keydown", (e) => {
- if (
- (e as KeyboardEvent).key === "Escape" &&
- DOM.resetConfirmationModal &&
- DOM.resetConfirmationModal.style.display === "flex"
- ) {
- hideResetConfirmation();
- }
- });
-
- // Legacy select is hidden; custom UI will trigger load via graph_select helper
- document
- .getElementById("graph-options")
- ?.addEventListener("click", async () => {
- onGraphChange();
- const selected = getSelectedGraph();
- if (!selected) return;
- const selectedLabel = document.getElementById("graph-selected");
- if (selectedLabel) {
- const dropdownText = selectedLabel.querySelector(
- ".dropdown-text"
- ) as HTMLElement | null;
- if (dropdownText) {
- dropdownText.textContent = selected;
- dropdownText.title = selected;
- }
- }
- if (
- DOM.schemaContainer &&
- DOM.schemaContainer.classList.contains("open")
- ) {
- loadAndShowGraph(selected);
- setTimeout(resizeGraph, 450);
- }
- });
-
- DOM.fileUpload?.addEventListener("change", handleFileUpload);
- window.addEventListener("resize", handleWindowResize);
-
- // Expose toggleSidebar function globally for HTML template onclick handlers
- (window as any).toggleSidebar = function(containerId: string) {
- const container = document.getElementById(containerId) as HTMLElement;
- if (container) {
- toggleContainer(container, containerId === 'schema-container' ? async () => {
- const selected = getSelectedGraph();
- if (!selected) return;
- loadAndShowGraph(selected);
- setTimeout(resizeGraph, 450);
- } : undefined);
- }
- };
-}
-
-function setupUIComponents() {
- setupUserProfileDropdown();
- setupThemeToggle();
- setupAuthenticationModal();
- setupDatabaseModal();
- setupTokenManagement();
- setupToolbar();
- // initialize left toolbar behavior (burger, responsive default)
- initLeftToolbar();
- setupCustomDropdown();
- setupTextareaAutoResize();
- setupResizeHandles();
-}
-
-function loadInitialData() {
- loadGraphs();
- updateInputState(); // Set initial input state based on database selection
-}
-
-// Expose updateInputState globally so other modules can use it
-(window as any).updateInputState = updateInputState;
-
-document.addEventListener("DOMContentLoaded", initializeApp);
diff --git a/app/ts/modules/chat.ts b/app/ts/modules/chat.ts
deleted file mode 100644
index 6a7f60ce..00000000
--- a/app/ts/modules/chat.ts
+++ /dev/null
@@ -1,293 +0,0 @@
-/**
- * Chat API and messaging functionality (TypeScript)
- */
-
-import { DOM, state, MESSAGE_DELIMITER } from './config';
-import { addMessage, removeLoadingMessage, moveLoadingMessageToBottom } from './messages';
-import { getSelectedGraph } from './graph_select';
-import { adjustTextareaHeight } from './input';
-
-export async function sendMessage() {
- const message = (DOM.messageInput?.value || '').trim();
-
- if (!message) return;
-
- const selectedValue = getSelectedGraph();
-
- if (!selectedValue || selectedValue === "Select Database") return console.debug("No selected graph");
-
- if (state.currentRequestController) {
- state.currentRequestController.abort();
- }
-
- addMessage(message, "user", false, (window as any).currentUser || null);
- if (DOM.messageInput) {
- DOM.messageInput.value = '';
- adjustTextareaHeight();
- }
-
- // Show typing indicator
- DOM.inputContainer?.classList.add('loading');
- if (DOM.submitButton) DOM.submitButton.style.display = 'none';
- if (DOM.pauseButton) DOM.pauseButton.style.display = 'flex';
- if (DOM.newChatButton) DOM.newChatButton.disabled = true;
- addMessage('', "loading");
-
- [DOM.confValue, DOM.expValue, DOM.missValue, DOM.ambValue].forEach((element) => {
- if (element) element.innerHTML = '';
- });
-
- try {
- state.currentRequestController = new AbortController();
-
- const response = await fetch('/graphs/' + encodeURIComponent(selectedValue) + '?q=' + encodeURIComponent(message), {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- chat: state.questions_history,
- result: state.result_history,
- instructions: DOM.expInstructions?.value
- }),
- signal: state.currentRequestController.signal
- });
-
- if (!response.ok) {
- throw new Error(`Server responded with ${response.status}`);
- }
-
- await processStreamingResponse(response);
- state.currentRequestController = null;
- } catch (error: any) {
- if (error.name === 'AbortError') {
- console.log('Request was aborted');
- } else {
- console.error('Error:', error);
- resetUIState();
- addMessage('Sorry, there was an error processing your message: ' + (error.message || String(error)));
- }
- state.currentRequestController = null;
- }
-}
-
-async function processStreamingResponse(response: Response) {
- if (!response.body) return;
- const reader = response.body.getReader();
- const decoder = new TextDecoder();
- let buffer = '';
-
- while (true) {
- const { done, value } = await reader.read();
- if (done) {
- if (buffer.trim()) {
- try {
- const step = JSON.parse(buffer);
- addMessage(step.message || JSON.stringify(step));
- } catch {
- addMessage(buffer);
- }
- }
- break;
- }
-
- const chunk = decoder.decode(value, { stream: true });
- buffer += chunk;
-
- let delimiterIndex: number;
- while ((delimiterIndex = buffer.indexOf(MESSAGE_DELIMITER)) !== -1) {
- const message = buffer.slice(0, delimiterIndex).trim();
- buffer = buffer.slice(delimiterIndex + MESSAGE_DELIMITER.length);
-
- if (!message) continue;
-
- try {
- const step = JSON.parse(message);
- handleStreamMessage(step);
- } catch {
- addMessage('Failed: ' + message);
- }
- }
- }
-}
-
-function handleStreamMessage(step: any) {
- // Save to result_history if this is a final response, regardless of step type
- if (step.final_response === true) {
- state.result_history.push(step.message);
- }
-
- if (step.type === 'reasoning_step') {
- addMessage(step.message);
- moveLoadingMessageToBottom();
- } else if (step.type === 'final_result') {
- handleFinalResult(step);
- } else if (step.type === 'sql_query') {
- handleFinalResult(step, true);
- } else if (step.type === 'followup_questions') {
- handleFollowupQuestions(step);
- } else if (step.type === 'query_result') {
- handleQueryResult(step);
- } else if (step.type === 'ai_response') {
- addMessage(step.message, "final-result");
- } else if (step.type === 'destructive_confirmation') {
- addDestructiveConfirmationMessage(step);
- } else if (step.type === 'operation_cancelled') {
- addMessage(step.message, "followup");
- } else {
- addMessage(step.message || JSON.stringify(step));
- }
-
- if (step.type !== 'reasoning_step') {
- resetUIState();
- }
-}
-
-function handleFinalResult(step: any, isQuery = false) {
- if (DOM.confValue) DOM.confValue.textContent = `${step.conf}%`;
-
- [[step.exp, DOM.expValue], [step.miss, DOM.missValue], [step.amb, DOM.ambValue]].forEach(([value, element]: any) => {
- if (!element) return;
- element.innerHTML = '';
- let ul = document.getElementById(`${element.id}-list`) as HTMLUListElement | null;
-
- ul = document.createElement('ul');
- ul.className = `final-result-list`;
- ul.id = `${element.id}-list`;
- element.appendChild(ul);
-
- (value || '').split('-').forEach((item: string, i: number) => {
- if (item === '') return;
-
- let li = document.getElementById(`${element.id}-${i}-li`);
-
- li = document.createElement('li');
- li.id = `${element.id}-${i}-li`;
- ul.appendChild(li);
-
- li.textContent = i === 0 ? `${item}` : `- ${item}`;
- });
- });
-
- const message = step.message || JSON.stringify(step.data, null, 2);
- if (step.is_valid) {
- addMessage(message, "final-result", isQuery);
- }
-}
-
-function handleFollowupQuestions(step: any) {
- if (DOM.expValue) DOM.expValue.textContent = 'N/A';
- if (DOM.confValue) DOM.confValue.textContent = 'N/A';
- if (DOM.missValue) DOM.missValue.textContent = 'N/A';
- if (DOM.ambValue) DOM.ambValue.textContent = 'N/A';
- addMessage(step.message, "followup");
-}
-
-function handleQueryResult(step: any) {
- if (step.data) {
- addMessage("Query Result", "query-final-result", false, null, step.data);
- } else {
- addMessage('No results found for the query.');
- }
-}
-
-function resetUIState() {
- DOM.inputContainer?.classList.remove('loading');
- if (DOM.submitButton) DOM.submitButton.style.display = 'flex';
- if (DOM.pauseButton) DOM.pauseButton.style.display = 'none';
- if (DOM.newChatButton) DOM.newChatButton.disabled = false;
- removeLoadingMessage();
-}
-
-export function pauseRequest() {
- if (state.currentRequestController) {
- state.currentRequestController.abort();
- state.currentRequestController = null;
-
- resetUIState();
- addMessage('Request was paused by user.', "followup");
- }
-}
-
-function escapeForSingleQuotedJsString(str: string) {
- return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
-}
-
-export function addDestructiveConfirmationMessage(step: any) {
- const messageDiv = document.createElement('div');
- const messageDivContainer = document.createElement('div');
-
- messageDivContainer.className = 'message-container bot-message-container destructive-confirmation-container';
- messageDiv.className = 'message bot-message destructive-confirmation-message';
-
- const confirmationId = 'confirmation-' + Date.now();
-
- const confirmationHTML = `
-
-
${(step.message || '').replace(/\n/g, ' ')}
-
-
- CONFIRM - Execute Query
-
-
- CANCEL - Abort Operation
-
-
-
- `;
-
- messageDiv.innerHTML = confirmationHTML;
-
- messageDivContainer.appendChild(messageDiv);
- if (DOM.chatMessages) DOM.chatMessages.appendChild(messageDivContainer);
- if (DOM.chatMessages) DOM.chatMessages.scrollTop = DOM.chatMessages.scrollHeight;
-
- if (DOM.messageInput) DOM.messageInput.disabled = true;
- if (DOM.submitButton) DOM.submitButton.disabled = true;
-}
-
-export async function handleDestructiveConfirmation(confirmation: string, sqlQuery: string, confirmationId: string) {
- const confirmationDialog = document.querySelector(`[data-confirmation-id="${confirmationId}"]`);
- if (confirmationDialog) {
- const confirmBtn = confirmationDialog.querySelector('.confirm-btn') as HTMLButtonElement | null;
- const cancelBtn = confirmationDialog.querySelector('.cancel-btn') as HTMLButtonElement | null;
- if (confirmBtn) confirmBtn.disabled = true;
- if (cancelBtn) cancelBtn.disabled = true;
- }
-
- if (DOM.messageInput) DOM.messageInput.disabled = false;
- if (DOM.submitButton) DOM.submitButton.disabled = false;
-
- addMessage(`User choice: ${confirmation}`, "user", (window as any).currentUser || null);
-
- if (confirmation === 'CANCEL') {
- addMessage('Operation cancelled. The destructive SQL query was not executed.', "followup");
- return;
- }
-
- try {
- const selectedValue = getSelectedGraph() || '';
-
- const response = await fetch('/graphs/' + encodeURIComponent(selectedValue) + '/confirm', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- confirmation: confirmation,
- sql_query: sqlQuery,
- chat: state.questions_history
- })
- });
-
- if (!response.ok) throw new Error(`Server responded with ${response.status}`);
-
- await processStreamingResponse(response);
- } catch (error: any) {
- console.error('Error:', error);
- addMessage('Sorry, there was an error processing the confirmation: ' + (error.message || String(error)));
- }
-}
-
-// Expose global for inline onclick handlers
-(window as any).handleDestructiveConfirmation = handleDestructiveConfirmation;
diff --git a/app/ts/modules/config.ts b/app/ts/modules/config.ts
deleted file mode 100644
index d579f8c4..00000000
--- a/app/ts/modules/config.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * TypeScript: Constants and configuration for the chat application
- */
-
-export const MESSAGE_DELIMITER = '|||FALKORDB_MESSAGE_BOUNDARY|||';
-
-export const SELECTORS = {
- messageInput: '#message-input',
- submitButton: '#submit-button',
- pauseButton: '#pause-button',
- newChatButton: '#reset-button',
- chatMessages: '#chat-messages',
- expValue: '#exp-value',
- confValue: '#conf-value',
- missValue: '#info-value',
- ambValue: '#amb-value',
- fileUpload: '#schema-upload',
- fileLabel: '#custom-file-upload',
- sideMenuButton: '#side-menu-button',
- menuButton: '#menu-button',
- schemaButton: '#schema-button',
- menuContainer: '#menu-container',
- schemaContainer: '#schema-container',
- chatContainer: '#chat-container',
- leftToolbar: '#left-toolbar',
- toolbarButtons: '#toolbar-buttons',
- leftToolbarInner: '#left-toolbar-inner',
- expInstructions: '#instructions-textarea',
- inputContainer: '#input-container',
- resetConfirmationModal: '#reset-confirmation-modal',
- resetConfirmBtn: '#reset-confirm-btn',
- resetCancelBtn: '#reset-cancel-btn'
-} as const;
-
-function getElement(id: string): T {
- return document.getElementById(id) as T;
-}
-
-export const DOM = {
- messageInput: getElement('message-input'),
- submitButton: getElement('submit-button'),
- pauseButton: getElement('pause-button'),
- newChatButton: getElement('reset-button'),
- chatMessages: getElement('chat-messages'),
- expValue: getElement('exp-value'),
- confValue: getElement('conf-value'),
- missValue: getElement('info-value'),
- ambValue: getElement('amb-value'),
- fileUpload: getElement('schema-upload'),
- fileLabel: getElement('custom-file-upload'),
- menuButton: getElement('menu-button'),
- schemaButton: getElement('schema-button'),
- menuContainer: getElement('menu-container'),
- schemaContainer: getElement('schema-container'),
- chatContainer: getElement('chat-container'),
- leftToolbar: getElement('left-toolbar'),
- toolbarButtons: getElement('toolbar-buttons'),
- leftToolbarInner: getElement('left-toolbar-inner'),
- expInstructions: getElement('instructions-textarea'),
- inputContainer: getElement('input-container'),
- graphSelectRefresh: getElement('graph-select-refresh'),
- resetConfirmationModal: getElement('reset-confirmation-modal'),
- resetConfirmBtn: getElement('reset-confirm-btn'),
- resetCancelBtn: getElement('reset-cancel-btn')
-};
-
-export type AppState = {
- questions_history: string[];
- result_history: string[];
- currentRequestController: AbortController | null;
-};
-
-export const state: AppState = {
- questions_history: [],
- result_history: [],
- currentRequestController: null
-};
-
-export const urlParams = new URLSearchParams(window.location.search);
diff --git a/app/ts/modules/graph_select.ts b/app/ts/modules/graph_select.ts
deleted file mode 100644
index 690474fc..00000000
--- a/app/ts/modules/graph_select.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Helper to manage the custom graph selector UI.
- * Exposes functions to get/set the selected graph and render the list.
- */
-import { DOM } from './config';
-
-export function getSelectedGraph(): string | null {
- const selectedLabel = document.getElementById('graph-selected');
- const text = selectedLabel?.querySelector('.dropdown-text')?.textContent;
- if (text) return text;
- return null;
-}
-
-export function setSelectedGraph(name: string) {
- const selectedLabel = document.getElementById('graph-selected');
- const textNode = selectedLabel?.querySelector('.dropdown-text');
- if (textNode) textNode.textContent = name;
-}
-
-export function clearGraphOptions() {
- const optionsContainer = document.getElementById('graph-options');
- if (optionsContainer) optionsContainer.innerHTML = '';
-}
-
-export function addGraphOption(name: string, onSelect: (n: string) => void, onDelete: (n: string) => void, isDemo: boolean = false) {
- const optionsContainer = document.getElementById('graph-options');
- if (!optionsContainer) return;
- const row = document.createElement('div');
- row.className = 'dropdown-option';
- row.setAttribute('data-value', name);
- row.setAttribute('data-is-demo', isDemo.toString());
- const icon = document.createElement('span');
- icon.className = 'db-icon';
- // optional: could add icons later
- const text = document.createElement('span');
- text.textContent = name;
- row.appendChild(icon);
- row.appendChild(text);
-
- const delBtn = document.createElement('button');
- delBtn.className = 'delete-btn';
- delBtn.title = isDemo ? 'Demo databases cannot be deleted' : `Delete ${name}`;
- delBtn.innerHTML = ` `;
-
- // Disable delete button for demo databases
- if (isDemo) {
- delBtn.disabled = true;
- }
-
- row.appendChild(delBtn);
-
- row.addEventListener('click', () => {
- if (DOM.graphSelectRefresh && DOM.submitButton) {
- // Disable refresh button for demo databases
- DOM.graphSelectRefresh.disabled = isDemo;
- DOM.submitButton.disabled = false
- };
- setSelectedGraph(name);
- onSelect(name);
- optionsContainer.classList.remove('open');
- });
-
- delBtn.addEventListener('click', (ev) => {
- ev.stopPropagation();
- onDelete(name);
- });
-
- optionsContainer.appendChild(row);
-}
-
-export function toggleOptions() {
- const optionsContainer = document.getElementById('graph-options');
- if (optionsContainer) optionsContainer.classList.toggle('open');
-}
diff --git a/app/ts/modules/graphs.ts b/app/ts/modules/graphs.ts
deleted file mode 100644
index 23cabebf..00000000
--- a/app/ts/modules/graphs.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-/**
- * Graph loading and management functionality (TypeScript)
- */
-
-import { DOM } from "./config";
-import { addMessage, initChat } from "./messages";
-import {
- addGraphOption,
- clearGraphOptions,
- setSelectedGraph,
- toggleOptions,
- getSelectedGraph,
-} from "./graph_select";
-
-export function loadGraphs() {
- const isAuthenticated =
- (window as any).isAuthenticated !== undefined
- ? (window as any).isAuthenticated
- : false;
-
- if (!isAuthenticated) {
- const option = document.createElement("option");
- option.value = "";
- option.textContent = "Please log in to access graphs";
- option.disabled = true;
-
- if (DOM.messageInput) DOM.messageInput.disabled = true;
- if (DOM.submitButton) DOM.submitButton.disabled = true;
- if (DOM.messageInput)
- DOM.messageInput.placeholder = "Please log in to start chatting";
- return;
- }
-
- fetch("/graphs")
- .then((response) => {
- if (!response.ok) {
- if (response.status === 401) {
- throw new Error(
- "Authentication required. Please log in to access graphs."
- );
- }
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
- return response.json();
- })
- .then((data: string[]) => {
- if (!data || data.length === 0) {
- // Clear custom dropdown and show no graphs state
- clearGraphOptions();
-
- if (DOM.messageInput) DOM.messageInput.disabled = true;
- if (DOM.submitButton) DOM.submitButton.disabled = true;
- if (DOM.messageInput)
- DOM.messageInput.placeholder =
- "Please upload a schema or connect a database to start chatting";
-
- addMessage(
- "No graphs are available. Please upload a schema file or connect to a database to get started."
- );
-
- // Update the visible selected label to show no graphs state
- const selectedLabel = document.getElementById("graph-selected");
- if (selectedLabel) {
- const dropdownText = selectedLabel.querySelector(".dropdown-text");
- if (dropdownText) {
- dropdownText.textContent = "Select Database";
- }
- }
- return;
- }
-
- // populate hidden select for legacy code
- data.forEach((graph) => {
- const option = document.createElement("option");
- option.value = graph;
- option.textContent = graph;
- option.title = graph;
- });
-
- // populate custom dropdown
- try {
- clearGraphOptions();
- data.forEach((graph) => {
- // Check if this graph is a demo database
- const generalPrefix = (window as any).generalPrefix;
- const isDemo = !!(generalPrefix && graph.startsWith(generalPrefix));
-
- addGraphOption(
- graph,
- (name) => {
- // onSelect
- setSelectedGraph(name);
- initChat();
- if (typeof (window as any).updateInputState === 'function') {
- (window as any).updateInputState();
- }
- },
- async (name) => {
- // onDelete
- const confirmed = confirm(
- `Delete graph "${name}"? This action cannot be undone.`
- );
- if (!confirmed) return;
- try {
- const resp = await fetch(
- `/graphs/${encodeURIComponent(name)}`,
- { method: "DELETE" }
- );
- if (!resp.ok) {
- const text = await resp.text();
- throw new Error(`Delete failed: ${resp.status} ${text}`);
- }
- addMessage(`Graph "${name}" deleted.`);
- } catch (err) {
- console.error("Error deleting graph:", err);
- addMessage("Error deleting graph: " + (err as Error).message);
- } finally {
- // Always refresh the graph list after delete attempt
- loadGraphs();
- }
- },
- isDemo
- );
- });
-
- const sel = document.getElementById("graph-selected");
- if (sel) sel.addEventListener("click", () => toggleOptions());
- } catch (e) {
- console.warn("Custom graph dropdown not available", e);
- }
-
- // Attach delete button handler if present
- const deleteBtn = document.getElementById("delete-graph-btn");
- if (deleteBtn) {
- deleteBtn.removeEventListener("click", onDeleteClick as EventListener);
- deleteBtn.addEventListener("click", onDeleteClick as EventListener);
- }
- })
- .catch((error) => {
- console.error("Error fetching graphs:", error);
-
- if ((error as Error).message.includes("Authentication required")) {
- addMessage(
- "Authentication required. Please log in to access your graphs."
- );
- } else {
- addMessage(
- "Sorry, there was an error fetching the available graphs: " +
- (error as Error).message
- );
- if (DOM.messageInput) DOM.messageInput.disabled = true;
- if (DOM.submitButton) DOM.submitButton.disabled = true;
- if (DOM.messageInput)
- DOM.messageInput.placeholder = "Cannot connect to server";
- }
-
- const option = document.createElement("option");
- option.value = "";
- option.textContent = (error as Error).message.includes("Authentication")
- ? "Please log in"
- : "Error loading graphs";
- option.disabled = true;
- });
-}
-
-async function onDeleteClick() {
- const graphName = getSelectedGraph();
- if (!graphName) {
- addMessage("Please select a graph to delete.");
- return;
- }
-
- const confirmed = confirm(
- `Are you sure you want to delete the graph '${graphName}'? This action cannot be undone.`
- );
- if (!confirmed) return;
-
- try {
- const resp = await fetch(`/graphs/${encodeURIComponent(graphName)}`, {
- method: "DELETE",
- });
- if (!resp.ok) {
- const text = await resp.text();
- throw new Error(`Failed to delete graph: ${resp.status} ${text}`);
- }
- addMessage(`Graph '${graphName}' deleted.`);
- // Clear current chat state if the deleted graph was selected
- if (window && (window as any).currentGraph === graphName) {
- (window as any).currentGraph = undefined;
- }
- } catch (err) {
- console.error("Error deleting graph:", err);
- addMessage("Error deleting graph: " + (err as Error).message);
- } finally {
- // Always reload graphs list after delete attempt
- loadGraphs();
- }
-}
-
-export function handleFileUpload(event: Event) {
- const target = event.target as HTMLInputElement | null;
- const file = target?.files ? target.files[0] : null;
- if (!file) return;
-
- const formData = new FormData();
- formData.append("file", file);
-
- fetch("/graphs", {
- method: "POST",
- body: formData,
- })
- .then((response) => response.json())
- .then((data) => {
- console.log("File uploaded successfully", data);
- })
- .catch((error) => {
- console.error("Error uploading file:", error);
- addMessage(
- "Sorry, there was an error uploading your file: " +
- (error as Error).message
- );
- });
-}
-
-export function onGraphChange() {
- initChat();
- if (typeof (window as any).updateInputState === 'function') {
- (window as any).updateInputState();
- }
-}
diff --git a/app/ts/modules/input.ts b/app/ts/modules/input.ts
deleted file mode 100644
index 4f47ec18..00000000
--- a/app/ts/modules/input.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Input handling module - textarea auto-resize functionality
- */
-
-import { DOM } from "./config";
-
-export function adjustTextareaHeight() {
- const textarea = DOM.messageInput;
- if (!textarea) return;
-
- // Reset height to auto to get the correct scrollHeight
- textarea.style.height = "auto";
-
- // Calculate the new height based on content
- const scrollHeight = textarea.scrollHeight;
- const maxHeight = parseInt(getComputedStyle(textarea).maxHeight);
-
- if (scrollHeight <= maxHeight) {
- // Content fits within max height, grow the textarea
- textarea.style.height = scrollHeight + "px";
- textarea.style.overflowY = "hidden";
- } else {
- // Content exceeds max height, set to max and enable scrolling
- textarea.style.height = maxHeight + "px";
- textarea.style.overflowY = "auto";
- }
-}
-
-export function setupTextareaAutoResize() {
- const textarea = DOM.messageInput;
-
- if (!textarea) return;
-
- // Adjust height on input
- textarea.addEventListener("input", adjustTextareaHeight);
-
- // Adjust height on paste
- textarea.addEventListener("paste", () => {
- // Use setTimeout to ensure the pasted content is processed
- setTimeout(adjustTextareaHeight, 0);
- });
-
- // Initial adjustment in case there's pre-filled content
- adjustTextareaHeight();
-}
diff --git a/app/ts/modules/left_toolbar.ts b/app/ts/modules/left_toolbar.ts
deleted file mode 100644
index 94d2162a..00000000
--- a/app/ts/modules/left_toolbar.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Left toolbar behavior extracted from template script.
- * This module exports initLeftToolbar and can be imported so bundlers include it in the main bundle.
- */
-export function initLeftToolbar(): void {
- const nav = document.getElementById('left-toolbar') as HTMLElement | null;
- const btn = document.getElementById('burger-toggle-btn') as HTMLElement | null;
- if (!nav || !btn) return;
-
- function setOpen(open: boolean) {
- // `nav` and `btn` are checked above; use non-null assertions to satisfy TypeScript
- if (open) {
- nav!.classList.remove('collapsed');
- document.body.classList.add('left-toolbar-open');
- btn!.setAttribute('title', 'Close menu');
- btn!.setAttribute('aria-label', 'Close menu');
- btn!.setAttribute('aria-pressed', 'true');
- btn!.setAttribute('aria-expanded', 'true');
- } else {
- nav!.classList.add('collapsed');
- document.body.classList.remove('left-toolbar-open');
- btn!.setAttribute('title', 'Open menu');
- btn!.setAttribute('aria-label', 'Open menu');
- btn!.setAttribute('aria-pressed', 'false');
- btn!.setAttribute('aria-expanded', 'false');
- }
- }
-
- const mq = window.matchMedia('(min-width: 768px)');
-
- try {
- setOpen(mq.matches);
- } catch (e) {
- setOpen(true);
- }
-
- // Support both modern and legacy addListener APIs
- if (typeof (mq as MediaQueryList).addEventListener === 'function') {
- (mq as MediaQueryList).addEventListener('change', (ev: MediaQueryListEvent) => setOpen(ev.matches));
- } else if (typeof (mq as any).addListener === 'function') {
- (mq as any).addListener((ev: MediaQueryListEvent) => setOpen(ev.matches));
- }
-
- let ignoreNextClick = false;
-
- function handleToggleEvent() {
- const isCollapsed = nav!.classList.contains('collapsed');
- setOpen(isCollapsed);
- }
-
- btn.addEventListener('pointerdown', function (e: PointerEvent) {
- e.preventDefault();
- handleToggleEvent();
- ignoreNextClick = true;
- });
-
- btn.addEventListener('click', function (_e: MouseEvent) {
- if (ignoreNextClick) {
- ignoreNextClick = false;
- return;
- }
- handleToggleEvent();
- });
-
- // Expose a minimal API for other scripts
- (window as any).__leftToolbar = {
- open: () => setOpen(true),
- close: () => setOpen(false),
- toggle: () => setOpen(!nav.classList.contains('collapsed')),
- };
-}
-
-// Note: We don't auto-init here. Importing module and calling initLeftToolbar() from the app entry
-// ensures the bundler includes this file and initialization timing stays explicit.
diff --git a/app/ts/modules/messages.ts b/app/ts/modules/messages.ts
deleted file mode 100644
index 238ca659..00000000
--- a/app/ts/modules/messages.ts
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * Message handling and UI functions (TypeScript)
- */
-
-import { DOM, state } from "./config";
-import { getSelectedGraph } from "./graph_select";
-import { adjustTextareaHeight } from "./input";
-
-export function addMessage(
- message: string,
- type:
- | "user"
- | "bot"
- | "followup"
- | "final-result"
- | "query-final-result"
- | "loading" = "bot",
- isQuery = false,
- userInfo: { picture?: string; name?: string } | null = null,
- queryResult: any = null
-) {
- const messageDiv = document.createElement("div");
- const messageDivContainer = document.createElement("div");
-
- messageDiv.className = "message";
- messageDivContainer.className = "message-container";
-
- let userAvatar: HTMLImageElement | null = null;
-
- switch (type) {
- case "followup":
- messageDivContainer.className += " followup-message-container";
- messageDiv.className += " followup-message";
- messageDiv.textContent = message;
- break;
- case "user":
- messageDivContainer.className += " user-message-container";
- messageDiv.className += " user-message";
-
- if (userInfo && userInfo.picture) {
- userAvatar = document.createElement("img");
- userAvatar.src = userInfo.picture;
- userAvatar.alt =
- (userInfo.name?.charAt(0).toUpperCase() as string) || "User";
- userAvatar.className = "user-message-avatar";
- messageDivContainer.classList.add("has-avatar");
- }
-
- state.questions_history.push(message);
- break;
- case "bot":
- messageDivContainer.className += " bot-message-container";
- messageDiv.className += " bot-message";
- break;
- case "final-result":
- state.result_history.push(message);
- messageDivContainer.className += " final-result-message-container";
- messageDiv.className += " final-result-message";
- if (isQuery) messageDiv.classList.add("query-text");
- break;
- case "query-final-result":
- messageDivContainer.className += " final-result-message-container";
- messageDiv.className += " final-result-message";
- messageDiv.style.overflow = "auto";
- const table = document.createElement("table");
- table.id = "query-final-result-table";
- const tableHeader = document.createElement("thead");
- const headerRow = document.createElement("tr");
- Object.keys(queryResult[0]).forEach((column: any) => {
- const headerCell = document.createElement("th");
- headerCell.textContent = column;
- headerRow.appendChild(headerCell);
- });
- tableHeader.appendChild(headerRow);
- table.appendChild(tableHeader);
- const tableBody = document.createElement("tbody");
- queryResult.forEach((row: any, index: number) => {
- const rowRow = document.createElement("tr");
- Object.values(row).forEach((value: any) => {
- const cell = document.createElement("td");
- cell.textContent = value;
- rowRow.appendChild(cell);
- });
- tableBody.appendChild(rowRow);
- });
- table.appendChild(tableBody);
- messageDiv.appendChild(table);
- break;
- case "loading":
- messageDivContainer.className += " bot-message-container";
- messageDiv.className += " bot-message";
- messageDivContainer.id = "loading-message-container";
- messageDivContainer.className += " loading-message-container";
- break;
- }
-
- const block = formatBlock(message);
-
- if (block) {
- block.forEach((lineDiv) => {
- messageDiv.appendChild(lineDiv);
- });
- } else if (type !== "loading" && type !== "query-final-result") {
- messageDiv.textContent = message;
- }
-
- if (type !== "loading") {
- messageDivContainer.appendChild(messageDiv);
- if (userAvatar) {
- messageDivContainer.appendChild(userAvatar);
- }
- }
-
- DOM.chatMessages?.appendChild(messageDivContainer);
- if (DOM.chatMessages)
- DOM.chatMessages.scrollTop = DOM.chatMessages.scrollHeight;
-
- return messageDiv;
-}
-
-export function removeLoadingMessage() {
- const loadingMessageContainer = document.getElementById(
- "loading-message-container"
- );
- if (loadingMessageContainer) {
- loadingMessageContainer.remove();
- }
-}
-
-export function moveLoadingMessageToBottom() {
- const loadingMessageContainer = document.getElementById(
- "loading-message-container"
- );
- if (loadingMessageContainer && DOM.chatMessages) {
- loadingMessageContainer.remove();
- DOM.chatMessages.appendChild(loadingMessageContainer);
- DOM.chatMessages.scrollTop = DOM.chatMessages.scrollHeight;
- }
-}
-
-export function formatBlock(text: string) {
- text = text.replace(/^"(.*)"$/, "$1").trim();
-
- // SQL block
- if (text.startsWith("```sql") && text.endsWith("```")) {
- const sql = text.slice(6, -3).trim();
- return sql.split("\n").map((line) => {
- const lineDiv = document.createElement("div");
- lineDiv.textContent = line;
- return lineDiv;
- });
- }
-
- // Array block
- if (text.includes("[") && text.includes("]")) {
- const parts = text.split("[");
- const formattedParts = parts.map((part) => {
- const lineDiv = document.createElement("div");
- part = part.replace(/\]/g, "");
- lineDiv.textContent = part;
- return lineDiv;
- });
- return formattedParts;
- }
-
- // Generic multi-line block
- text = text.replace(/\\n/g, "\n");
- if (text.includes("\n")) {
- return text.split("\n").map((line) => {
- const lineDiv = document.createElement("div");
- lineDiv.textContent = line;
- return lineDiv;
- });
- }
-
- return null;
-}
-
-export function initChat() {
- if (DOM.messageInput) {
- DOM.messageInput.value = "";
- adjustTextareaHeight();
- }
- if (DOM.chatMessages) DOM.chatMessages.innerHTML = "";
- [DOM.confValue, DOM.expValue, DOM.missValue].forEach((element) => {
- if (element) element.innerHTML = "";
- });
-
- const selected = getSelectedGraph();
- if (selected) {
- addMessage("Hello! How can I help you today?");
- } else {
- addMessage(
- "Hello! Please select a graph from the dropdown above, upload a schema or connect to a database to get started."
- );
- }
-
- state.questions_history = [];
- state.result_history = [];
-}
diff --git a/app/ts/modules/modals.ts b/app/ts/modules/modals.ts
deleted file mode 100644
index 9c767726..00000000
--- a/app/ts/modules/modals.ts
+++ /dev/null
@@ -1,409 +0,0 @@
-/**
- * Modal dialogs and authentication (TypeScript)
- */
-
-export function setupAuthenticationModal() {
- const isAuthenticated = (window as any).isAuthenticated !== undefined ? (window as any).isAuthenticated : false;
- const loginModal = document.getElementById('login-modal') as HTMLElement | null;
- const signupModal = document.getElementById('signup-modal') as HTMLElement | null;
- const container = document.getElementById('container') as HTMLElement | null;
-
- if (loginModal && container) {
- if (!isAuthenticated) {
- loginModal.style.display = 'flex';
- container.style.filter = 'blur(2px)';
- } else {
- loginModal.style.display = 'none';
- container.style.filter = '';
- }
- }
-
- // Setup modal switching
- const showSignupBtn = document.getElementById('show-signup-modal') as HTMLElement | null;
- const showLoginBtn = document.getElementById('show-login-modal') as HTMLElement | null;
-
- if (showSignupBtn && loginModal && signupModal) {
- showSignupBtn.addEventListener('click', (e) => {
- e.preventDefault();
- loginModal.style.display = 'none';
- signupModal.style.display = 'flex';
- });
- }
-
- if (showLoginBtn && loginModal && signupModal) {
- showLoginBtn.addEventListener('click', (e) => {
- e.preventDefault();
- signupModal.style.display = 'none';
- loginModal.style.display = 'flex';
- });
- }
-
- // Setup email login form
- const emailLoginForm = document.getElementById('email-login-form') as HTMLFormElement | null;
- if (emailLoginForm) {
- emailLoginForm.addEventListener('submit', handleEmailLogin);
- }
-
- // Setup email signup form
- const emailSignupForm = document.getElementById('email-signup-form') as HTMLFormElement | null;
- if (emailSignupForm) {
- emailSignupForm.addEventListener('submit', handleEmailSignup);
- }
-
- // Close modals on escape key
- document.addEventListener('keydown', (e) => {
- if (e.key === 'Escape') {
- if (loginModal && loginModal.style.display === 'flex') {
- // Don't close login modal on escape if user is not authenticated
- if (isAuthenticated) {
- loginModal.style.display = 'none';
- if (container) container.style.filter = '';
- }
- }
- if (signupModal && signupModal.style.display === 'flex') {
- signupModal.style.display = 'none';
- if (loginModal) loginModal.style.display = 'flex';
- }
- }
- });
-}
-
-async function handleEmailLogin(e: Event) {
- e.preventDefault();
-
- const form = e.target as HTMLFormElement;
- const submitBtn = form.querySelector('.email-login-btn') as HTMLButtonElement;
- const emailInput = document.getElementById('login-email') as HTMLInputElement;
- const passwordInput = document.getElementById('login-password') as HTMLInputElement;
-
- if (!emailInput || !passwordInput || !submitBtn) return;
-
- const email = emailInput.value.trim();
- const password = passwordInput.value;
-
- if (!email || !password) {
- alert('Please fill in all fields');
- return;
- }
-
- // Set loading state
- submitBtn.disabled = true;
- submitBtn.textContent = 'Signing in...';
-
- try {
- const response = await fetch('/login/email', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ email, password }),
- });
-
- const data = await response.json();
-
- if (data.success) {
- // Reload page to update authentication state
- window.location.reload();
- } else {
- alert(data.error || 'Login failed. Please try again.');
- }
- } catch (error) {
- console.error('Login error:', error);
- alert('An error occurred during login. Please try again.');
- } finally {
- // Reset button state
- submitBtn.disabled = false;
- submitBtn.textContent = 'Sign in with Email';
- }
-}
-
-async function handleEmailSignup(e: Event) {
- e.preventDefault();
-
- const form = e.target as HTMLFormElement;
- const submitBtn = form.querySelector('.email-signup-btn') as HTMLButtonElement;
- const firstNameInput = document.getElementById('signup-firstname') as HTMLInputElement;
- const lastNameInput = document.getElementById('signup-lastname') as HTMLInputElement;
- const emailInput = document.getElementById('signup-email') as HTMLInputElement;
- const passwordInput = document.getElementById('signup-password') as HTMLInputElement;
- const repeatPasswordInput = document.getElementById('signup-repeat-password') as HTMLInputElement;
-
- if (!firstNameInput || !lastNameInput || !emailInput || !passwordInput || !repeatPasswordInput || !submitBtn) return;
-
- const firstName = firstNameInput.value.trim();
- const lastName = lastNameInput.value.trim();
- const email = emailInput.value.trim();
- const password = passwordInput.value;
- const repeatPassword = repeatPasswordInput.value;
-
- if (!firstName || !lastName || !email || !password || !repeatPassword) {
- alert('Please fill in all fields');
- return;
- }
-
- if (password !== repeatPassword) {
- alert('Passwords do not match');
- return;
- }
-
- if (password.length < 8) {
- alert('Password must be at least 8 characters long');
- return;
- }
-
- // Set loading state
- submitBtn.disabled = true;
- submitBtn.textContent = 'Creating account...';
-
- try {
- const response = await fetch('/signup/email', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- firstName,
- lastName,
- email,
- password,
- }),
- });
-
- const data = await response.json();
-
- if (data.success) {
- // Reload page to update authentication state
- window.location.reload();
- } else {
- alert(data.error || 'Signup failed. Please try again.');
- }
- } catch (error) {
- console.error('Signup error:', error);
- alert('An error occurred during signup. Please try again.');
- } finally {
- // Reset button state
- submitBtn.disabled = false;
- submitBtn.textContent = 'Sign up';
- }
-}
-
-function setLoadingState(isLoading: boolean, connectBtn: HTMLButtonElement, urlInput: HTMLInputElement) {
- const connectText = connectBtn.querySelector('.db-modal-connect-text') as HTMLElement | null;
- const loadingSpinner = connectBtn.querySelector('.db-modal-loading-spinner') as HTMLElement | null;
- const cancelBtn = document.getElementById('db-modal-cancel') as HTMLButtonElement | null;
-
- if (connectText) connectText.style.display = isLoading ? 'none' : 'inline';
- if (loadingSpinner) loadingSpinner.style.display = isLoading ? 'flex' : 'none';
- connectBtn.disabled = isLoading;
- if (cancelBtn) cancelBtn.disabled = isLoading;
- urlInput.disabled = isLoading;
-}
-
-export function setupDatabaseModal() {
- const dbModal = document.getElementById('db-modal') as HTMLElement;
- // Select any connect buttons by id or class to be resilient to template variations
- const openConnectBtns = Array.from(document.querySelectorAll('#connect-database-btn, .connect-database-btn, #connect-database')) as HTMLButtonElement[];
- const cancelDbModalBtn = document.getElementById('db-modal-cancel') as HTMLButtonElement;
- const connectDbModalBtn = document.getElementById('db-modal-connect') as HTMLButtonElement;
- const dbUrlInput = document.getElementById('db-url-input') as HTMLInputElement;
- // This is a hidden input used by the custom dropdown UI
- const dbTypeSelect = document.getElementById('database-type-select') as HTMLInputElement;
-
- const databaseConfig: Record = {
- postgresql: {
- placeholder: 'postgresql://username:password@host:port/database',
- example: 'postgresql://myuser:mypass@localhost:5432/mydb'
- },
- mysql: {
- placeholder: 'mysql://username:password@host:port/database',
- example: 'mysql://myuser:mypass@localhost:3306/mydb'
- }
- };
-
- const openModal = function() {
- if (connectDbModalBtn) connectDbModalBtn.disabled = true;
- if (dbTypeSelect) dbTypeSelect.value = '';
- const steps = document.getElementById('db-connection-steps-list') as HTMLUListElement | null;
- if (steps) steps.innerHTML = '';
- dbModal.style.display = 'flex';
- };
-
- // Open modal from any connect-database button (header and toolbar)
- if (openConnectBtns && openConnectBtns.length > 0) {
- openConnectBtns.forEach(b => b.addEventListener('click', openModal));
- }
-
-
- // Helpers for displaying incremental connection steps in the modal (static elements in template)
- function addStep(text: string, status: 'pending' | 'success' | 'error' = 'pending') {
- const list = document.getElementById('db-connection-steps-list') as HTMLUListElement | null;
- if (!list) return;
-
- // Mark the previous pending step as completed (✓) when adding a new step
- const prevLi = list.lastElementChild as HTMLLIElement | null;
- if (prevLi) {
- const prevIcon = prevLi.querySelector('.step-icon') as HTMLElement | null;
- if (prevIcon && prevIcon.classList.contains('pending')) {
- prevIcon.className = 'step-icon success';
- prevIcon.textContent = '✓';
- }
- }
-
- const li = document.createElement('li');
- li.className = 'db-connection-step';
-
- const icon = document.createElement('span');
- icon.className = 'step-icon ' + status;
- if (status === 'pending') icon.textContent = '⭮';
- else if (status === 'success') icon.textContent = '✓';
- else icon.textContent = '✕';
-
- const textNode = document.createElement('span');
- textNode.textContent = text;
-
- li.appendChild(icon);
- li.appendChild(textNode);
- list.appendChild(li);
- list.scrollTop = list.scrollHeight;
- }
-
- dbTypeSelect.addEventListener('change', function(this: HTMLInputElement) {
- const selectedType = this.value;
- if (selectedType && databaseConfig[selectedType]) {
- dbUrlInput.disabled = false;
- dbUrlInput.placeholder = databaseConfig[selectedType].placeholder;
- dbModal.style.display = 'flex';
- // clear previous connection steps
- const existingList = document.getElementById('db-connection-steps-list') as HTMLUListElement | null;
- if (existingList) existingList.innerHTML = '';
- connectDbModalBtn.disabled = false;
- setTimeout(() => dbUrlInput.focus(), 100);
- } else {
- dbUrlInput.disabled = true;
- dbUrlInput.placeholder = 'Select database type first...';
- connectDbModalBtn.disabled = true;
- }
- });
-
- if (cancelDbModalBtn && dbModal) {
- cancelDbModalBtn.addEventListener('click', function() {
- dbModal.style.display = 'none';
- if (dbTypeSelect) dbTypeSelect.value = '';
- if (connectDbModalBtn) connectDbModalBtn.disabled = true;
- });
- }
-
- document.addEventListener('keydown', function(e) {
- if (dbModal && dbModal.style.display === 'flex' && e.key === 'Escape') {
- dbModal.style.display = 'none';
- }
- });
-
- dbUrlInput.addEventListener('keypress', function(e) {
- if (e.key === 'Enter') {
- connectDbModalBtn.click();
- }
- });
-
- connectDbModalBtn.addEventListener('click', function() {
- if (!connectDbModalBtn || !dbUrlInput) return;
- const connectBtn = connectDbModalBtn as HTMLButtonElement;
- const urlInput = dbUrlInput as HTMLInputElement;
- const dbUrl = urlInput.value.trim();
- const selectedType = dbTypeSelect.value;
-
- if (!selectedType) {
- alert('Please select a database type.');
- return;
- }
- if (!dbUrl) {
- alert('Please enter a database URL.');
- return;
- }
-
- if (selectedType === 'postgresql' && !dbUrl.startsWith('postgresql://') && !dbUrl.startsWith('postgres://')) {
- alert('PostgreSQL URL must start with postgresql:// or postgres://');
- return;
- }
- if (selectedType === 'mysql' && !dbUrl.startsWith('mysql://')) {
- alert('MySQL URL must start with mysql://');
- return;
- }
-
- setLoadingState(true, connectBtn, urlInput);
-
- fetch('/database', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ url: dbUrl, type: selectedType }),
- }).then(response => {
- if (!response.ok) throw new Error(`Network response was not ok (${response.status})`);
-
- const reader = response.body!.getReader();
- const decoder = new TextDecoder();
- let buffer = '';
- const delimiter = '|||FALKORDB_MESSAGE_BOUNDARY|||';
-
- function processChunk(text: string) {
- if (!text || !text.trim()) return;
- let obj: any = null;
- try {
- obj = JSON.parse(text);
- } catch (e) {
- console.error('Failed to parse chunk as JSON', e, text);
- return;
- }
-
- if (obj.type === 'reasoning_step') {
- // show incremental step
- addStep(obj.message || 'Working...', 'pending');
- } else if (obj.type === 'final_result') {
- // mark last step as success and finish
- addStep(obj.message || 'Completed', obj.success ? 'success' : 'error');
- setLoadingState(false, connectBtn, urlInput);
- if (obj.success) {
- if (dbModal) dbModal.style.display = 'none';
- if (dbTypeSelect) dbTypeSelect.value = '';
- if (connectBtn) connectBtn.disabled = true;
- location.reload();
- } else {
- alert('Failed to connect: ' + (obj.message || 'Unknown error'));
- }
- } else if (obj.type === 'error') {
- addStep(obj.message || 'Error', 'error');
- setLoadingState(false, connectBtn, urlInput);
- alert('Error connecting to database: ' + (obj.message || 'Unknown error'));
- } else {
- // handle other message types if needed
- console.log('Stream message', obj);
- }
- }
-
- function pump(): Promise {
- return reader.read().then(({ done, value }) => {
- if (done) {
- if (buffer.length > 0) {
- processChunk(buffer);
- }
- setLoadingState(false, connectBtn, urlInput);
- return;
- }
-
- buffer += decoder.decode(value, { stream: true });
- const parts = buffer.split(delimiter);
- // last piece is possibly incomplete
- buffer = parts.pop() || '';
- for (const part of parts) {
- processChunk(part);
- }
- return pump();
- });
- }
-
- return pump();
- }).catch(error => {
- setLoadingState(false, connectBtn, urlInput);
- alert('Error connecting to database: ' + (error as Error).message);
- });
- });
-}
diff --git a/app/ts/modules/schema.ts b/app/ts/modules/schema.ts
deleted file mode 100644
index 288ca8f4..00000000
--- a/app/ts/modules/schema.ts
+++ /dev/null
@@ -1,245 +0,0 @@
-/**
- * Graph visualization (TypeScript)
- */
-
-let graphInstance: any;
-
-export function showGraph(data: any) {
- // ForceGraph might be a global factory function provided by a bundled lib
- const nodeWidth = 160;
- const container = document.getElementById("schema-graph") as HTMLDivElement;
- graphInstance = (ForceGraph as any)()(container)
- .graphData(data)
- .nodeId("name")
- .width(container.clientWidth)
- .height(container.clientHeight)
- .nodeCanvasObject((node: any, ctx: CanvasRenderingContext2D) => {
- const lineHeight = 14;
- const padding = 8;
- const headerHeight = 20;
- const fontSize = 12;
- const textColor = "#111";
- const fillColor = "#f6f6f6";
- const strokeColor = "#222";
-
- if (!node.height) {
- node.height =
- headerHeight + (node.columns?.length || 0) * lineHeight + padding * 2;
- }
-
- ctx.fillStyle = fillColor;
- ctx.strokeStyle = strokeColor;
- ctx.lineWidth = 1;
- ctx.fillRect(
- node.x - nodeWidth / 2,
- node.y - node.height / 2,
- nodeWidth,
- node.height
- );
- ctx.strokeRect(
- node.x - nodeWidth / 2,
- node.y - node.height / 2,
- nodeWidth,
- node.height
- );
-
- ctx.fillStyle = textColor;
- ctx.font = `bold ${fontSize}px Arial`;
- ctx.textAlign = "center";
- ctx.textBaseline = "middle";
- ctx.fillText(
- node.name,
- node.x,
- node.y - node.height / 2 + headerHeight / 2 + padding / 2
- );
-
- ctx.font = `${fontSize - 2}px Arial`;
- ctx.textAlign = "left";
- const startX = node.x - nodeWidth / 2 + padding;
- let colY = node.y - node.height / 2 + headerHeight + padding;
- (node.columns || []).forEach((col: any) => {
- let name = col;
- let type = null;
- if (typeof col === "object") {
- name = col.name || "";
- type = col.type || col.dataType || null;
- }
-
- ctx.textAlign = "left";
- ctx.fillStyle = "#000";
- ctx.fillText(name, startX, colY);
-
- if (type) {
- ctx.fillStyle = "#555";
- const nameWidth = ctx.measureText(name).width;
- const available = nodeWidth - padding * 2 - nameWidth - 8;
- let typeText = String(type);
- if (available > 0) {
- if (ctx.measureText(typeText).width > available) {
- while (
- typeText.length > 0 &&
- ctx.measureText(typeText + "…").width > available
- ) {
- typeText = typeText.slice(0, -1);
- }
- typeText = typeText + "…";
- }
- ctx.textAlign = "right";
- ctx.fillText(typeText, node.x + nodeWidth / 2 - padding, colY);
- }
- ctx.fillStyle = "#000";
- ctx.textAlign = "left";
- }
-
- colY += lineHeight;
- });
- })
- .linkCanvasObject((link: any, ctx: CanvasRenderingContext2D) => {
- const getEdgeColor = () => {
- try {
- const root = getComputedStyle(document.documentElement);
- const cssEdge = root.getPropertyValue("--edge-color");
- if (cssEdge && cssEdge.trim()) return cssEdge.trim();
-
- const bg = getComputedStyle(document.body).backgroundColor || "";
- const m = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
- if (m) {
- const r = parseInt(m[1], 10) / 255;
- const g = parseInt(m[2], 10) / 255;
- const b = parseInt(m[3], 10) / 255;
- const L = 0.2126 * r + 0.7152 * g + 0.0722 * b;
- return L > 0.6 ? "#111" : "#ffffff";
- }
- } catch {
- // ignore
- }
- return "#ffffff";
- };
-
- const edgeColor = getEdgeColor();
- ctx.strokeStyle = edgeColor;
- ctx.lineWidth = 1.5;
- ctx.beginPath();
- ctx.moveTo(link.source.x, link.source.y);
- ctx.lineTo(link.target.x, link.target.y);
- ctx.stroke();
- })
- .nodePointerAreaPaint(
- (node: any, color: string, ctx: CanvasRenderingContext2D) => {
- ctx.fillStyle = color;
- const padding = 5;
- ctx.fillRect(
- node.x - nodeWidth / 2 - padding,
- node.y - node.height / 2 - padding,
- nodeWidth + padding * 2,
- node.height + padding * 2
- );
- }
- )
- .onEngineStop(() => {
- center();
- })
- .cooldownTime(2000);
-
- if (
- typeof (window as any).d3 !== "undefined" &&
- typeof (window as any).d3.forceManyBody === "function"
- ) {
- const d3 = (window as any).d3;
- graphInstance.d3Force("charge", d3.forceManyBody().strength(-1200));
- graphInstance.d3Force(
- "link",
- d3
- .forceLink()
- .id((d: any) => d.name)
- .distance(300)
- .strength(0.6)
- );
-
- if (typeof d3.forceCollide === "function") {
- graphInstance.d3Force(
- "collision",
- d3
- .forceCollide()
- .radius((node: any) => {
- const collisionRadius =
- Math.max(nodeWidth / 2, node.height / 2) + 10;
- return collisionRadius;
- })
- .strength(0.9)
- );
- }
- }
-
- try {
- const computedBg = getComputedStyle(document.body).backgroundColor || "";
- const pickColor = (bg: string) => {
- try {
- const m = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
- if (m) {
- const r = parseInt(m[1], 10) / 255;
- const g = parseInt(m[2], 10) / 255;
- const b = parseInt(m[3], 10) / 255;
- const L = 0.2126 * r + 0.7152 * g + 0.0722 * b;
- return L > 0.6 ? "#111" : "#ffffff";
- }
- } catch {
- /* empty */
- }
- return "#ffffff";
- };
- const edgeColor = (() => {
- const root = getComputedStyle(document.documentElement);
- const cssEdge = root.getPropertyValue("--edge-color");
- if (cssEdge && cssEdge.trim()) return cssEdge.trim();
- return pickColor(computedBg);
- })();
-
- graphInstance
- .linkColor(() => edgeColor)
- .linkDirectionalArrowLength(6)
- .linkDirectionalArrowRelPos(1);
- } catch {
- graphInstance.linkDirectionalArrowLength(6).linkDirectionalArrowRelPos(1);
- }
-
- const zoomInButton = document.getElementById(
- "schema-controls-zoom-in"
- ) as HTMLButtonElement;
- const zoomOutButton = document.getElementById(
- "schema-controls-zoom-out"
- ) as HTMLButtonElement;
- const centerButton = document.getElementById(
- "schema-controls-center"
- ) as HTMLButtonElement;
-
- zoomInButton.addEventListener("click", () => {
- graphInstance.zoom(graphInstance.zoom() * 1.1);
- });
- zoomOutButton.addEventListener("click", () => {
- graphInstance.zoom(graphInstance.zoom() * 0.9);
- });
- centerButton.addEventListener("click", () => {
- center();
- });
-}
-
-const center = () => {
- const canvas = document.getElementById("schema-graph") as HTMLCanvasElement;
-
- if (canvas) {
- const rect = canvas.getBoundingClientRect();
- const minDimension = Math.min(rect.width, rect.height);
- const padding = minDimension * 0.1;
- graphInstance.zoomToFit(500, padding);
- }
-};
-
-export function resizeGraph() {
- if (graphInstance) {
- const container = document.getElementById("schema-graph") as HTMLDivElement;
- if (container) {
- graphInstance.width(container.clientWidth).height(container.clientHeight);
- }
- }
-}
diff --git a/app/ts/modules/tokens.ts b/app/ts/modules/tokens.ts
deleted file mode 100644
index 7e6f8414..00000000
--- a/app/ts/modules/tokens.ts
+++ /dev/null
@@ -1,347 +0,0 @@
-/**
- * Token management functionality (TypeScript)
- */
-interface Token {
- token_id: string;
- created_at: number;
-}
-
-interface TokenListResponse {
- tokens: Token[];
-}
-
-let currentDeleteTokenId: string | null = null;
-
-export function setupTokenManagement() {
- const apiTokensBtn = document.getElementById('api-tokens-btn');
- const tokensModal = document.getElementById('tokens-modal');
- const closeTokensModal = document.getElementById('close-tokens-modal');
- const generateTokenBtn = document.getElementById('generate-token-btn');
- const copyTokenBtn = document.getElementById('copy-token-btn');
- const toggleTokenVisibilityBtn = document.getElementById('toggle-token-visibility');
- const deleteTokenModal = document.getElementById('delete-token-modal');
- const closeDeleteTokenModal = document.getElementById('close-delete-token-modal');
- const confirmDeleteToken = document.getElementById('confirm-delete-token');
- const cancelDeleteToken = document.getElementById('cancel-delete-token');
-
- if (!apiTokensBtn || !tokensModal) return;
-
- // Open tokens modal
- apiTokensBtn.addEventListener('click', async function(e) {
- e.preventDefault();
- e.stopPropagation();
-
- // Close user profile dropdown
- const userProfileDropdown = document.getElementById('user-profile-dropdown');
- if (userProfileDropdown) {
- userProfileDropdown.classList.remove('show');
- }
-
- // Use flex so the overlay uses its centering styles (align-items/justify-content)
- tokensModal.style.display = 'flex';
- await loadTokens();
- });
-
- // Close tokens modal
- closeTokensModal?.addEventListener('click', function() {
- tokensModal.style.display = 'none';
- hideTokenGenerated();
- });
-
- // Close modal when clicking outside
- tokensModal.addEventListener('click', function(e) {
- if (e.target === tokensModal) {
- tokensModal.style.display = 'none';
- hideTokenGenerated();
- }
- });
-
- // Generate new token
- generateTokenBtn?.addEventListener('click', async function() {
- await generateToken();
- });
-
-
- // Copy token to clipboard (read the input value directly)
- copyTokenBtn?.addEventListener('click', function() {
- const tokenInput = document.getElementById('new-token-value') as HTMLInputElement;
- if (tokenInput) {
- const value = tokenInput.value || '';
- if (value) {
- navigator.clipboard?.writeText(value).then(() => {
- const originalText = copyTokenBtn.textContent;
- copyTokenBtn.textContent = 'Copied!';
- setTimeout(() => {
- copyTokenBtn.textContent = originalText as string;
- }, 2000);
- }).catch(() => {
- tokenInput.select();
- document.execCommand('copy');
- });
- }
- }
- });
-
- // Toggle token visibility: simply toggle input.type between password and text
- toggleTokenVisibilityBtn?.addEventListener('click', function() {
- const tokenInput = document.getElementById('new-token-value') as HTMLInputElement;
- if (!tokenInput) return;
- const btn = toggleTokenVisibilityBtn as HTMLButtonElement;
- if (tokenInput.type === 'password') {
- tokenInput.type = 'text';
- btn.textContent = 'Hide';
- setTimeout(() => tokenInput.select(), 50);
- } else {
- tokenInput.type = 'password';
- btn.textContent = 'Show';
- }
- });
-
- // Delete token modal handlers
- closeDeleteTokenModal?.addEventListener('click', function() {
- if (deleteTokenModal) {
- deleteTokenModal.style.display = 'none';
- }
- currentDeleteTokenId = null;
- });
-
- cancelDeleteToken?.addEventListener('click', function() {
- if (deleteTokenModal) {
- deleteTokenModal.style.display = 'none';
- }
- currentDeleteTokenId = null;
- });
-
- confirmDeleteToken?.addEventListener('click', async function() {
- if (currentDeleteTokenId) {
- await deleteToken(currentDeleteTokenId);
- }
- });
-
- // Close delete modal when clicking outside
- deleteTokenModal?.addEventListener('click', function(e) {
- if (e.target === deleteTokenModal) {
- deleteTokenModal.style.display = 'none';
- currentDeleteTokenId = null;
- }
- });
-
- // Handle escape key - check computed style to determine visibility
- document.addEventListener('keydown', function(e) {
- if (e.key === 'Escape') {
- try {
- if (tokensModal && getComputedStyle(tokensModal).display !== 'none') {
- tokensModal.style.display = 'none';
- hideTokenGenerated();
- }
- if (deleteTokenModal && getComputedStyle(deleteTokenModal).display !== 'none') {
- deleteTokenModal.style.display = 'none';
- currentDeleteTokenId = null;
- }
- } catch (err) {
- // ignore if computed style fails for any reason
- }
- }
- });
-}
-
-async function loadTokens(): Promise {
- try {
- const response = await fetch('/tokens/list', {
- method: 'GET',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const data: TokenListResponse = await response.json();
- displayTokens(data.tokens);
- } catch (error) {
- console.error('Error loading tokens:', error);
- showError('Failed to load tokens. Please try again.');
- }
-}
-
-function displayTokens(tokens: Token[]): void {
- const noTokensMessage = document.getElementById('no-tokens-message');
- const tokensTable = document.getElementById('tokens-table');
- const tokensTbody = document.getElementById('tokens-tbody');
-
- if (!noTokensMessage || !tokensTable || !tokensTbody) return;
-
- if (tokens.length === 0) {
- noTokensMessage.style.display = 'block';
- tokensTable.style.display = 'none';
- } else {
- noTokensMessage.style.display = 'none';
- tokensTable.style.display = 'block';
-
- tokensTbody.innerHTML = '';
- tokens.forEach(token => {
- const row = document.createElement('tr');
- row.innerHTML = `
- ****${token.token_id}
- ${formatDate(token.created_at)}
-
-
- Delete
-
-
- `;
- tokensTbody.appendChild(row);
- });
-
- // Add event listeners to delete buttons
- const deleteButtons = tokensTbody.querySelectorAll('.delete-token-btn');
- deleteButtons.forEach(button => {
- button.addEventListener('click', function(ev) {
- const target = ev.currentTarget as HTMLElement;
- const tokenId = target.getAttribute('data-token-id');
- if (tokenId) {
- showDeleteTokenModal(tokenId);
- }
- });
- });
- }
-}
-
-async function generateToken(): Promise {
- const generateBtn = document.getElementById('generate-token-btn') as HTMLButtonElement;
- if (!generateBtn) return;
-
- try {
- generateBtn.disabled = true;
- generateBtn.textContent = 'Generating...';
-
- const response = await fetch('/tokens/generate', {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- const data: Token = await response.json();
- showTokenGenerated(data.token_id);
- await loadTokens(); // Refresh the tokens list
- } catch (error) {
- console.error('Error generating token:', error);
- showError('Failed to generate token. Please try again.');
- } finally {
- generateBtn.disabled = false;
- generateBtn.textContent = 'Generate New Token';
- }
-}
-
-function showTokenGenerated(token: string): void {
- const tokenGenerated = document.getElementById('token-generated');
- const tokenInput = document.getElementById('new-token-value') as HTMLInputElement;
-
- if (tokenGenerated && tokenInput) {
- // Store the real token as the input's value and show it masked by default
- tokenInput.value = token;
- tokenInput.type = 'password';
- tokenGenerated.style.display = 'block';
- }
-}
-
-function hideTokenGenerated(): void {
- const tokenGenerated = document.getElementById('token-generated');
- const tokenInput = document.getElementById('new-token-value') as HTMLInputElement;
-
- if (tokenGenerated) {
- tokenGenerated.style.display = 'none';
- }
- if (tokenInput) {
- tokenInput.value = '';
- }
-}
-
-function showDeleteTokenModal(tokenId: string): void {
- const deleteTokenModal = document.getElementById('delete-token-modal');
- const deleteTokenLast4 = document.getElementById('delete-token-last4');
-
- if (deleteTokenModal && deleteTokenLast4) {
- currentDeleteTokenId = tokenId;
- deleteTokenLast4.textContent = tokenId;
- deleteTokenModal.style.display = 'flex'; // Use flex to ensure overlay centers content
- }
-}
-
-async function deleteToken(tokenId: string): Promise {
- const confirmBtn = document.getElementById('confirm-delete-token') as HTMLButtonElement;
- if (!confirmBtn) return;
-
- try {
- confirmBtn.disabled = true;
- confirmBtn.textContent = 'Deleting...';
-
- const response = await fetch(`/tokens/${tokenId}`, {
- method: 'DELETE',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
-
- // Close modal and refresh tokens
- const deleteTokenModal = document.getElementById('delete-token-modal');
- if (deleteTokenModal) {
- deleteTokenModal.style.display = 'none';
- }
- currentDeleteTokenId = null;
-
- await loadTokens(); // Refresh the tokens list
- showSuccess('Token deleted successfully.');
- } catch (error) {
- console.error('Error deleting token:', error);
- showError('Failed to delete token. Please try again.');
- } finally {
- confirmBtn.disabled = false;
- confirmBtn.textContent = 'Delete Token';
- }
-}
-
-function formatDate(timestamp: number | null | undefined): string {
- if (!timestamp && timestamp !== 0) return '';
-
- // Backend may return created_at in seconds (10 digits) or milliseconds (13 digits).
- // Normalize to milliseconds for Date constructor.
- let ms = Number(timestamp);
- if (!isFinite(ms)) return '';
-
- // If the value looks like seconds (less than 1e12), convert to ms.
- // Current UNIX time in ms is ~1.7e12 (year 2024). Anything below 1e12 is almost certainly seconds.
- if (ms > 0 && ms < 1e12) {
- ms = ms * 1000;
- }
-
- const date = new Date(ms);
- if (isNaN(date.getTime())) return '';
- return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
-}
-
-function showError(message: string): void {
- // You can implement a proper notification system here
- // For now, just use alert
- alert('Error: ' + message);
-}
-
-function showSuccess(message: string): void {
- // You can implement a proper notification system here
- // For now, just use alert
- alert(message);
-}
\ No newline at end of file
diff --git a/app/ts/modules/ui.ts b/app/ts/modules/ui.ts
deleted file mode 100644
index a3bae915..00000000
--- a/app/ts/modules/ui.ts
+++ /dev/null
@@ -1,376 +0,0 @@
-/**
- * UI components and interactions (TypeScript)
- */
-
-import { DOM } from "./config";
-import { resizeGraph } from "./schema";
-
-export function toggleContainer(container: HTMLElement, onOpen?: () => void) {
- const isMobile = window.innerWidth <= 768;
-
- const allContainers = document.querySelectorAll(".sidebar-container");
- allContainers.forEach((c) => {
- if (c !== container && c.classList.contains("open")) {
- c.classList.remove("open");
- // Clear the inline width style when closing other panels
- (c as HTMLElement).style.width = '';
- }
- });
-
- if (!container.classList.contains("open")) {
- container.classList.add("open");
-
- // Reset to default 50% width when opening
- if (!isMobile) {
- container.style.width = '50%';
- }
-
- if (!isMobile && DOM.chatContainer) {
- DOM.chatContainer.style.paddingRight = "10%";
- DOM.chatContainer.style.paddingLeft = "10%";
- }
- if (onOpen) onOpen();
- } else {
- container.classList.remove("open");
-
- // Clear any inline width style that was set during resizing
- container.style.width = '';
-
- if (!isMobile && DOM.chatContainer) {
- DOM.chatContainer.style.paddingRight = "20%";
- DOM.chatContainer.style.paddingLeft = "20%";
- }
- }
-}
-
-export function showResetConfirmation() {
- if (DOM.resetConfirmationModal)
- DOM.resetConfirmationModal.style.display = "flex";
- setTimeout(() => {
- DOM.resetConfirmBtn?.focus();
- }, 100);
-}
-
-export function hideResetConfirmation() {
- if (DOM.resetConfirmationModal)
- DOM.resetConfirmationModal.style.display = "none";
-}
-
-export function handleResetConfirmation() {
- hideResetConfirmation();
- import("./messages").then(({ initChat }) => {
- initChat();
- });
-}
-
-export function setupUserProfileDropdown() {
- const userProfileBtn = document.getElementById("user-profile-btn");
- const userProfileDropdown = document.getElementById("user-profile-dropdown");
-
- if (userProfileBtn && userProfileDropdown) {
- userProfileBtn.addEventListener("click", function (e) {
- e.stopPropagation();
- userProfileDropdown.classList.toggle("show");
- });
-
- document.addEventListener("click", function (e) {
- if (
- !userProfileBtn.contains(e.target as Node) &&
- !userProfileDropdown.contains(e.target as Node)
- ) {
- userProfileDropdown.classList.remove("show");
- }
- });
-
- document.addEventListener("keydown", function (e) {
- if (
- e.key === "Escape" &&
- userProfileDropdown.classList.contains("show")
- ) {
- userProfileDropdown.classList.remove("show");
- }
- });
-
- userProfileDropdown.addEventListener("click", function (e) {
- e.stopPropagation();
- });
- }
-}
-
-export function setupThemeToggle() {
- const themeToggleBtn = document.getElementById("theme-toggle-btn");
- const currentTheme = localStorage.getItem("theme") || "system";
- document.documentElement.setAttribute("data-theme", currentTheme);
-
- if (themeToggleBtn) {
- themeToggleBtn.addEventListener("click", function () {
- const currentTheme = document.documentElement.getAttribute("data-theme");
- let newTheme: string;
-
- switch (currentTheme) {
- case "dark":
- newTheme = "light";
- break;
- case "light":
- newTheme = "system";
- break;
- case "system":
- default:
- newTheme = "dark";
- break;
- }
-
- document.documentElement.setAttribute("data-theme", newTheme);
- localStorage.setItem("theme", newTheme);
-
- const titles: Record = {
- dark: "Switch to Light Mode",
- light: "Switch to System Mode",
- system: "Switch to Dark Mode",
- };
- (themeToggleBtn as HTMLElement).title = titles[newTheme];
- });
-
- const titles: Record = {
- dark: "Switch to Light Mode",
- light: "Switch to System Mode",
- system: "Switch to Dark Mode",
- };
- (themeToggleBtn as HTMLElement).title = titles[currentTheme];
- }
-}
-
-export function setupToolbar() {
- const toolbar = document.getElementById("toolbar-buttons");
- if (toolbar) {
- const buttons = Array.from(
- toolbar.querySelectorAll("button.toolbar-button")
- ) as HTMLButtonElement[];
- buttons.forEach((b, i) => b.setAttribute("tabindex", i === 0 ? "0" : "-1"));
-
- toolbar.addEventListener("keydown", (e) => {
- const focused = document.activeElement as HTMLElement | null;
- const idx = buttons.indexOf(focused as HTMLButtonElement);
- if (e.key === "ArrowDown" || e.key === "ArrowRight") {
- e.preventDefault();
- const next = buttons[(idx + 1) % buttons.length];
- if (next) {
- buttons.forEach((b) => b.setAttribute("tabindex", "-1"));
- next.setAttribute("tabindex", "0");
- next.focus();
- }
- } else if (e.key === "ArrowUp" || e.key === "ArrowLeft") {
- e.preventDefault();
- const prev = buttons[(idx - 1 + buttons.length) % buttons.length];
- if (prev) {
- buttons.forEach((b) => b.setAttribute("tabindex", "-1"));
- prev.setAttribute("tabindex", "0");
- prev.focus();
- }
- } else if (e.key === "Enter" || e.key === " ") {
- e.preventDefault();
- if (focused) (focused as HTMLElement).click();
- }
- });
- }
-}
-
-export function handleWindowResize() {
- const isMobile = window.innerWidth <= 768;
-
- const allContainers = document.querySelectorAll(".sidebar-container");
- allContainers.forEach((c) => {
- if (isMobile && c.classList.contains("open") && DOM.chatContainer) {
- DOM.chatContainer.style.paddingRight = "";
- DOM.chatContainer.style.paddingLeft = "";
- } else if (!isMobile && c.classList.contains("open") && DOM.chatContainer) {
- DOM.chatContainer.style.paddingRight = "10%";
- DOM.chatContainer.style.paddingLeft = "10%";
- } else if (
- !isMobile &&
- !c.classList.contains("open") &&
- DOM.chatContainer
- ) {
- DOM.chatContainer.style.paddingRight = "20%";
- DOM.chatContainer.style.paddingLeft = "20%";
- }
- });
-
- setTimeout(resizeGraph, 450);
-}
-
-export function setupCustomDropdown() {
- const dropdown = document.getElementById(
- "database-type-dropdown"
- ) as HTMLElement;
- const selected = dropdown?.querySelector(".dropdown-selected") as HTMLElement;
- const options = dropdown?.querySelector(".dropdown-options") as HTMLElement;
- const hiddenInput = document.getElementById(
- "database-type-select"
- ) as HTMLInputElement;
-
- selected.addEventListener("click", (e) => {
- e.stopPropagation();
- dropdown.classList.toggle("open");
- selected.classList.toggle("active");
- });
-
- options.addEventListener("click", (e) => {
- const option = (e.target as HTMLElement).closest(
- ".dropdown-option"
- ) as HTMLElement;
- if (!option) return;
-
- const value = option.dataset.value || "";
- const text = option.querySelector("span")?.textContent || "";
- const icon = option
- .querySelector(".db-icon")
- ?.cloneNode(true) as Node | null;
-
- const dropdownText = selected.querySelector(
- ".dropdown-text"
- ) as HTMLElement | null;
- if (dropdownText) dropdownText.innerHTML = "";
- if (icon && dropdownText) dropdownText.appendChild(icon);
- if (dropdownText) dropdownText.appendChild(document.createTextNode(text));
-
- hiddenInput.value = value;
- dropdown.classList.remove("open");
- selected.classList.remove("active");
-
- const changeEvent = new Event("change", { bubbles: true });
- hiddenInput.dispatchEvent(changeEvent);
- });
-
- document.addEventListener("click", (e) => {
- if (!dropdown.contains(e.target as Node)) {
- dropdown.classList.remove("open");
- selected.classList.remove("active");
- }
- });
-
- document.addEventListener("keydown", (e) => {
- if (e.key === "Escape" && dropdown.classList.contains("open")) {
- dropdown.classList.remove("open");
- selected.classList.remove("active");
- }
- });
-}
-
-export function setupResizeHandles() {
- const resizeHandles = document.querySelectorAll('.resize-handle');
-
- resizeHandles.forEach(handle => {
- let isResizing = false;
- let startX = 0;
- let startWidth = 0;
- let targetContainer: HTMLElement | null = null;
-
- const handleMouseDown = (e: MouseEvent | { clientX: number; preventDefault: () => void }) => {
- isResizing = true;
- startX = e.clientX;
-
- // Get the target container from data-target attribute
- const targetId = (handle as HTMLElement).getAttribute('data-target');
- targetContainer = targetId ? document.getElementById(targetId) : null;
-
- if (targetContainer) {
- startWidth = targetContainer.offsetWidth;
- (handle as HTMLElement).classList.add('resizing');
- targetContainer.classList.add('resizing');
- document.body.style.cursor = 'col-resize';
- document.body.style.userSelect = 'none';
- }
-
- e.preventDefault();
- };
-
- const handleMouseMove = (e: MouseEvent | { clientX: number }) => {
- if (!isResizing || !targetContainer) return;
-
- const deltaX = e.clientX - startX;
- const newWidth = startWidth + deltaX;
-
- // Get parent container width for percentage calculations
- const parentWidth = targetContainer.parentElement?.offsetWidth || window.innerWidth;
- const newWidthPercent = (newWidth / parentWidth) * 100;
-
- // Set minimum and maximum widths as percentages of parent
- const collapseThreshold = 25; // 25% of parent width
- const maxWidthPercent = 60; // 60% of parent width
-
- // If width goes below 25%, collapse the panel
- if (newWidthPercent < collapseThreshold) {
- // Directly close the container
- const isMobile = window.innerWidth <= 768;
- targetContainer.classList.remove('open');
-
- // Clear the inline width style that was set during resizing
- targetContainer.style.width = '';
-
- // Reset chat container padding when closing
- if (!isMobile && DOM.chatContainer) {
- DOM.chatContainer.style.paddingRight = "20%";
- DOM.chatContainer.style.paddingLeft = "20%";
- }
-
- // Clean up resize state
- isResizing = false;
- (handle as HTMLElement).classList.remove('resizing');
- targetContainer.classList.remove('resizing');
- document.body.style.cursor = '';
- document.body.style.userSelect = '';
- targetContainer = null;
- return;
- }
-
- const clampedWidthPercent = Math.max(collapseThreshold, Math.min(maxWidthPercent, newWidthPercent));
- targetContainer.style.width = clampedWidthPercent + '%';
-
- // Trigger graph resize if schema container is being resized
- if (targetContainer.id === 'schema-container' && targetContainer.classList.contains('open')) {
- setTimeout(() => {
- resizeGraph();
- }, 50);
- }
- };
-
- const handleMouseUp = () => {
- if (isResizing) {
- isResizing = false;
- (handle as HTMLElement).classList.remove('resizing');
- if (targetContainer) {
- targetContainer.classList.remove('resizing');
- }
- document.body.style.cursor = '';
- document.body.style.userSelect = '';
- targetContainer = null;
- }
- };
-
- handle.addEventListener('mousedown', handleMouseDown as EventListener);
- document.addEventListener('mousemove', handleMouseMove as EventListener);
- document.addEventListener('mouseup', handleMouseUp);
-
- // Handle touch events for mobile
- handle.addEventListener('touchstart', (e: Event) => {
- const touchEvent = e as TouchEvent;
- const touch = touchEvent.touches[0];
- handleMouseDown({
- clientX: touch.clientX,
- preventDefault: () => e.preventDefault()
- });
- });
-
- document.addEventListener('touchmove', (e: Event) => {
- if (isResizing) {
- const touchEvent = e as TouchEvent;
- const touch = touchEvent.touches[0];
- handleMouseMove({ clientX: touch.clientX });
- e.preventDefault();
- }
- });
-
- document.addEventListener('touchend', handleMouseUp);
- });
-}
diff --git a/app/tsconfig.app.json b/app/tsconfig.app.json
new file mode 100644
index 00000000..44117e07
--- /dev/null
+++ b/app/tsconfig.app.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"]
+}
diff --git a/app/tsconfig.json b/app/tsconfig.json
index c0028400..dfcabe46 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -1,15 +1,15 @@
{
+ "files": [],
+ "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
"compilerOptions": {
- "target": "ES2020",
- "module": "ESNext",
- "moduleResolution": "node",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ },
"strict": true,
- "esModuleInterop": true,
- "forceConsistentCasingInFileNames": true,
+ "noUnusedParameters": true,
+ "noUnusedLocals": true,
"skipLibCheck": true,
- "outDir": "./public/js",
- "declaration": false,
- "sourceMap": true
- },
- "include": ["./**/*"]
+ "allowJs": true
+ }
}
diff --git a/app/tsconfig.node.json b/app/tsconfig.node.json
new file mode 100644
index 00000000..3133162c
--- /dev/null
+++ b/app/tsconfig.node.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/app/vite.config.ts b/app/vite.config.ts
new file mode 100644
index 00000000..ef42d407
--- /dev/null
+++ b/app/vite.config.ts
@@ -0,0 +1,35 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react-swc";
+import path from "path";
+
+// https://vitejs.dev/config/
+export default defineConfig(({ mode }) => ({
+ server: {
+ host: "::",
+ port: 8080,
+ proxy: {
+ '/api': {
+ target: 'http://127.0.0.1:5000',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, ''),
+ secure: false,
+ },
+ '/login': {
+ target: 'http://127.0.0.1:5000',
+ changeOrigin: true,
+ secure: false,
+ },
+ '/logout': {
+ target: 'http://127.0.0.1:5000',
+ changeOrigin: true,
+ secure: false,
+ },
+ },
+ },
+ plugins: [react()],
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+}));
diff --git a/docs/SQL_IDENTIFIER_QUOTING.md b/docs/SQL_IDENTIFIER_QUOTING.md
new file mode 100644
index 00000000..fc24d1f2
--- /dev/null
+++ b/docs/SQL_IDENTIFIER_QUOTING.md
@@ -0,0 +1,199 @@
+# SQL Identifier Quoting - Fix for Special Characters in Table Names
+
+## Problem
+
+Users reported that table names containing special characters (particularly dashes/hyphens like `-`) cause SQL execution failures because the LLM-generated queries don't properly quote these identifiers.
+
+### Example Issue
+```sql
+-- ❌ Fails - table name has dash
+SELECT * FROM table-name
+
+-- ✅ Works - properly quoted
+SELECT * FROM "table-name" -- PostgreSQL
+SELECT * FROM `table-name` -- MySQL
+```
+
+## Solution
+
+We've implemented a **two-layer approach** to ensure identifiers are properly quoted:
+
+### Layer 1: Enhanced LLM Prompt
+The Analysis Agent prompt now includes explicit instructions to quote table/column names with special characters:
+
+```
+CRITICAL: When table or column names contain special characters (especially dashes/hyphens like '-'),
+you MUST wrap them in double quotes for PostgreSQL (e.g., "table-name") or backticks for MySQL
+(e.g., `table-name`). This is NON-NEGOTIABLE.
+```
+
+### Layer 2: Automatic SQL Sanitization (Safety Net)
+Even if the LLM forgets to quote identifiers, we automatically fix the SQL before execution using the `SQLIdentifierQuoter` utility.
+
+## How It Works
+
+### 1. SQL Identifier Quoting Utility (`api/utils/sql_sanitizer.py`)
+
+The `SQLIdentifierQuoter` class provides:
+
+- **Detection**: Identifies table names with special characters (`-`, spaces, etc.)
+- **Extraction**: Parses SQL queries to find table references (FROM, JOIN, UPDATE, etc.)
+- **Auto-quoting**: Automatically wraps identifiers with the correct quote character
+- **Database-aware**: Uses `"` for PostgreSQL, `` ` `` for MySQL
+
+### 2. Integration Points
+
+The sanitizer is integrated at two critical points in the query execution pipeline:
+
+#### A. Regular Query Execution (`api/core/text2sql.py`)
+After the LLM generates SQL but before execution:
+
+```python
+# Auto-quote table names with special characters
+original_sql = answer_an['sql_query']
+if original_sql:
+ # Extract known table names from schema
+ known_tables = {table[0] for table in result}
+
+ # Determine database-specific quote character
+ db_type, _ = get_database_type_and_loader(db_url)
+ quote_char = DatabaseSpecificQuoter.get_quote_char(db_type)
+
+ # Auto-quote identifiers with special characters
+ sanitized_sql, was_modified = SQLIdentifierQuoter.auto_quote_identifiers(
+ original_sql, known_tables, quote_char
+ )
+
+ if was_modified:
+ logging.info("SQL query auto-sanitized: quoted table names with special characters")
+ answer_an['sql_query'] = sanitized_sql
+```
+
+#### B. Destructive Operations Confirmation
+The same sanitization applies to confirmed destructive operations (INSERT, UPDATE, DELETE, etc.).
+
+## Features
+
+### Safety First
+- **Only quotes known tables**: Won't quote arbitrary strings or aliases
+- **Idempotent**: Already-quoted identifiers aren't double-quoted
+- **SQL keyword aware**: Doesn't quote SQL keywords (SELECT, FROM, etc.)
+- **Database-specific**: Uses correct quote character for each database type
+
+### Comprehensive Coverage
+- Handles multiple table references in complex queries
+- Supports qualified column names (`table-name.column`)
+- Works with JOINs, subqueries, INSERT, UPDATE, DELETE, etc.
+
+### Special Characters Handled
+- Dashes/hyphens: `-`
+- Spaces: ` `
+- Dots: `.`
+- And many more: `@`, `#`, `$`, `%`, etc.
+
+## Usage Examples
+
+### Example 1: Simple SELECT
+```python
+query = "SELECT * FROM order-items"
+known_tables = {"order-items"}
+result, modified = SQLIdentifierQuoter.auto_quote_identifiers(query, known_tables, '"')
+# Result: SELECT * FROM "order-items"
+```
+
+### Example 2: Complex JOIN
+```python
+query = "SELECT * FROM user-accounts JOIN order-history ON user-accounts.id = order-history.user_id"
+known_tables = {"user-accounts", "order-history"}
+result, modified = SQLIdentifierQuoter.auto_quote_identifiers(query, known_tables, '"')
+# Result: SELECT * FROM "user-accounts" JOIN "order-history" ON "user-accounts".id = "order-history".user_id
+```
+
+### Example 3: INSERT with Dashes
+```python
+query = "INSERT INTO table-name (id, name) VALUES (1, 'test')"
+known_tables = {"table-name"}
+result, modified = SQLIdentifierQuoter.auto_quote_identifiers(query, known_tables, '`')
+# Result: INSERT INTO `table-name` (id, name) VALUES (1, 'test')
+```
+
+## Testing
+
+Comprehensive unit tests are available in `tests/test_sql_sanitizer.py`:
+
+```bash
+# Run SQL sanitizer tests
+pytest tests/test_sql_sanitizer.py -v
+
+# Run all tests
+make test
+```
+
+Test coverage includes:
+- ✅ Table name detection and quoting
+- ✅ Special character handling
+- ✅ Complex queries (JOINs, subqueries)
+- ✅ Database-specific quote characters
+- ✅ Edge cases (already quoted, SQL keywords, aliases)
+
+## Performance
+
+The sanitizer has minimal performance impact:
+- **Fast regex-based parsing**: No full SQL parsing overhead
+- **Only runs when needed**: Skipped if no special characters detected
+- **Non-blocking**: Executes synchronously in milliseconds
+
+## Limitations
+
+### What It Handles
+- ✅ Table names in FROM, JOIN, UPDATE, INSERT INTO clauses
+- ✅ Qualified column references (`table.column`)
+- ✅ Common special characters (dashes, spaces, etc.)
+
+### What It Doesn't Handle (Yet)
+- ❌ Column names with special characters (future enhancement)
+- ❌ Complex subquery table aliases
+- ❌ Dynamic SQL with string concatenation
+
+These limitations are acceptable because:
+1. Table names with special chars are the primary pain point (as per user feedback)
+2. The LLM prompt layer can still handle column quoting
+3. Complex scenarios are rare in typical Text2SQL use cases
+
+## Configuration
+
+No configuration required! The system automatically:
+- Detects database type from connection URL
+- Selects appropriate quote character
+- Identifies tables from schema
+- Sanitizes queries transparently
+
+## Monitoring
+
+When sanitization occurs, it's logged:
+
+```
+INFO: SQL query auto-sanitized: quoted table names with special characters
+```
+
+This helps track when the LLM missed quoting vs. when queries were already correct.
+
+## Future Enhancements
+
+Potential improvements:
+1. **Column name quoting**: Extend to handle column names with special chars
+2. **Full SQL parsing**: Use a proper SQL parser for more robust handling
+3. **Configurable rules**: Allow users to customize quoting behavior
+4. **Performance optimization**: Cache table names per session
+
+## Contributing
+
+When modifying the SQL sanitizer:
+1. Add tests to `tests/test_sql_sanitizer.py`
+2. Ensure backward compatibility
+3. Update this documentation
+4. Test with both PostgreSQL and MySQL
+
+## Conclusion
+
+This two-layer approach (LLM prompt + automatic sanitization) provides robust handling of special characters in SQL identifiers, addressing the user's concern while maintaining safety and reliability.
diff --git a/e2e/config/urls.ts b/e2e/config/urls.ts
new file mode 100644
index 00000000..011ddf6a
--- /dev/null
+++ b/e2e/config/urls.ts
@@ -0,0 +1,85 @@
+/**
+ * E2E Test Configuration for URLs and Endpoints
+ *
+ * Centralizes all URL configuration for E2E tests.
+ * Uses environment variables with sensible defaults.
+ */
+
+export const config = {
+ /**
+ * Base URL for the API server
+ * Override with API_BASE_URL environment variable
+ */
+ baseUrl: process.env.API_BASE_URL || 'http://localhost:5000',
+
+ /**
+ * Test user credentials
+ * Override with TEST_USER_EMAIL and TEST_USER_PASSWORD environment variables
+ */
+ testUser: {
+ email: process.env.TEST_USER_EMAIL || 'test@example.com',
+ password: process.env.TEST_USER_PASSWORD || 'testpassword123',
+ },
+
+ /**
+ * Second test user credentials for multi-user tests
+ * Override with TEST_USER2_EMAIL and TEST_USER2_PASSWORD environment variables
+ */
+ testUser2: {
+ email: process.env.TEST_USER2_EMAIL || 'test2@example.com',
+ password: process.env.TEST_USER2_PASSWORD || 'testpassword456',
+ },
+
+ /**
+ * Third test user credentials for logout tests
+ * Override with TEST_USER3_EMAIL and TEST_USER3_PASSWORD environment variables
+ */
+ testUser3: {
+ email: process.env.TEST_USER3_EMAIL || 'test3@example.com',
+ password: process.env.TEST_USER3_PASSWORD || 'testpassword789',
+ },
+
+ /**
+ * Test database connection URLs
+ * Override with environment variables for local/CI testing
+ */
+ testDatabases: {
+ postgres: process.env.TEST_POSTGRES_URL || 'postgresql://postgres:postgres@localhost:5432/testdb',
+ mysql: process.env.TEST_MYSQL_URL || 'mysql://root:password@localhost:3306/testdb',
+ },
+} as const;
+
+/**
+ * Get the base URL for API calls
+ */
+export function getBaseUrl(): string {
+ return config.baseUrl;
+}
+
+/**
+ * Get test user credentials
+ */
+export function getTestUser() {
+ return config.testUser;
+}
+
+/**
+ * Get second test user credentials
+ */
+export function getTestUser2() {
+ return config.testUser2;
+}
+
+/**
+ * Get third test user credentials
+ */
+export function getTestUser3() {
+ return config.testUser3;
+}
+
+/**
+ * Get test database connection URLs
+ */
+export function getTestDatabases() {
+ return config.testDatabases;
+}
diff --git a/e2e/docker-compose.test.yml b/e2e/docker-compose.test.yml
new file mode 100644
index 00000000..e75f1f64
--- /dev/null
+++ b/e2e/docker-compose.test.yml
@@ -0,0 +1,73 @@
+services:
+ # PostgreSQL test database (for regular tests)
+ postgres-test:
+ image: postgres:15-alpine
+ container_name: queryweaver-postgres-test
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ POSTGRES_DB: testdb
+ ports:
+ - "5432:5432"
+ volumes:
+ - ./test-data/postgres-init.sql:/docker-entrypoint-initdb.d/init.sql
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ # PostgreSQL test database (for delete tests)
+ postgres-test-delete:
+ image: postgres:15-alpine
+ container_name: queryweaver-postgres-test-delete
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ POSTGRES_DB: testdb_delete
+ ports:
+ - "5433:5432"
+ volumes:
+ - ./test-data/postgres-init.sql:/docker-entrypoint-initdb.d/init.sql
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ # MySQL test database (for regular tests)
+ mysql-test:
+ image: mysql:8.0
+ container_name: queryweaver-mysql-test
+ environment:
+ MYSQL_ROOT_PASSWORD: password
+ MYSQL_DATABASE: testdb
+ ports:
+ - "3306:3306"
+ volumes:
+ - ./test-data/mysql-init.sql:/docker-entrypoint-initdb.d/init.sql
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-ppassword"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+ command: --default-authentication-plugin=mysql_native_password
+
+ # MySQL test database (for delete tests)
+ mysql-test-delete:
+ image: mysql:8.0
+ container_name: queryweaver-mysql-test-delete
+ environment:
+ MYSQL_ROOT_PASSWORD: password
+ MYSQL_DATABASE: testdb_delete
+ ports:
+ - "3307:3306"
+ volumes:
+ - ./test-data/mysql-init.sql:/docker-entrypoint-initdb.d/init.sql
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-ppassword"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+ command: --default-authentication-plugin=mysql_native_password
+
diff --git a/e2e/infra/api/apiRequests.ts b/e2e/infra/api/apiRequests.ts
new file mode 100644
index 00000000..512315ab
--- /dev/null
+++ b/e2e/infra/api/apiRequests.ts
@@ -0,0 +1,50 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+import { APIRequestContext, request } from "@playwright/test"
+
+
+const getRequest = async (url: string, headers?: Record, body?: any, availableRequest?: APIRequestContext) => {
+ const requestOptions = {
+ data: body,
+ headers: headers || undefined,
+ };
+
+ const requestContext = availableRequest || (await request.newContext());
+ const response = await requestContext.get(url, requestOptions);
+ return response;
+};
+
+const postRequest = async (url: string, body?: any, availableRequest?: APIRequestContext, headers?: Record) => {
+ const requestOptions = {
+ data: body,
+ headers: headers || undefined,
+ };
+
+ const requestContext = availableRequest || (await request.newContext());
+ const response = await requestContext.post(url, requestOptions);
+ return response;
+};
+
+const deleteRequest = async (url: string, headers?: Record, body?: any, availableRequest?: APIRequestContext) => {
+ const requestOptions = {
+ data: body,
+ headers: headers || undefined,
+ };
+
+ const requestContext = availableRequest || (await request.newContext());
+ const response = await requestContext.delete(url, requestOptions);
+ return response;
+};
+
+const patchRequest = async (url: string, body?: any, availableRequest?: APIRequestContext, headers?: Record) => {
+ const requestOptions = {
+ data: body,
+ headers: headers || undefined,
+ };
+
+ const requestContext = availableRequest || (await request.newContext());
+ const response = await requestContext.patch(url, requestOptions);
+ return response;
+};
+
+export { getRequest, deleteRequest, postRequest, patchRequest }
\ No newline at end of file
diff --git a/e2e/infra/ui/basePage.ts b/e2e/infra/ui/basePage.ts
new file mode 100644
index 00000000..472d9352
--- /dev/null
+++ b/e2e/infra/ui/basePage.ts
@@ -0,0 +1,30 @@
+import { Page } from "playwright";
+
+export default class BasePage {
+ protected page: Page;
+
+ constructor(page: Page) {
+ this.page = page;
+ }
+
+ async initPage() {
+ await this.page.waitForLoadState();
+ }
+
+ getCurrentURL(): string {
+ return this.page.url();
+ }
+
+ async refreshPage() {
+ await this.page.reload({ waitUntil: "networkidle" });
+ }
+
+ async waitForResponse(url: string) {
+ const response = await this.page.waitForResponse(url);
+ return response;
+ }
+
+ async waitForUrl(url: string) {
+ return this.page.waitForURL(url);
+ }
+}
diff --git a/e2e/infra/ui/browserWrapper.ts b/e2e/infra/ui/browserWrapper.ts
new file mode 100644
index 00000000..b92584b0
--- /dev/null
+++ b/e2e/infra/ui/browserWrapper.ts
@@ -0,0 +1,113 @@
+import { chromium, Browser, BrowserContext, Page, firefox } from 'playwright';
+import { test } from '@playwright/test';
+import BasePage from './basePage';
+
+async function launchBrowser(projectName: string): Promise {
+ if (projectName.toLowerCase().includes('firefox')) {
+ return firefox.launch();
+ }
+
+ return chromium.launch();
+}
+
+export default class BrowserWrapper {
+
+ private browser: Browser | null = null;
+
+ private context: BrowserContext | null = null;
+
+ private page: Page | null = null;
+
+ async createNewPage(
+ PageClass: new (page: Page) => T,
+ url?: string,
+ storageStatePath?: string
+ ) {
+ if (!this.browser) {
+ const projectName = test.info().project.name;
+ this.browser = await launchBrowser(projectName);
+ }
+
+ // If storageStatePath is explicitly provided and context already exists,
+ // we need to close the existing context and create a new one with the new auth
+ if (storageStatePath && this.context) {
+ await this.closeContext();
+ }
+
+ if (!this.context) {
+ const projectName = test.info().project.name;
+ const isFirefox = projectName.toLowerCase().includes('firefox');
+
+ // Firefox doesn't support clipboard-read/write permissions
+ const contextOptions: any = isFirefox ? {} : { permissions: ['clipboard-read', 'clipboard-write'] };
+
+ // Add storage state if provided
+ if (storageStatePath) {
+ contextOptions.storageState = storageStatePath;
+ }
+
+ this.context = await this.browser.newContext(contextOptions);
+ }
+ if (!this.page) {
+ this.page = await this.context.newPage();
+ }
+ if (url) {
+ await this.navigateTo(url)
+ }
+
+ const pageInstance = new PageClass(this.page);
+ return pageInstance;
+ }
+
+ getContext(): BrowserContext | null {
+ return this.context;
+ }
+
+ async getPage() {
+ if (!this.page) {
+ throw new Error('Browser is not launched yet!');
+ }
+ return this.page;
+ }
+
+ async setPageToFullScreen() {
+ if (!this.page) {
+ throw new Error('Browser is not launched yet!');
+ }
+
+ await this.page.setViewportSize({ width: 1920, height: 1080 });
+ }
+
+ async navigateTo(url: string) {
+ if (!this.page) {
+ throw new Error('Browser is not launched yet!');
+ }
+ await this.page.goto(url);
+ await this.page.waitForLoadState('networkidle');
+ }
+
+ async closePage() {
+ if (this.page) {
+ await this.page.close();
+ this.page = null;
+ }
+ }
+
+ async closeContext() {
+ await this.closePage();
+
+ if (this.context) {
+ await this.context.close();
+ this.context = null;
+ }
+ }
+
+ async closeBrowser() {
+ await this.closeContext();
+
+ if (this.browser) {
+ await this.browser.close();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/e2e/infra/utils.ts b/e2e/infra/utils.ts
new file mode 100644
index 00000000..5b2e7fef
--- /dev/null
+++ b/e2e/infra/utils.ts
@@ -0,0 +1,67 @@
+import { Locator } from "playwright";
+
+export function delay(ms: number) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms);
+ });
+}
+
+export const waitForElementToBeVisible = async (
+ locator: Locator,
+ time = 500,
+ retry = 10
+): Promise => {
+ for (let i = 0; i < retry; i += 1) {
+ try {
+ if (await locator.isVisible()) {
+ return true;
+ }
+ } catch (error) {
+ console.error(`Error checking element visibility: ${error}`);
+ }
+ await delay(time);
+ }
+ return false;
+};
+
+export const waitForElementToNotBeVisible = async (
+ locator: Locator,
+ time = 500,
+ retry = 10
+): Promise => {
+ for (let i = 0; i < retry; i += 1) {
+ try {
+ if (!(await locator.isVisible())) {
+ return true;
+ }
+ } catch (error) {
+ console.error(`Error checking element visibility: ${error}`);
+ }
+ await delay(time);
+ }
+ return false;
+};
+
+export const waitForElementToBeEnabled = async (
+ locator: Locator,
+ time = 500,
+ retry = 10
+): Promise => {
+ for (let i = 0; i < retry; i += 1) {
+ try {
+ if (await locator.isEnabled()) {
+ return true;
+ }
+ } catch (error) {
+ console.error(`Error checking element enabled: ${error}`);
+ }
+ await delay(time);
+ }
+ return false;
+};
+
+export function getRandomString(prefix = "", delimiter = "_"): string {
+ const uuid = crypto.randomUUID();
+ const timestamp = Date.now();
+ return `${prefix}${prefix ? delimiter : ""}${uuid}-${timestamp}`;
+}
diff --git a/e2e/logic/api/apiCalls.ts b/e2e/logic/api/apiCalls.ts
new file mode 100644
index 00000000..a1d00c92
--- /dev/null
+++ b/e2e/logic/api/apiCalls.ts
@@ -0,0 +1,445 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+import { APIRequestContext, APIResponse } from "@playwright/test";
+import { getRequest, postRequest, deleteRequest } from "../../infra/api/apiRequests";
+import { getBaseUrl } from "../../config/urls";
+import type {
+ AuthStatusResponse,
+ LoginResponse,
+ SignupResponse,
+ LogoutResponse,
+ GraphsListResponse,
+ GraphDataResponse,
+ GraphUploadResponse,
+ DeleteGraphResponse,
+ StreamMessage,
+ TokenListResponse,
+ GenerateTokenResponse,
+ DeleteTokenResponse,
+} from "./apiResponses";
+
+// ==================== AUTHENTICATION ENDPOINTS ====================
+export default class ApiCalls {
+ /**
+ * Check authentication status
+ * GET /auth-status
+ */
+ async getAuthStatus(
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await getRequest(
+ `${baseUrl}/auth-status`,
+ undefined,
+ undefined,
+ requestContext
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to get auth status. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Login with email and password
+ * POST /login/email
+ */
+ async loginWithEmail(
+ email: string,
+ password: string,
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await postRequest(
+ `${baseUrl}/login/email`,
+ { email, password },
+ requestContext
+ );
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ throw new Error(
+ `Failed to login with email. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Signup with email and password
+ * POST /signup/email
+ */
+ async signupWithEmail(
+ firstName: string,
+ lastName: string,
+ email: string,
+ password: string,
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await postRequest(
+ `${baseUrl}/signup/email`,
+ { firstName, lastName, email, password },
+ requestContext
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to signup with email. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Logout
+ * POST /logout
+ */
+ async logout(
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await postRequest(
+ `${baseUrl}/logout`,
+ undefined,
+ requestContext
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to logout. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Get Google OAuth login URL
+ * GET /login/google
+ */
+ async getGoogleLoginUrl(): Promise {
+ const baseUrl = getBaseUrl();
+ return `${baseUrl}/login/google`;
+ }
+
+ /**
+ * Get GitHub OAuth login URL
+ * GET /login/github
+ */
+ async getGithubLoginUrl(): Promise {
+ const baseUrl = getBaseUrl();
+ return `${baseUrl}/login/github`;
+ }
+
+ // ==================== GRAPH/DATABASE MANAGEMENT ENDPOINTS ====================
+
+ /**
+ * Get list of all graphs for authenticated user
+ * GET /graphs
+ */
+ async getGraphs(): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await getRequest(
+ `${baseUrl}/graphs`,
+ undefined,
+ undefined
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to get graphs. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Get graph schema data (nodes and links)
+ * GET /graphs/{graph_id}/data
+ */
+ async getGraphData(
+ graphId: string
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await getRequest(
+ `${baseUrl}/graphs/${graphId}/data`,
+ undefined,
+ undefined
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to get graph data for ${graphId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Upload graph data file (JSON, CSV, XML)
+ * POST /graphs
+ */
+ async uploadGraph(
+ filePath: string,
+ database?: string,
+ description?: string
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const formData: Record = {
+ file: filePath,
+ };
+
+ if (database) formData.database = database;
+ if (description) formData.description = description;
+
+ const response = await postRequest(
+ `${baseUrl}/graphs`,
+ formData,
+ undefined,
+ { "Content-Type": "multipart/form-data" }
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to upload graph. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Query a database with natural language (streaming)
+ * POST /graphs/{graph_id}
+ * Returns streaming SSE response
+ */
+ async queryGraph(
+ graphId: string,
+ chat: string[],
+ result?: string[] | null,
+ instructions?: string
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const body = {
+ chat,
+ result: result || null,
+ instructions: instructions || undefined,
+ };
+
+ const response = await postRequest(
+ `${baseUrl}/graphs/${graphId}`,
+ body,
+ undefined,
+ { "Content-Type": "application/json" }
+ );
+
+ return response;
+ } catch (error) {
+ throw new Error(
+ `Failed to query graph ${graphId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Parse streaming SSE response
+ * Helper to parse streaming messages separated by |||FALKORDB_MESSAGE_BOUNDARY|||
+ */
+ async parseStreamingResponse(
+ response: APIResponse
+ ): Promise {
+ try {
+ const body = await response.text();
+ const messages = body
+ .split("|||FALKORDB_MESSAGE_BOUNDARY|||")
+ .filter((msg) => msg.trim())
+ .map((msg) => JSON.parse(msg.trim()));
+ return messages;
+ } catch (error) {
+ throw new Error(
+ `Failed to parse streaming response. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Confirm destructive SQL operation
+ * POST /graphs/{graph_id}/confirm
+ */
+ async confirmGraphOperation(
+ graphId: string,
+ sqlQuery: string,
+ confirmation: string,
+ chat: any[] = []
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const body = {
+ sql_query: sqlQuery,
+ confirmation,
+ chat,
+ };
+
+ const response = await postRequest(
+ `${baseUrl}/graphs/${graphId}/confirm`,
+ body,
+ undefined,
+ { "Content-Type": "application/json" }
+ );
+
+ return response;
+ } catch (error) {
+ throw new Error(
+ `Failed to confirm operation for graph ${graphId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Refresh graph schema
+ * POST /graphs/{graph_id}/refresh
+ */
+ async refreshGraphSchema(
+ graphId: string
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await postRequest(
+ `${baseUrl}/graphs/${graphId}/refresh`,
+ undefined,
+ undefined,
+ { "Content-Type": "application/json" }
+ );
+
+ return response;
+ } catch (error) {
+ throw new Error(
+ `Failed to refresh schema for graph ${graphId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Delete a graph
+ * DELETE /graphs/{graph_id}
+ */
+ async deleteGraph(
+ graphId: string,
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await deleteRequest(
+ `${baseUrl}/graphs/${graphId}`,
+ undefined,
+ undefined,
+ requestContext
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to delete graph ${graphId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ // ==================== DATABASE CONNECTION ENDPOINTS ====================
+
+ /**
+ * Connect to external database using connection URL
+ * POST /database
+ * Supports PostgreSQL and MySQL
+ */
+ async connectDatabase(
+ connectionUrl: string
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const body = {
+ url: connectionUrl,
+ };
+
+ const response = await postRequest(
+ `${baseUrl}/database`,
+ body,
+ undefined,
+ { "Content-Type": "application/json" }
+ );
+
+ return response;
+ } catch (error) {
+ throw new Error(
+ `Failed to connect to database. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ // ==================== TOKEN MANAGEMENT ENDPOINTS ====================
+
+ /**
+ * Generate a new API token
+ * POST /tokens/generate
+ */
+ async generateToken(): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await postRequest(
+ `${baseUrl}/tokens/generate`,
+ undefined
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to generate token. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * List all tokens for authenticated user
+ * GET /tokens/list
+ */
+ async listTokens(): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await getRequest(
+ `${baseUrl}/tokens/list`,
+ undefined,
+ undefined
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to list tokens. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+
+ /**
+ * Delete a specific token
+ * DELETE /tokens/{token_id}
+ */
+ async deleteToken(
+ tokenId: string,
+ requestContext?: APIRequestContext
+ ): Promise {
+ try {
+ const baseUrl = getBaseUrl();
+ const response = await deleteRequest(
+ `${baseUrl}/tokens/${tokenId}`,
+ undefined,
+ undefined,
+ requestContext
+ );
+ return await response.json();
+ } catch (error) {
+ throw new Error(
+ `Failed to delete token ${tokenId}. \n Error: ${(error as Error).message}`
+ );
+ }
+ }
+}
diff --git a/e2e/logic/api/apiResponses.ts b/e2e/logic/api/apiResponses.ts
new file mode 100644
index 00000000..b2a1bb38
--- /dev/null
+++ b/e2e/logic/api/apiResponses.ts
@@ -0,0 +1,147 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+// ==================== AUTHENTICATION RESPONSES ====================
+
+export interface User {
+ id: string;
+ email: string;
+ name: string;
+ picture: string;
+ provider: 'google' | 'github' | 'email';
+}
+
+export interface AuthStatusResponse {
+ authenticated: boolean;
+ user?: User;
+}
+
+export interface LoginResponse {
+ success: boolean;
+ error?: string;
+}
+
+export interface SignupResponse {
+ success: boolean;
+ error?: string;
+}
+
+export interface LogoutResponse {
+ success: true;
+}
+
+// ==================== GRAPH/DATABASE RESPONSES ====================
+
+export type GraphsListResponse = string[];
+
+export interface GraphColumn {
+ name: string;
+ type: string | null;
+}
+
+export interface GraphNode {
+ id: string;
+ name: string;
+ columns: GraphColumn[];
+}
+
+export interface GraphLink {
+ source: string;
+ target: string;
+}
+
+export interface GraphDataResponse {
+ nodes: GraphNode[];
+ links: GraphLink[];
+}
+
+export interface GraphUploadResponse {
+ graph_id: string;
+ message: string;
+ tables?: string[];
+}
+
+export interface DeleteGraphResponse {
+ success?: boolean;
+ message?: string;
+ error?: string;
+}
+
+// ==================== STREAMING RESPONSES ====================
+
+export type StreamMessageType =
+ | 'reasoning'
+ | 'reasoning_step'
+ | 'sql'
+ | 'sql_query'
+ | 'result'
+ | 'query_result'
+ | 'ai_response'
+ | 'error'
+ | 'followup'
+ | 'followup_questions'
+ | 'confirmation'
+ | 'destructive_confirmation'
+ | 'schema_refresh'
+ | 'status'
+ | 'final_result';
+
+export interface StreamMessage {
+ type: StreamMessageType;
+ content?: string;
+ message?: string;
+ data?: any;
+ step?: string;
+ require_confirmation?: boolean;
+ confirmation_id?: string;
+ final_response?: boolean;
+ conf?: number;
+ miss?: string;
+ amb?: string;
+ exp?: string;
+ is_valid?: boolean;
+ missing_information?: string;
+ ambiguities?: string;
+ sql_query?: string;
+ operation_type?: string;
+ refresh_status?: string;
+ success?: boolean;
+ graph_id?: string;
+ graph_name?: string;
+}
+
+// ==================== TOKEN MANAGEMENT RESPONSES ====================
+
+export interface TokenListItem {
+ token_id: string;
+ created_at: number;
+}
+
+export interface TokenListResponse {
+ tokens: TokenListItem[];
+}
+
+export interface GenerateTokenResponse {
+ token_id: string;
+ created_at: number;
+}
+
+export interface DeleteTokenResponse {
+ message: string;
+}
+
+// ==================== DATABASE CONNECTION RESPONSES ====================
+
+export interface DatabaseConnectionResponse {
+ success?: boolean;
+ message?: string;
+ error?: string;
+}
+
+// ==================== ERROR RESPONSE ====================
+
+export interface ApiError {
+ error?: string;
+ detail?: string;
+ message?: string;
+ status?: number;
+}
diff --git a/e2e/logic/pom/homePage.ts b/e2e/logic/pom/homePage.ts
new file mode 100644
index 00000000..e7359b25
--- /dev/null
+++ b/e2e/logic/pom/homePage.ts
@@ -0,0 +1,1185 @@
+import { Locator, Page } from "@playwright/test";
+import { waitForElementToBeVisible, waitForElementToBeEnabled } from "../../infra/utils";
+import BasePage from "../../infra/ui/basePage";
+import ApiCalls from "../api/apiCalls";
+import { getTestDatabases } from "../../config/urls";
+
+export class HomePage extends BasePage {
+ // ==================== LOCATORS ====================
+
+ // Header Elements
+ private get logoImage(): Locator {
+ return this.page.getByTestId("logo");
+ }
+
+ private get databaseStatusBadge(): Locator {
+ return this.page.getByTestId("database-status-badge");
+ }
+
+ private get githubStarsLink(): Locator {
+ return this.page.getByTestId("github-stars-link");
+ }
+
+ private get signInBtn(): Locator {
+ return this.page.getByTestId("sign-in-btn");
+ }
+
+ private get userMenuTrigger(): Locator {
+ return this.page.getByTestId("user-menu-trigger");
+ }
+
+ private get apiTokensMenuItem(): Locator {
+ return this.page.getByTestId("api-tokens-menu-item");
+ }
+
+ private get logoutMenuItem(): Locator {
+ return this.page.getByTestId("logout-menu-item");
+ }
+
+ // Database Controls
+ private get refreshSchemaBtn(): Locator {
+ return this.page.getByTestId("refresh-schema-btn");
+ }
+
+ private get databaseSelectorTrigger(): Locator {
+ return this.page.getByTestId("database-selector-trigger");
+ }
+
+ private get connectDatabaseBtn(): Locator {
+ return this.page.getByTestId("connect-database-btn");
+ }
+
+ private get uploadSchemaBtn(): Locator {
+ return this.page.getByTestId("upload-schema-btn");
+ }
+
+ private get schemaUploadInput(): Locator {
+ return this.page.getByTestId("schema-upload-input");
+ }
+
+ // Database Dropdown Items
+ private getDatabaseOption(databaseId: string): Locator {
+ return this.page.getByTestId(`database-option-${databaseId}`);
+ }
+
+ private getDeleteGraphBtn(databaseId: string): Locator {
+ return this.page.getByTestId(`delete-graph-btn-${databaseId}`);
+ }
+
+ // Chat Interface Elements
+ private get chatInterface(): Locator {
+ return this.page.getByTestId("chat-interface");
+ }
+
+ private get queryTextarea(): Locator {
+ return this.page.getByTestId("query-textarea");
+ }
+
+ private get sendQueryBtn(): Locator {
+ return this.page.getByTestId("send-query-btn");
+ }
+
+ // Chat Messages
+ private get userMessage(): Locator {
+ return this.page.getByTestId("user-message");
+ }
+
+ private get aiMessage(): Locator {
+ return this.page.getByTestId("ai-message");
+ }
+
+ private get sqlQueryMessage(): Locator {
+ return this.page.getByTestId("sql-query-message");
+ }
+
+ private get queryResultsMessage(): Locator {
+ return this.page.getByTestId("query-results-message");
+ }
+
+ private get resultsTable(): Locator {
+ return this.page.getByTestId("results-table");
+ }
+
+ private get confirmationMessage(): Locator {
+ return this.page.getByTestId("confirmation-message");
+ }
+
+ private get confirmationConfirmBtn(): Locator {
+ return this.page.getByTestId("confirmation-confirm-button");
+ }
+
+ private get confirmationCancelBtn(): Locator {
+ return this.page.getByTestId("confirmation-cancel-button");
+ }
+
+ // Modals
+ private get loginModal(): Locator {
+ return this.page.getByTestId("login-modal");
+ }
+
+ private get databaseModal(): Locator {
+ return this.page.getByTestId("database-modal");
+ }
+
+ private get deleteDatabaseModal(): Locator {
+ return this.page.getByTestId("delete-database-modal");
+ }
+
+ private get tokensModal(): Locator {
+ return this.page.getByTestId("tokens-modal");
+ }
+
+ // Login Modal Elements
+ private get googleLoginBtn(): Locator {
+ return this.page.getByTestId("google-login-btn");
+ }
+
+ private get githubLoginBtn(): Locator {
+ return this.page.getByTestId("github-login-btn");
+ }
+
+ // Database Modal Elements
+ private get databaseTypeSelect(): Locator {
+ // SelectTrigger is wrapped in a div with data-testid, find the button inside
+ return this.page.getByTestId("database-type-select").locator('button');
+ }
+
+ private get connectionModeUrl(): Locator {
+ return this.page.getByTestId("connection-mode-url");
+ }
+
+ private get connectionModeManual(): Locator {
+ return this.page.getByTestId("connection-mode-manual");
+ }
+
+ private get connectionUrlInput(): Locator {
+ return this.page.getByTestId("connection-url-input");
+ }
+
+ private get hostInput(): Locator {
+ return this.page.locator('#host');
+ }
+
+ private get portInput(): Locator {
+ return this.page.locator('#port');
+ }
+
+ private get databaseNameInput(): Locator {
+ return this.page.locator('#database');
+ }
+
+ private get usernameInput(): Locator {
+ return this.page.locator('#username');
+ }
+
+ private get passwordInput(): Locator {
+ return this.page.locator('#password');
+ }
+
+ private get databaseModalConnectBtn(): Locator {
+ return this.page.getByTestId("connect-database-button");
+ }
+
+ private get databaseModalCancelBtn(): Locator {
+ return this.page.getByTestId("database-modal-cancel");
+ }
+
+ // Delete Modal Elements
+ private get deleteModalConfirmBtn(): Locator {
+ return this.page.getByTestId("delete-modal-confirm");
+ }
+
+ private get deleteModalCancelBtn(): Locator {
+ return this.page.getByTestId("delete-modal-cancel");
+ }
+
+ // Tokens Modal Elements
+ private get generateTokenBtn(): Locator {
+ return this.page.getByTestId("generate-token-btn");
+ }
+
+ private get newTokenInput(): Locator {
+ return this.page.getByTestId("new-token-input");
+ }
+
+ private get copyTokenBtn(): Locator {
+ return this.page.getByTestId("copy-token-btn");
+ }
+
+ private get tokensTable(): Locator {
+ return this.page.getByTestId("tokens-table");
+ }
+
+ private getDeleteTokenBtn(tokenId: string): Locator {
+ return this.page.getByTestId(`delete-token-btn-${tokenId}`);
+ }
+
+ // Toast Elements
+ private get toastNotification(): Locator {
+ return this.page.getByTestId("toast-notification");
+ }
+
+ private get toastTitle(): Locator {
+ return this.page.getByTestId("toast-title");
+ }
+
+ private get toastDescription(): Locator {
+ return this.page.getByTestId("toast-description");
+ }
+
+ // Processing Indicator
+ private get processingQueryIndicator(): Locator {
+ return this.page.getByTestId("processing-query-indicator");
+ }
+
+ // ==================== LAYER 2: INTERACT WHEN VISIBLE ====================
+
+ // Header Elements - InteractWhenVisible
+ private async interactWithLogoImage(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.logoImage);
+ if (!isVisible) throw new Error("Logo image is not visible!");
+ return this.logoImage;
+ }
+
+ private async interactWithDatabaseStatusBadge(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.databaseStatusBadge);
+ if (!isVisible) throw new Error("Database status badge is not visible!");
+ return this.databaseStatusBadge;
+ }
+
+ private async interactWithGithubStarsLink(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.githubStarsLink);
+ if (!isVisible) throw new Error("GitHub stars link is not visible!");
+ return this.githubStarsLink;
+ }
+
+ private async interactWithSignInBtn(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.signInBtn);
+ if (!isVisible) throw new Error("Sign in button is not visible!");
+ return this.signInBtn;
+ }
+
+ private async interactWithUserMenuTrigger(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.userMenuTrigger);
+ if (!isVisible) throw new Error("User menu trigger is not visible!");
+ return this.userMenuTrigger;
+ }
+
+ private async interactWithApiTokensMenuItem(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.apiTokensMenuItem);
+ if (!isVisible) throw new Error("API tokens menu item is not visible!");
+ return this.apiTokensMenuItem;
+ }
+
+ private async interactWithLogoutMenuItem(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.logoutMenuItem);
+ if (!isVisible) throw new Error("Logout menu item is not visible!");
+ return this.logoutMenuItem;
+ }
+
+ // Database Controls - InteractWhenVisible
+ private async interactWithRefreshSchemaBtn(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.refreshSchemaBtn);
+ if (!isVisible) throw new Error("Refresh schema button is not visible!");
+ const isEnabled = await waitForElementToBeEnabled(this.refreshSchemaBtn);
+ if (!isEnabled) throw new Error("Refresh schema button is not enabled!");
+ return this.refreshSchemaBtn;
+ }
+
+ private async interactWithDatabaseSelectorTrigger(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.databaseSelectorTrigger);
+ if (!isVisible) throw new Error("Database selector trigger is not visible!");
+ return this.databaseSelectorTrigger;
+ }
+
+ private async interactWithConnectDatabaseBtn(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.connectDatabaseBtn);
+ if (!isVisible) throw new Error("Connect database button is not visible!");
+ return this.connectDatabaseBtn;
+ }
+
+ private async interactWithUploadSchemaBtn(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.uploadSchemaBtn);
+ if (!isVisible) throw new Error("Upload schema button is not visible!");
+ return this.uploadSchemaBtn;
+ }
+
+ private async interactWithSchemaUploadInput(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.schemaUploadInput);
+ if (!isVisible) throw new Error("Schema upload input is not visible!");
+ return this.schemaUploadInput;
+ }
+
+ // Database Dropdown Items - InteractWhenVisible
+ private async interactWithDatabaseOption(databaseId: string): Promise {
+ const dbOption = this.getDatabaseOption(databaseId);
+ const isVisible = await waitForElementToBeVisible(dbOption);
+ if (!isVisible) throw new Error(`Database option ${databaseId} is not visible!`);
+ return dbOption;
+ }
+
+ private async interactWithDeleteGraphBtn(databaseId: string): Promise {
+ const deleteBtn = this.getDeleteGraphBtn(databaseId);
+ const isVisible = await waitForElementToBeVisible(deleteBtn);
+ if (!isVisible) throw new Error(`Delete graph button for ${databaseId} is not visible!`);
+ return deleteBtn;
+ }
+
+ // Chat Interface Elements - InteractWhenVisible
+ private async interactWithChatInterface(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.chatInterface);
+ if (!isVisible) throw new Error("Chat interface is not visible!");
+ return this.chatInterface;
+ }
+
+ private async interactWithQueryTextarea(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.queryTextarea);
+ if (!isVisible) throw new Error("Query textarea is not visible!");
+ return this.queryTextarea;
+ }
+
+ private async interactWithSendQueryBtn(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.sendQueryBtn);
+ if (!isVisible) throw new Error("Send query button is not visible!");
+ const isEnabled = await waitForElementToBeEnabled(this.sendQueryBtn);
+ if (!isEnabled) throw new Error("Send query button is not enabled!");
+ return this.sendQueryBtn;
+ }
+
+ // Chat Messages - InteractWhenVisible
+ private async interactWithUserMessage(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.userMessage);
+ if (!isVisible) throw new Error("User message is not visible!");
+ return this.userMessage;
+ }
+
+ private async interactWithAiMessage(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.aiMessage);
+ if (!isVisible) throw new Error("AI message is not visible!");
+ return this.aiMessage;
+ }
+
+ private async interactWithSqlQueryMessage(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.sqlQueryMessage);
+ if (!isVisible) throw new Error("SQL query message is not visible!");
+ return this.sqlQueryMessage;
+ }
+
+ private async interactWithQueryResultsMessage(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.queryResultsMessage);
+ if (!isVisible) throw new Error("Query results message is not visible!");
+ return this.queryResultsMessage;
+ }
+
+ private async interactWithResultsTable(): Promise {
+ const isVisible = await waitForElementToBeVisible(this.resultsTable);
+ if (!isVisible) throw new Error("Results table is not visible!");
+ return this.resultsTable;
+ }
+
+ // Modals - InteractWhenVisible
+ private async interactWithLoginModal(): Promise