diff --git a/.github/templates/preview-comment.md b/.github/templates/preview-comment.md index a1bd37c3d40..f555706ecd5 100644 --- a/.github/templates/preview-comment.md +++ b/.github/templates/preview-comment.md @@ -14,11 +14,6 @@ $DATABASE_LINK -Fly.io Electric (Fly.io) -$ELECTRIC_STATUS -$ELECTRIC_LINK - - Vercel API (Vercel) $API_STATUS $API_LINK diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index ff17b9e2529..8f2acaca814 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -20,15 +20,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Setup Node.js (for native addon compilation) - uses: actions/setup-node@v5 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: 22 @@ -43,7 +43,7 @@ jobs: run: bun run build:dist --target=${{ matrix.target }} - name: Upload tarball - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: superset-${{ matrix.target }} path: packages/cli/dist/superset-${{ matrix.target }}.tar.gz @@ -59,10 +59,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Download all artifacts - uses: actions/download-artifact@v5 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: path: release-artifacts pattern: superset-* diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index 8f132df951a..6d0f5733b41 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -41,16 +41,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | ~/.bun/install/cache @@ -136,7 +136,7 @@ jobs: } - name: Upload DMG artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ inputs.artifact_prefix }}-mac-${{ matrix.arch }}-dmg path: apps/desktop/release/*.dmg @@ -144,7 +144,7 @@ jobs: if-no-files-found: error - name: Upload ZIP artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ inputs.artifact_prefix }}-mac-${{ matrix.arch }}-zip path: apps/desktop/release/*.zip @@ -152,7 +152,7 @@ jobs: if-no-files-found: error - name: Upload auto-update manifest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ inputs.artifact_prefix }}-mac-${{ matrix.arch }}-update-manifest path: apps/desktop/release/*-mac.yml @@ -166,16 +166,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | ~/.bun/install/cache @@ -249,7 +249,7 @@ jobs: } - name: Upload AppImage artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ inputs.artifact_prefix }}-linux-appimage path: apps/desktop/release/*.AppImage @@ -257,7 +257,7 @@ jobs: if-no-files-found: error - name: Upload Linux auto-update manifest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ inputs.artifact_prefix }}-linux-update-manifest path: apps/desktop/release/*-linux.yml diff --git a/.github/workflows/bump-homebrew.yml b/.github/workflows/bump-homebrew.yml index d8312607e27..42ce5f8fea4 100644 --- a/.github/workflows/bump-homebrew.yml +++ b/.github/workflows/bump-homebrew.yml @@ -54,7 +54,7 @@ jobs: done - name: Checkout homebrew-tap - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: superset-sh/homebrew-tap token: ${{ secrets.HOMEBREW_TAP_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1c9a076cf0..ffbb41a421a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,16 +12,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -37,16 +37,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -62,16 +62,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -108,16 +108,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -133,16 +133,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} diff --git a/.github/workflows/cleanup-preview.yml b/.github/workflows/cleanup-preview.yml index 79774cdc5f9..2af3e565286 100644 --- a/.github/workflows/cleanup-preview.yml +++ b/.github/workflows/cleanup-preview.yml @@ -7,7 +7,6 @@ on: jobs: cleanup: name: Cleanup Preview Resources - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest permissions: contents: read @@ -16,7 +15,7 @@ jobs: steps: - name: Delete Neon branch id: neon-cleanup - uses: neondatabase/delete-branch-action@v3 + uses: neondatabase/delete-branch-action@4468d825d5a88ef4012f1705a82f02ec3072f776 # v3.2.1 continue-on-error: true with: project_id: ${{ vars.NEON_PROJECT_ID }} @@ -24,7 +23,7 @@ jobs: api_key: ${{ secrets.NEON_API_KEY }} - name: Setup Fly CLI - uses: superfly/flyctl-actions/setup-flyctl@master + uses: superfly/flyctl-actions/setup-flyctl@ed8efb33836e8b2096c7fd3ba1c8afe303ebbff1 # 1.6 - name: Delete Electric Fly.io app id: electric-cleanup @@ -36,7 +35,7 @@ jobs: - name: Update comment if: always() - uses: thollander/actions-comment-pull-request@v3 + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 with: message: | ## ๐Ÿงน Preview Cleanup Complete diff --git a/.github/workflows/deploy-preview.yml b/.github/workflows/deploy-preview.yml index 84045155038..772641b28b5 100644 --- a/.github/workflows/deploy-preview.yml +++ b/.github/workflows/deploy-preview.yml @@ -18,27 +18,25 @@ env: MARKETING_ALIAS: marketing-pr-${{ github.event.pull_request.number }}-superset.vercel.app ADMIN_ALIAS: admin-pr-${{ github.event.pull_request.number }}-superset.vercel.app DOCS_ALIAS: docs-pr-${{ github.event.pull_request.number }}-superset.vercel.app - ELECTRIC_URL: https://superset-electric-pr-${{ github.event.pull_request.number }}.fly.dev/v1/shape jobs: deploy-database: name: Deploy Database (Neon) - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: preview steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -48,7 +46,7 @@ jobs: - name: Create Neon branch id: create-branch - uses: neondatabase/create-branch-action@v6 + uses: neondatabase/create-branch-action@fb620d43d4c565abaf088b848a4e28e5c4ea4d9c # 6.3.1 with: project_id: ${{ vars.NEON_PROJECT_ID }} branch_name: ${{ github.head_ref }} @@ -74,76 +72,29 @@ jobs: EOF - name: Upload database status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: database-status path: database-status.env - deploy-electric: - name: Deploy Electric (Fly.io) - if: github.repository == 'superset-sh/superset' - runs-on: ubuntu-latest - needs: deploy-database - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Download database info - uses: actions/download-artifact@v4 - with: - name: database-status - - - name: Load database URL - run: | - source database-status.env - echo "DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED" >> $GITHUB_ENV - - - name: Deploy Electric to Fly.io - uses: superfly/fly-pr-review-apps@1.3.0 - with: - name: superset-electric-pr-${{ github.event.pull_request.number }} - region: iad - org: ${{ vars.FLY_ORG }} - config: fly.toml - secrets: | - DATABASE_URL=${{ env.DATABASE_URL_UNPOOLED }} - ELECTRIC_SECRET=${{ secrets.ELECTRIC_SECRET_PREVIEW }} - env: - FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} - - - name: Save Electric status - run: | - cat > electric-status.env << EOF - ELECTRIC_STATUS="โœ…" - ELECTRIC_LINK="View App" - EOF - - - name: Upload Electric status - uses: actions/upload-artifact@v4 - with: - name: electric-status - path: electric-status.env - deploy-api: name: Deploy API - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: preview needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Download database info - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: database-status @@ -154,7 +105,7 @@ jobs: echo "DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED" >> $GITHUB_ENV - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -206,10 +157,9 @@ jobs: GH_APP_PRIVATE_KEY: ${{ secrets.GH_APP_PRIVATE_KEY }} GH_WEBHOOK_SECRET: ${{ secrets.GH_WEBHOOK_SECRET }} QSTASH_TOKEN: ${{ secrets.QSTASH_TOKEN }} + QSTASH_URL: ${{ secrets.QSTASH_URL }} QSTASH_CURRENT_SIGNING_KEY: ${{ secrets.QSTASH_CURRENT_SIGNING_KEY }} QSTASH_NEXT_SIGNING_KEY: ${{ secrets.QSTASH_NEXT_SIGNING_KEY }} - ELECTRIC_URL: ${{ env.ELECTRIC_URL }} - ELECTRIC_SECRET: ${{ secrets.ELECTRIC_SECRET_PREVIEW }} DURABLE_STREAMS_URL: ${{ secrets.DURABLE_STREAMS_URL }} DURABLE_STREAMS_SECRET: ${{ secrets.DURABLE_STREAMS_SECRET }} STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} @@ -220,6 +170,7 @@ jobs: SLACK_BILLING_WEBHOOK_URL: ${{ secrets.SLACK_BILLING_WEBHOOK_URL }} SECRETS_ENCRYPTION_KEY: ${{ secrets.SECRETS_ENCRYPTION_KEY }} TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} + RELAY_URL: ${{ secrets.RELAY_URL }} run: | vercel pull --yes --environment=preview --token=$VERCEL_TOKEN vercel build --token=$VERCEL_TOKEN @@ -258,10 +209,9 @@ jobs: --env GH_APP_PRIVATE_KEY="$GH_APP_PRIVATE_KEY" \ --env GH_WEBHOOK_SECRET="$GH_WEBHOOK_SECRET" \ --env QSTASH_TOKEN=$QSTASH_TOKEN \ + --env QSTASH_URL=$QSTASH_URL \ --env QSTASH_CURRENT_SIGNING_KEY=$QSTASH_CURRENT_SIGNING_KEY \ --env QSTASH_NEXT_SIGNING_KEY=$QSTASH_NEXT_SIGNING_KEY \ - --env ELECTRIC_URL=$ELECTRIC_URL \ - --env ELECTRIC_SECRET=$ELECTRIC_SECRET \ --env DURABLE_STREAMS_URL=$DURABLE_STREAMS_URL \ --env DURABLE_STREAMS_SECRET=$DURABLE_STREAMS_SECRET \ --env STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY \ @@ -271,7 +221,8 @@ jobs: --env STRIPE_ENTERPRISE_YEARLY_PRICE_ID=$STRIPE_ENTERPRISE_YEARLY_PRICE_ID \ --env SLACK_BILLING_WEBHOOK_URL=$SLACK_BILLING_WEBHOOK_URL \ --env SECRETS_ENCRYPTION_KEY=$SECRETS_ENCRYPTION_KEY \ - --env TAVILY_API_KEY=$TAVILY_API_KEY) + --env TAVILY_API_KEY=$TAVILY_API_KEY \ + --env RELAY_URL=$RELAY_URL) vercel alias $VERCEL_URL ${{ env.API_ALIAS }} --scope=$VERCEL_ORG_ID --token=$VERCEL_TOKEN echo "vercel_url=$VERCEL_URL" >> $GITHUB_OUTPUT @@ -284,14 +235,13 @@ jobs: EOF - name: Upload API status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: api-status path: api-status.env deploy-web: name: Deploy Web - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: name: preview @@ -300,22 +250,22 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} - name: Download database info - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: database-status @@ -403,30 +353,40 @@ jobs: EOF - name: Upload web status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: web-status path: web-status.env deploy-marketing: name: Deploy Marketing - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: preview needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version + - name: Download database info + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: database-status + + - name: Load database URL + run: | + source database-status.env + echo "DATABASE_URL=$DATABASE_URL" >> $GITHUB_ENV + echo "DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED" >> $GITHUB_ENV + - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -443,6 +403,8 @@ jobs: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_MARKETING_PROJECT_ID }} + DATABASE_URL: ${{ env.DATABASE_URL }} + DATABASE_URL_UNPOOLED: ${{ env.DATABASE_URL_UNPOOLED }} NEXT_PUBLIC_API_URL: https://${{ env.API_ALIAS }} NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }} NEXT_PUBLIC_MARKETING_URL: https://${{ env.MARKETING_ALIAS }} @@ -470,6 +432,8 @@ jobs: vercel pull --yes --environment=preview --token=$VERCEL_TOKEN vercel build --token=$VERCEL_TOKEN VERCEL_URL=$(vercel deploy --prebuilt --archive=tgz --token=$VERCEL_TOKEN \ + --env DATABASE_URL=$DATABASE_URL \ + --env DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED \ --env BETTER_AUTH_SECRET=$BETTER_AUTH_SECRET \ --env NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \ --env NEXT_PUBLIC_WEB_URL=$NEXT_PUBLIC_WEB_URL \ @@ -503,30 +467,29 @@ jobs: EOF - name: Upload marketing status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: marketing-status path: marketing-status.env deploy-admin: name: Deploy Admin - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: preview needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Download database info - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: database-status @@ -537,7 +500,7 @@ jobs: echo "DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED" >> $GITHUB_ENV - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -622,30 +585,40 @@ jobs: EOF - name: Upload admin status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: admin-status path: admin-status.env deploy-docs: name: Deploy Docs - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: preview needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version + - name: Download database info + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: database-status + + - name: Load database URL + run: | + source database-status.env + echo "DATABASE_URL=$DATABASE_URL" >> $GITHUB_ENV + echo "DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED" >> $GITHUB_ENV + - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -662,6 +635,8 @@ jobs: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} + DATABASE_URL: ${{ env.DATABASE_URL }} + DATABASE_URL_UNPOOLED: ${{ env.DATABASE_URL_UNPOOLED }} NEXT_PUBLIC_API_URL: https://${{ env.API_ALIAS }} NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }} NEXT_PUBLIC_MARKETING_URL: https://${{ env.MARKETING_ALIAS }} @@ -675,6 +650,8 @@ jobs: vercel pull --yes --environment=preview --token=$VERCEL_TOKEN vercel build --token=$VERCEL_TOKEN VERCEL_URL=$(vercel deploy --prebuilt --archive=tgz --token=$VERCEL_TOKEN \ + --env DATABASE_URL=$DATABASE_URL \ + --env DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED \ --env NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY \ --env NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST \ --env NEXT_PUBLIC_SENTRY_DSN_DOCS=$NEXT_PUBLIC_SENTRY_DSN_DOCS \ @@ -691,26 +668,26 @@ jobs: EOF - name: Upload docs status - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: docs-status path: docs-status.env post-final-comment: name: Post Deployment Comment - if: github.repository == 'superset-sh/superset' && always() runs-on: ubuntu-latest - needs: [deploy-database, deploy-electric, deploy-api, deploy-web, deploy-marketing, deploy-admin, deploy-docs] + if: always() + needs: [deploy-database, deploy-api, deploy-web, deploy-marketing, deploy-admin, deploy-docs] permissions: contents: read pull-requests: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Download all status artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: "*-status" merge-multiple: true @@ -719,8 +696,6 @@ jobs: run: | DATABASE_STATUS="โŒ" DATABASE_LINK="Failed to create" - ELECTRIC_STATUS="โŒ" - ELECTRIC_LINK="Failed to deploy" API_STATUS="โŒ" API_LINK="Failed to deploy" WEB_STATUS="โŒ" @@ -736,10 +711,6 @@ jobs: source database-status.env fi - if [[ "${{ needs.deploy-electric.result }}" == "success" ]]; then - source electric-status.env - fi - if [[ "${{ needs.deploy-api.result }}" == "success" ]]; then source api-status.env fi @@ -760,11 +731,11 @@ jobs: source docs-status.env fi - export DATABASE_STATUS DATABASE_LINK ELECTRIC_STATUS ELECTRIC_LINK API_STATUS API_LINK WEB_STATUS WEB_LINK MARKETING_STATUS MARKETING_LINK ADMIN_STATUS ADMIN_LINK DOCS_STATUS DOCS_LINK + export DATABASE_STATUS DATABASE_LINK API_STATUS API_LINK WEB_STATUS WEB_LINK MARKETING_STATUS MARKETING_LINK ADMIN_STATUS ADMIN_LINK DOCS_STATUS DOCS_LINK envsubst < .github/templates/preview-comment.md > final-comment.md - name: Post final deployment comment - uses: thollander/actions-comment-pull-request@v3 + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 with: file-path: final-comment.md comment-tag: "๐Ÿš€-preview-deployment" diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index 05fc0908307..ced6ac2d246 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -5,31 +5,27 @@ on: branches: [main] workflow_dispatch: -# Disabled in fork โ€” only runs on the upstream repository -# To re-enable, remove the `if` condition from each job - env: VERCEL_CLI_VERSION: 50.22.1 jobs: deploy-database: name: Deploy Database Migrations - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -46,23 +42,22 @@ jobs: deploy-api: name: Deploy API to Vercel - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -113,10 +108,9 @@ jobs: GH_APP_PRIVATE_KEY: ${{ secrets.GH_APP_PRIVATE_KEY }} GH_WEBHOOK_SECRET: ${{ secrets.GH_WEBHOOK_SECRET }} QSTASH_TOKEN: ${{ secrets.QSTASH_TOKEN }} + QSTASH_URL: ${{ secrets.QSTASH_URL }} QSTASH_CURRENT_SIGNING_KEY: ${{ secrets.QSTASH_CURRENT_SIGNING_KEY }} QSTASH_NEXT_SIGNING_KEY: ${{ secrets.QSTASH_NEXT_SIGNING_KEY }} - ELECTRIC_URL: ${{ secrets.ELECTRIC_URL }} - ELECTRIC_SECRET: ${{ secrets.ELECTRIC_SECRET }} DURABLE_STREAMS_URL: ${{ secrets.DURABLE_STREAMS_URL }} DURABLE_STREAMS_SECRET: ${{ secrets.DURABLE_STREAMS_SECRET }} STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} @@ -127,6 +121,7 @@ jobs: SLACK_BILLING_WEBHOOK_URL: ${{ secrets.SLACK_BILLING_WEBHOOK_URL }} SECRETS_ENCRYPTION_KEY: ${{ secrets.SECRETS_ENCRYPTION_KEY }} TAVILY_API_KEY: ${{ secrets.TAVILY_API_KEY }} + RELAY_URL: ${{ secrets.RELAY_URL }} run: | vercel pull --yes --environment=production --token=$VERCEL_TOKEN vercel build --prod --token=$VERCEL_TOKEN @@ -165,10 +160,9 @@ jobs: --env GH_APP_PRIVATE_KEY="$GH_APP_PRIVATE_KEY" \ --env GH_WEBHOOK_SECRET="$GH_WEBHOOK_SECRET" \ --env QSTASH_TOKEN=$QSTASH_TOKEN \ + --env QSTASH_URL=$QSTASH_URL \ --env QSTASH_CURRENT_SIGNING_KEY=$QSTASH_CURRENT_SIGNING_KEY \ --env QSTASH_NEXT_SIGNING_KEY=$QSTASH_NEXT_SIGNING_KEY \ - --env ELECTRIC_URL=$ELECTRIC_URL \ - --env ELECTRIC_SECRET=$ELECTRIC_SECRET \ --env DURABLE_STREAMS_URL=$DURABLE_STREAMS_URL \ --env DURABLE_STREAMS_SECRET=$DURABLE_STREAMS_SECRET \ --env STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY \ @@ -178,27 +172,27 @@ jobs: --env STRIPE_ENTERPRISE_YEARLY_PRICE_ID=$STRIPE_ENTERPRISE_YEARLY_PRICE_ID \ --env SLACK_BILLING_WEBHOOK_URL=$SLACK_BILLING_WEBHOOK_URL \ --env SECRETS_ENCRYPTION_KEY=$SECRETS_ENCRYPTION_KEY \ - --env TAVILY_API_KEY=$TAVILY_API_KEY + --env TAVILY_API_KEY=$TAVILY_API_KEY \ + --env RELAY_URL=$RELAY_URL deploy-web: name: Deploy Web to Vercel - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -272,23 +266,22 @@ jobs: deploy-marketing: name: Deploy Marketing to Vercel - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -304,6 +297,8 @@ jobs: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_MARKETING_PROJECT_ID }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + DATABASE_URL_UNPOOLED: ${{ secrets.DATABASE_URL_UNPOOLED }} NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }} NEXT_PUBLIC_MARKETING_URL: ${{ secrets.NEXT_PUBLIC_MARKETING_URL }} @@ -331,6 +326,8 @@ jobs: vercel pull --yes --environment=production --token=$VERCEL_TOKEN vercel build --prod --token=$VERCEL_TOKEN vercel deploy --prod --prebuilt --archive=tgz --token=$VERCEL_TOKEN \ + --env DATABASE_URL=$DATABASE_URL \ + --env DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED \ --env BETTER_AUTH_SECRET=$BETTER_AUTH_SECRET \ --env NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \ --env NEXT_PUBLIC_WEB_URL=$NEXT_PUBLIC_WEB_URL \ @@ -356,23 +353,22 @@ jobs: deploy-admin: name: Deploy Admin to Vercel - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -448,16 +444,15 @@ jobs: deploy-electric: name: Deploy Electric to Fly.io - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Fly CLI - uses: superfly/flyctl-actions/setup-flyctl@master + uses: superfly/flyctl-actions/setup-flyctl@ed8efb33836e8b2096c7fd3ba1c8afe303ebbff1 # 1.6 - name: Stage secrets env: @@ -476,22 +471,21 @@ jobs: deploy-electric-proxy: name: Deploy Electric Proxy to Cloudflare - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -508,23 +502,22 @@ jobs: deploy-docs: name: Deploy Docs to Vercel - if: github.repository == 'superset-sh/superset' runs-on: ubuntu-latest environment: production needs: deploy-database steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} @@ -540,6 +533,8 @@ jobs: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + DATABASE_URL_UNPOOLED: ${{ secrets.DATABASE_URL_UNPOOLED }} NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }} NEXT_PUBLIC_MARKETING_URL: ${{ secrets.NEXT_PUBLIC_MARKETING_URL }} @@ -553,6 +548,8 @@ jobs: vercel pull --yes --environment=production --token=$VERCEL_TOKEN vercel build --prod --token=$VERCEL_TOKEN vercel deploy --prod --prebuilt --archive=tgz --token=$VERCEL_TOKEN \ + --env DATABASE_URL=$DATABASE_URL \ + --env DATABASE_URL_UNPOOLED=$DATABASE_URL_UNPOOLED \ --env NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY \ --env NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST \ --env NEXT_PUBLIC_SENTRY_DSN_DOCS=$NEXT_PUBLIC_SENTRY_DSN_DOCS \ diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml index bcbf1918dbd..17aeda11096 100644 --- a/.github/workflows/generate-changelog.yml +++ b/.github/workflows/generate-changelog.yml @@ -17,18 +17,18 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} diff --git a/.github/workflows/release-desktop-canary.yml b/.github/workflows/release-desktop-canary.yml index 51c3a92f37f..061eb3a0ab1 100644 --- a/.github/workflows/release-desktop-canary.yml +++ b/.github/workflows/release-desktop-canary.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 @@ -88,10 +88,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: release-artifacts pattern: desktop-canary-* @@ -138,7 +138,7 @@ jobs: git push origin :refs/tags/desktop-canary || true - name: Create Canary Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: tag_name: desktop-canary name: "Superset Desktop Canary" diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 717b1a3806d..91be7e1cadb 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: echo "Previous tag: ${PREVIOUS_TAG:-none}" - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: release-artifacts pattern: desktop-* diff --git a/.github/workflows/setup-automations-schedule.yml b/.github/workflows/setup-automations-schedule.yml new file mode 100644 index 00000000000..e5c3f6ee27c --- /dev/null +++ b/.github/workflows/setup-automations-schedule.yml @@ -0,0 +1,36 @@ +name: Setup Automations Schedule + +on: + workflow_dispatch: + +jobs: + setup: + name: Ensure QStash schedule exists + runs-on: ubuntu-latest + environment: production + + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Bun + id: setup-bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: .bun-version + + - name: Cache dependencies + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} + + - name: Install dependencies + run: bun install --frozen --ignore-scripts + + - name: Create schedule + env: + NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} + QSTASH_TOKEN: ${{ secrets.QSTASH_TOKEN }} + QSTASH_URL: ${{ secrets.QSTASH_URL }} + run: bun run apps/api/scripts/setup-automations-schedule.ts diff --git a/.github/workflows/triage-issue.yml b/.github/workflows/triage-issue.yml index 9e405193c8f..1d44af19c4f 100644 --- a/.github/workflows/triage-issue.yml +++ b/.github/workflows/triage-issue.yml @@ -27,16 +27,16 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 5f3dfc9f5f2..056b0a6b5fe 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -17,18 +17,18 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 - name: Setup Bun id: setup-bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.bun/install/cache key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ hashFiles('bun.lock') }} diff --git a/README.md b/README.md index 40bc76bab43..648235d9497 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,10 @@ echo 'SKIP_ENV_VALIDATION=1' >> .env ```bash # Install caddy: brew install caddy (macOS) or see https://caddyserver.com/docs/install cp Caddyfile.example Caddyfile + +# Without this, Chromium rejects https://localhost:* with ERR_CERT_AUTHORITY_INVALID. +# Prompts for sudo once. +caddy trust ``` **4. Install dependencies and run** diff --git a/apps/admin/package.json b/apps/admin/package.json index b6a7a7bce52..8c6bec93071 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -23,9 +23,9 @@ "@trpc/client": "^11.7.1", "@trpc/server": "^11.7.1", "@trpc/tanstack-react-query": "^11.7.1", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "date-fns": "^4.1.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "import-in-the-middle": "2.0.1", "next": "^16.0.10", "next-themes": "^0.4.6", diff --git a/apps/api/package.json b/apps/api/package.json index 24595a756ba..f7e4aab1ae8 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -12,9 +12,8 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.78.0", - "@better-auth/oauth-provider": "1.5.6", + "@better-auth/oauth-provider": "1.6.5", "@durable-streams/client": "^0.2.3", - "@electric-sql/client": "1.5.15", "@linear/sdk": "^68.1.0", "@modelcontextprotocol/sdk": "^1.26.0", "@octokit/app": "^16.1.2", @@ -35,9 +34,9 @@ "@upstash/ratelimit": "^2.0.4", "@upstash/redis": "^1.34.3", "@vercel/blob": "^2.0.0", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "date-fns": "^4.1.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "import-in-the-middle": "2.0.1", "jose": "^6.1.3", "lodash.chunk": "^4.2.0", diff --git a/apps/api/src/app/api/desktop/version/route.ts b/apps/api/src/app/api/desktop/version/route.ts index 01751c8d186..2e6dff66c7e 100644 --- a/apps/api/src/app/api/desktop/version/route.ts +++ b/apps/api/src/app/api/desktop/version/route.ts @@ -1,4 +1,4 @@ -const MINIMUM_DESKTOP_VERSION = "0.0.48"; +const MINIMUM_DESKTOP_VERSION = "1.5.0"; /** * Used to force the desktop app to update, in cases where we can't support diff --git a/apps/api/src/app/api/electric/[...path]/route.ts b/apps/api/src/app/api/electric/[...path]/route.ts deleted file mode 100644 index 21e552bfcab..00000000000 --- a/apps/api/src/app/api/electric/[...path]/route.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { ELECTRIC_PROTOCOL_QUERY_PARAMS } from "@electric-sql/client"; -import { auth } from "@superset/auth/server"; -import { env } from "@/env"; -import { buildWhereClause } from "./utils"; - -interface AuthInfo { - userId: string; - organizationIds: string[]; -} - -async function authenticate(request: Request): Promise { - const bearer = request.headers.get("Authorization"); - if (bearer?.startsWith("Bearer ")) { - const token = bearer.slice(7); - try { - const { payload } = await auth.api.verifyJWT({ body: { token } }); - if (payload?.sub && Array.isArray(payload.organizationIds)) { - return { - userId: payload.sub, - organizationIds: payload.organizationIds as string[], - }; - } - } catch {} - } - - const sessionData = await auth.api.getSession({ headers: request.headers }); - if (!sessionData?.user) return null; - return { - userId: sessionData.user.id, - organizationIds: sessionData.session.organizationIds ?? [], - }; -} - -export async function GET(request: Request): Promise { - const authInfo = await authenticate(request); - if (!authInfo) { - return new Response("Unauthorized", { status: 401 }); - } - - const url = new URL(request.url); - - const organizationId = url.searchParams.get("organizationId"); - - if (organizationId && !authInfo.organizationIds.includes(organizationId)) { - return new Response("Not a member of this organization", { status: 403 }); - } - - const originUrl = new URL(env.ELECTRIC_URL); - originUrl.searchParams.set("secret", env.ELECTRIC_SECRET); - - url.searchParams.forEach((value, key) => { - if (ELECTRIC_PROTOCOL_QUERY_PARAMS.includes(key)) { - originUrl.searchParams.set(key, value); - } - }); - - const tableName = url.searchParams.get("table"); - if (!tableName) { - return new Response("Missing table parameter", { status: 400 }); - } - - const whereClause = await buildWhereClause( - tableName, - organizationId ?? "", - authInfo.userId, - ); - if (!whereClause) { - return new Response(`Unknown table: ${tableName}`, { status: 400 }); - } - - originUrl.searchParams.set("table", tableName); - originUrl.searchParams.set("where", whereClause.fragment); - whereClause.params.forEach((value, index) => { - originUrl.searchParams.set(`params[${index + 1}]`, String(value)); - }); - - if (tableName === "auth.apikeys") { - originUrl.searchParams.set( - "columns", - "id,name,start,created_at,last_request", - ); - } - - if (tableName === "integration_connections") { - originUrl.searchParams.set( - "columns", - "id,organization_id,connected_by_user_id,provider,token_expires_at,external_org_id,external_org_name,config,created_at,updated_at", - ); - } - - const response = await fetch(originUrl.toString()); - - const headers = new Headers(response.headers); - if (headers.get("content-encoding")) { - headers.delete("content-encoding"); - headers.delete("content-length"); - } - - return new Response(response.body, { - status: response.status, - statusText: response.statusText, - headers, - }); -} diff --git a/apps/api/src/app/api/electric/[...path]/utils.ts b/apps/api/src/app/api/electric/[...path]/utils.ts deleted file mode 100644 index 7206700204a..00000000000 --- a/apps/api/src/app/api/electric/[...path]/utils.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { db } from "@superset/db/client"; -import { - agentCommands, - chatSessions, - devicePresence, - githubPullRequests, - githubRepositories, - integrationConnections, - invitations, - members, - organizations, - projects, - sessionHosts, - subscriptions, - taskStatuses, - tasks, - v2Clients, - v2Hosts, - v2Projects, - v2UsersHosts, - v2Workspaces, - workspaces, -} from "@superset/db/schema"; -import { eq, inArray, sql } from "drizzle-orm"; -import type { PgColumn, PgTable } from "drizzle-orm/pg-core"; -import { QueryBuilder } from "drizzle-orm/pg-core"; - -export type AllowedTable = - | "tasks" - | "task_statuses" - | "projects" - | "v2_hosts" - | "v2_clients" - | "v2_projects" - | "v2_users_hosts" - | "v2_workspaces" - | "auth.members" - | "auth.organizations" - | "auth.users" - | "auth.invitations" - | "auth.apikeys" - | "device_presence" - | "agent_commands" - | "integration_connections" - | "subscriptions" - | "workspaces" - | "chat_sessions" - | "session_hosts" - | "github_repositories" - | "github_pull_requests"; - -interface WhereClause { - fragment: string; - params: unknown[]; -} - -function build(table: PgTable, column: PgColumn, id: string): WhereClause { - const whereExpr = eq(sql`${sql.identifier(column.name)}`, id); - const qb = new QueryBuilder(); - const { sql: query, params } = qb - .select() - .from(table) - .where(whereExpr) - .toSQL(); - const fragment = query.replace(/^select .* from .* where\s+/i, ""); - return { fragment, params }; -} - -export async function buildWhereClause( - tableName: string, - organizationId: string, - userId: string, -): Promise { - switch (tableName) { - case "tasks": - return build(tasks, tasks.organizationId, organizationId); - - case "task_statuses": - return build(taskStatuses, taskStatuses.organizationId, organizationId); - - case "projects": - return build(projects, projects.organizationId, organizationId); - - case "v2_projects": - return build(v2Projects, v2Projects.organizationId, organizationId); - - case "v2_hosts": - return build(v2Hosts, v2Hosts.organizationId, organizationId); - - case "v2_clients": - return build(v2Clients, v2Clients.organizationId, organizationId); - - case "v2_users_hosts": - return build(v2UsersHosts, v2UsersHosts.organizationId, organizationId); - - case "v2_workspaces": - return build(v2Workspaces, v2Workspaces.organizationId, organizationId); - - case "auth.members": - return build(members, members.organizationId, organizationId); - - case "auth.invitations": - return build(invitations, invitations.organizationId, organizationId); - - case "auth.organizations": { - // Use the authenticated user's ID to find their organizations - const userMemberships = await db.query.members.findMany({ - where: eq(members.userId, userId), - columns: { organizationId: true }, - }); - - if (userMemberships.length === 0) { - return { fragment: "1 = 0", params: [] }; - } - - const orgIds = [...new Set(userMemberships.map((m) => m.organizationId))]; - const whereExpr = inArray( - sql`${sql.identifier(organizations.id.name)}`, - orgIds, - ); - const qb = new QueryBuilder(); - const { sql: query, params } = qb - .select() - .from(organizations) - .where(whereExpr) - .toSQL(); - const fragment = query.replace(/^select .* from .* where\s+/i, ""); - return { fragment, params }; - } - - case "auth.users": { - const fragment = `$1 = ANY("organization_ids")`; - return { fragment, params: [organizationId] }; - } - - case "device_presence": - return build( - devicePresence, - devicePresence.organizationId, - organizationId, - ); - - case "agent_commands": - return build(agentCommands, agentCommands.organizationId, organizationId); - - case "auth.apikeys": { - const fragment = `"metadata" LIKE '%"organizationId":"' || $1 || '"%'`; - return { fragment, params: [organizationId] }; - } - - case "integration_connections": - return build( - integrationConnections, - integrationConnections.organizationId, - organizationId, - ); - - case "subscriptions": - return build(subscriptions, subscriptions.referenceId, organizationId); - - case "workspaces": - return build(workspaces, workspaces.organizationId, organizationId); - - case "chat_sessions": - return build(chatSessions, chatSessions.organizationId, organizationId); - - case "session_hosts": - return build(sessionHosts, sessionHosts.organizationId, organizationId); - - case "github_repositories": - return build( - githubRepositories, - githubRepositories.organizationId, - organizationId, - ); - - case "github_pull_requests": - return build( - githubPullRequests, - githubPullRequests.organizationId, - organizationId, - ); - - default: - return null; - } -} diff --git a/apps/api/src/env.ts b/apps/api/src/env.ts index 9c778d7d818..ce4a0b1564e 100644 --- a/apps/api/src/env.ts +++ b/apps/api/src/env.ts @@ -10,10 +10,6 @@ export const env = createEnv({ server: { DATABASE_URL: z.string(), DATABASE_URL_UNPOOLED: z.string(), - ELECTRIC_URL: z.string().url(), - ELECTRIC_SECRET: z.string().min(16), - ELECTRIC_SOURCE_ID: z.string().optional(), - ELECTRIC_SOURCE_SECRET: z.string().optional(), BLOB_READ_WRITE_TOKEN: z.string(), GOOGLE_CLIENT_ID: z.string().min(1), GOOGLE_CLIENT_SECRET: z.string().min(1), diff --git a/apps/api/src/proxy.ts b/apps/api/src/proxy.ts index 8e28b5829e2..6451123950c 100644 --- a/apps/api/src/proxy.ts +++ b/apps/api/src/proxy.ts @@ -29,15 +29,8 @@ function getCorsHeaders(origin: string | null, deploymentOrigin: string) { "Access-Control-Allow-Origin": isAllowed ? origin : "", "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS", "Access-Control-Allow-Headers": - "Content-Type, Authorization, x-trpc-source, trpc-accept, X-Electric-Backend, Producer-Id, Producer-Epoch, Producer-Seq, Stream-Closed", + "Content-Type, Authorization, x-trpc-source, trpc-accept, Producer-Id, Producer-Epoch, Producer-Seq, Stream-Closed", "Access-Control-Expose-Headers": [ - // Electric sync headers - "electric-offset", - "electric-handle", - "electric-schema", - "electric-cursor", - "electric-chunk-last-offset", - "electric-up-to-date", // Durable stream headers "Stream-Next-Offset", "Stream-Cursor", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a519a46713f..a96499c66f5 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -40,8 +40,8 @@ "@ai-sdk/openai": "3.0.36", "@ai-sdk/react": "^3.0.0", "@ast-grep/napi": "^0.41.0", - "@better-auth/api-key": "1.5.6", - "@better-auth/stripe": "1.5.6", + "@better-auth/api-key": "1.6.5", + "@better-auth/stripe": "1.6.5", "@codemirror/commands": "^6.10.2", "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-css": "^6.3.1", @@ -143,22 +143,22 @@ "@types/express": "^5.0.5", "@types/pidusage": "^2.0.5", "@vercel/blob": "^2.0.0", - "@vscode/ripgrep": "^1.15.9", - "@xterm/addon-clipboard": "0.3.0-beta.195", - "@xterm/addon-fit": "0.12.0-beta.195", - "@xterm/addon-image": "0.10.0-beta.195", - "@xterm/addon-ligatures": "0.11.0-beta.195", - "@xterm/addon-progress": "0.3.0-beta.195", - "@xterm/addon-search": "0.17.0-beta.195", - "@xterm/addon-serialize": "0.15.0-beta.195", - "@xterm/addon-unicode11": "0.10.0-beta.195", - "@xterm/addon-webgl": "0.20.0-beta.194", - "@xterm/headless": "6.1.0-beta.195", - "@xterm/xterm": "6.1.0-beta.195", +"@vscode/ripgrep": "^1.15.9", + "@xterm/addon-clipboard": "0.3.0-beta.197", + "@xterm/addon-fit": "0.12.0-beta.197", + "@xterm/addon-image": "0.10.0-beta.197", + "@xterm/addon-ligatures": "0.11.0-beta.197", + "@xterm/addon-progress": "0.3.0-beta.197", + "@xterm/addon-search": "0.17.0-beta.197", + "@xterm/addon-serialize": "0.15.0-beta.197", + "@xterm/addon-unicode11": "0.10.0-beta.197", + "@xterm/addon-webgl": "0.20.0-beta.196", + "@xterm/headless": "6.1.0-beta.197", + "@xterm/xterm": "6.1.0-beta.197", "@xyflow/react": "^12.10.0", "ai": "^6.0.0", - "ansi_up": "^6.0.6", - "better-auth": "1.5.6", +"ansi_up": "^6.0.6", + "better-auth": "1.6.5", "better-sqlite3": "12.6.2", "bindings": "^1.5.0", "bufferutil": "^4.1.0", @@ -177,7 +177,7 @@ "dockerfile-language-service": "0.16.1", "dockerfile-utils": "0.16.3", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "electron-updater": "^6.8.3", "elkjs": "^0.11.1", "exceljs": "^4.4.0", diff --git a/apps/desktop/plans/20260417-1830-lsof-excessive-spawning-3372.md b/apps/desktop/plans/20260417-1830-lsof-excessive-spawning-3372.md new file mode 100644 index 00000000000..63b59d57c90 --- /dev/null +++ b/apps/desktop/plans/20260417-1830-lsof-excessive-spawning-3372.md @@ -0,0 +1,74 @@ +# Stop Excessive `lsof` Process Spawning (Issue #3372) + +## Problem + +[#3372](https://github.com/superset-sh/superset/issues/3372): Superset spawns a growing pile of `lsof` processes. Symptoms: CPU pinned at 100%, count grows with open workspaces, closing workspaces doesn't help, quitting Superset leaves `lsof` behind. + +Related: [#3235](https://github.com/superset-sh/superset/issues/3235) โ€” EDR agents amplify every spawn, so fixing this also reduces their CPU. + +## Root Causes (three, compounding) + +All in `apps/desktop/src/main/lib/terminal/`. + +1. **Interval never stops.** `PortManager` constructor called `startPeriodicScan()` at module load. The 2.5s `setInterval` kept firing forever โ€” zero sessions, closed workspaces, whatever. +2. **Hint scans run concurrently with the bulk scan.** `scanPane` had no `isScanning` guard. Hint regexes `/port\s+(\d+)/i` and `/:(\d{4,5})\s*$/` were so loose they matched routine `git`/`ssh` output, firing spurious scans on top of the periodic ones. +3. **`lsof` children outlive us.** Code ran `exec("sh -c 'lsof โ€ฆ || true'")`. On timeout, Node SIGTERMs the shell; the shell doesn't forward to `lsof`; the child gets reparented to `launchd`/`init` and survives even app quit. + +## Fix (minimum-churn, one PR) + +1. **Lifecycle:** interval starts on first `registerSession`/`upsertDaemonSession`, stops on the last unregister. +2. **Coalesce:** one debounced hint timer + a `scanRequested` flag. If a hint or tick fires mid-scan, queue exactly one follow-up. `maxInFlight == 1` guaranteed. +3. **No orphans:** `execFile` instead of `exec` (no shell wrapper). `AbortController` on `PortManager`; `stopPeriodicScan` aborts the in-flight child. +4. **Regex noise:** delete the two over-broad patterns; keep the three that imply a real listener (`listening on`, `server started`, `ready on`). + +## Alternatives Considered (and why rejected) + +- **A3, event-driven only (no interval):** misses silent port openers. Deferred. +- **B1, shared `isScanning` flag only:** still drops detection for up to 2.5s with no follow-up guarantee. B2 is strictly better for the same worst-case latency. +- **B3, per-pane `isScanning` + semaphore:** more state, same behavior as B2. +- **C3, `killSignal: "SIGKILL"`:** kills the shell, child still orphans. Doesn't address the root issue. +- **D3, delete all hints:** loses fast-detection for dev servers (UX regression). +- **Option 1: delete the whole dynamic-port subsystem and rely on `.superset/ports.json`:** attractive (-1500 lines) but regresses feature for users without a static config. +- **Option 2: delete periodic scan, hint-only:** halves the code but misses silent port openers. +- **Option 4: delete `lsof` entirely, parse ports from terminal output:** most elegant (-700 lines) but loses PID info (Kill Port), still has edge cases. + +Chose minimum-churn because the real cost isn't `lsof`'s per-call expense (~100 ms on the fast path) โ€” it's the three lifecycle bugs multiplying it. Fix those and the feature works fine. + +## Prior Attempt โ€” Superseded + +Auto-generated PR [#3373](https://github.com/superset-sh/superset/pull/3373) by `github-actions[bot]` addresses lifecycle + a weaker `isScanning` guard on `scanPane`. Leaves the orphan-on-timeout and noisy-regex causes untouched. This PR addresses all three. + +## Progress + +- [x] (2026-04-17) Lifecycle: lazy start/stop via `ensurePeriodicScanRunning` / `stopPeriodicScanIfIdle` +- [x] (2026-04-17) Concurrency: `scanRequested` follow-up flag; deleted `scanPane`, `scanPidTreeAndUpdate`, `pendingHintScans` +- [x] (2026-04-17) `execFile` + `AbortSignal`; `runTolerant` helper for lsof exit-1 +- [x] (2026-04-17) `AbortController` aborted on `stopPeriodicScan` +- [x] (2026-04-17) Deleted the two over-broad hint regexes +- [x] (2026-04-17) Deleted dead `getProcessName` export and unused `paneId` parameter +- [x] (2026-04-17) 13 regression tests in `port-manager.test.ts`; A/B verified (8 fail on `main`) +- [x] (2026-04-17) `bun run typecheck` + `bun run lint:fix` clean; 127/127 terminal tests pass +- [x] (2026-04-17) PR [#3547](https://github.com/superset-sh/superset/pull/3547) opened +- [ ] Manual validation on macOS with 10 workspaces +- [ ] #3547 merged, #3372 and #3373 closed + +## Surprises + +- `execFile` via `promisify` rejects on non-zero exit codes. `lsof` exits 1 when its `-p` filter matches no PIDs โ€” legitimate empty result. Added `runTolerant` helper that reads `err.stdout` off the rejection. +- The production `getListeningPortsLsof` swallows all errors and returns `[]`. The initial test mock rejected on abort, which broke `forceScan`'s contract; fixed by mirroring production (resolve on abort). +- `getProcessName` was exported but had zero in-repo call sites. Likely dead since a prior hint-scan refactor. + +## Decisions + +- **Supersede #3373.** It fixes ~60% of the bug. Three causes โ†’ one PR is easier to review and revert. +- **Coalesce (B2) over shared-flag (B1).** B1 silently drops hint scans; B2 guarantees a follow-up at the same worst-case latency. +- **`execFile` + `AbortController`, not shell `exec`.** Removes the `sh -c` wrapper that strands children. Signal delivery becomes deterministic. +- **Delete the two over-broad regexes.** Routine non-port text shouldn't trigger scans. + +## Outcome + +- `port-manager.ts`: +36 / โˆ’110 +- `port-scanner.ts`: +52 / โˆ’40 +- `port-manager.test.ts`: +255 (new, 13 tests) + +A/B (mocked `lsof`): 100 hint-matching chunks during a 30 ms scan โ†’ โ‰ค2 `lsof` calls, `maxInFlight == 1`. On `main`: unbounded concurrency. diff --git a/apps/desktop/src/lib/trpc/routers/external/index.ts b/apps/desktop/src/lib/trpc/routers/external/index.ts index 431ae4a3b4c..bc779bf1c05 100644 --- a/apps/desktop/src/lib/trpc/routers/external/index.ts +++ b/apps/desktop/src/lib/trpc/routers/external/index.ts @@ -16,6 +16,7 @@ import { shell, } from "electron"; import { localDb } from "main/lib/local-db"; +import { externalUrlLogLabel, isSafeExternalUrl } from "main/lib/safe-url"; import { z } from "zod"; import { publicProcedure, router } from "../.."; import { getWorkspace } from "../workspaces/utils/db-helpers"; @@ -153,12 +154,26 @@ async function openPathInApp( export const createExternalRouter = () => { return router({ openUrl: publicProcedure.input(z.string()).mutation(async ({ input }) => { + if (!isSafeExternalUrl(input)) { + console.warn( + "[external/openUrl] Blocked unsafe URL scheme:", + externalUrlLogLabel(input), + ); + throw new TRPCError({ + code: "BAD_REQUEST", + message: "URL scheme not allowed", + }); + } try { await shell.openExternal(input); } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; - console.error("[external/openUrl] Failed to open URL:", input, error); + console.error( + "[external/openUrl] Failed to open URL:", + externalUrlLogLabel(input), + error, + ); throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: errorMessage, diff --git a/apps/desktop/src/lib/trpc/routers/settings/index.ts b/apps/desktop/src/lib/trpc/routers/settings/index.ts index a04b765e43f..2650cef1c97 100644 --- a/apps/desktop/src/lib/trpc/routers/settings/index.ts +++ b/apps/desktop/src/lib/trpc/routers/settings/index.ts @@ -48,6 +48,10 @@ import { DEFAULT_RINGTONE_ID, isBuiltInRingtoneId, } from "shared/ringtones"; +import { + applyLegacyPermissionsOverrides, + terminalPresetsMatchPre3546Seed, +} from "@superset/shared/agent-permissions-migration"; import { type AgentDefinitionId, applyCustomAgentDefinitionPatch, @@ -140,7 +144,42 @@ function saveTerminalPresets( .run(); } +let agentPresetPermissionsMigrationChecked = false; + +function runAgentPresetPermissionsMigration() { + if (agentPresetPermissionsMigrationChecked) return; + const row = getSettings(); + if (row.agentPresetPermissionsMigratedAt) { + agentPresetPermissionsMigrationChecked = true; + return; + } + + const isExistingUser = + row.terminalPresetsInitialized === true && + terminalPresetsMatchPre3546Seed(row.terminalPresets); + + const nextOverrides = isExistingUser + ? applyLegacyPermissionsOverrides( + readAgentPresetOverrides(row.agentPresetOverrides), + ) + : undefined; + + const now = Date.now(); + const setFields = { + agentPresetPermissionsMigratedAt: now, + ...(nextOverrides ? { agentPresetOverrides: nextOverrides } : {}), + }; + localDb + .insert(settings) + .values({ id: 1, ...setFields }) + .onConflictDoUpdate({ target: settings.id, set: setFields }) + .run(); + + agentPresetPermissionsMigrationChecked = true; +} + function readRawAgentPresetOverrides(): AgentPresetOverrideEnvelope { + runAgentPresetPermissionsMigration(); const row = getSettings(); return readAgentPresetOverrides(row.agentPresetOverrides); } diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.test.ts b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.test.ts new file mode 100644 index 00000000000..3dd93a28882 --- /dev/null +++ b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.test.ts @@ -0,0 +1,247 @@ +import { describe, expect, mock, test } from "bun:test"; + +/** + * Tests for getGitHubStatus procedure logic. + * + * Reproduces #2592: branch workspaces (no worktreeId) returned null + * from getGitHubStatus because the procedure required a worktree record. + */ + +const mockGetWorkspace = mock(); +const mockGetWorktree = mock(); +const mockGetProject = mock(); +const mockGetWorkspacePath = mock(); +const mockFetchGitHubPRStatus = mock(); +const mockFetchGitHubPRComments = mock(); +const mockUpdateProjectDefaultBranch = mock(); +const mockLocalDb = { + update: mock(() => ({ + set: mock(() => ({ + where: mock(() => ({ + run: mock(), + })), + })), + })), + select: mock(() => ({ + from: mock(() => ({ + where: mock(() => ({ + all: mock(() => []), + get: mock(() => undefined), + })), + })), + })), +}; + +// Mock @superset/local-db +mock.module("@superset/local-db", () => ({ + workspaces: { id: "id" }, + worktrees: { id: "id", projectId: "project_id" }, +})); + +mock.module("drizzle-orm", () => ({ + eq: mock(() => "eq"), + and: mock((...args: unknown[]) => args), + isNull: mock(() => "isNull"), +})); + +mock.module("../utils/db-helpers", () => ({ + getWorkspace: mockGetWorkspace, + getWorktree: mockGetWorktree, + getProject: mockGetProject, + updateProjectDefaultBranch: mockUpdateProjectDefaultBranch, +})); + +mock.module("../utils/worktree", () => ({ + getWorkspacePath: mockGetWorkspacePath, +})); + +mock.module("../utils/github", () => ({ + fetchGitHubPRComments: mockFetchGitHubPRComments, + fetchGitHubPRStatus: mockFetchGitHubPRStatus, + clearGitHubCachesForWorktree: mock(), + resolveReviewThread: mock(), +})); + +mock.module("main/lib/local-db", () => ({ + localDb: mockLocalDb, +})); + +mock.module("../../..", () => ({ + publicProcedure: { + input: () => ({ + query: (fn: unknown) => fn, + mutation: (fn: unknown) => fn, + }), + }, + router: (routes: Record) => routes, +})); + +mock.module("../utils/git", () => ({ + branchExistsOnRemote: mock(() => ({ status: "missing" })), + fetchDefaultBranch: mock(), + getAheadBehindCount: mock(() => ({ ahead: 0, behind: 0 })), + getDefaultBranch: mock(() => "main"), + listExternalWorktrees: mock(() => []), + refreshDefaultBranch: mock(() => "main"), +})); + +mock.module("node:fs", () => ({ + existsSync: mock(() => true), +})); + +const { createGitStatusProcedures } = await import("./git-status"); + +const procedures = createGitStatusProcedures() as unknown as Record< + string, + (opts: { input: Record }) => Promise +>; + +const fakeGitHubStatus = { + pr: { number: 42, title: "Test PR", url: "https://github.com/test/pr/42" }, + repoUrl: "https://github.com/test/repo", + upstreamUrl: "https://github.com/test/repo", + isFork: false, + branchExistsOnRemote: true, + previewUrl: undefined, + lastRefreshed: Date.now(), +}; + +describe("getGitHubStatus", () => { + test("returns GitHub status for branch workspaces (no worktreeId)", async () => { + const branchWorkspace = { + id: "ws-branch-1", + projectId: "proj-1", + worktreeId: null, + type: "branch" as const, + branch: "feature/branch-workspace", + name: "Feature Branch", + }; + + mockFetchGitHubPRStatus.mockClear(); + mockGetWorktree.mockClear(); + mockGetWorkspace.mockReturnValue(branchWorkspace); + mockGetWorkspacePath.mockReturnValue("/repos/my-project"); + mockFetchGitHubPRStatus.mockResolvedValue(fakeGitHubStatus); + + const result = await procedures.getGitHubStatus({ + input: { workspaceId: "ws-branch-1" }, + }); + + expect(result).not.toBeNull(); + expect(mockGetWorkspacePath).toHaveBeenCalledWith(branchWorkspace); + expect(mockFetchGitHubPRStatus).toHaveBeenCalledWith( + "/repos/my-project", + "feature/branch-workspace", + ); + expect(mockGetWorktree).not.toHaveBeenCalled(); + }); + + test("returns GitHub status for worktree workspaces", async () => { + const worktreeWorkspace = { + id: "ws-wt-1", + projectId: "proj-1", + worktreeId: "wt-1", + type: "worktree" as const, + branch: "feature/foo", + name: "Feature Foo", + }; + + mockFetchGitHubPRStatus.mockClear(); + mockGetWorkspace.mockReturnValue(worktreeWorkspace); + mockGetWorktree.mockReturnValue({ + id: "wt-1", + path: "/repos/my-project/.worktrees/feature-foo", + branch: "feature/foo", + githubStatus: null, + }); + mockGetWorkspacePath.mockReturnValue( + "/repos/my-project/.worktrees/feature-foo", + ); + mockFetchGitHubPRStatus.mockResolvedValue(fakeGitHubStatus); + + const result = await procedures.getGitHubStatus({ + input: { workspaceId: "ws-wt-1" }, + }); + + expect(result).not.toBeNull(); + expect(mockFetchGitHubPRStatus).toHaveBeenCalledWith( + "/repos/my-project/.worktrees/feature-foo", + null, + ); + }); + + test("returns null when workspace not found", async () => { + mockGetWorkspace.mockReturnValue(undefined); + + const result = await procedures.getGitHubStatus({ + input: { workspaceId: "nonexistent" }, + }); + + expect(result).toBeNull(); + }); + + test("returns null when workspace path cannot be resolved", async () => { + mockGetWorkspace.mockReturnValue({ + id: "ws-1", + projectId: "proj-1", + worktreeId: null, + type: "branch", + }); + mockGetWorkspacePath.mockReturnValue(null); + + const result = await procedures.getGitHubStatus({ + input: { workspaceId: "ws-1" }, + }); + + expect(result).toBeNull(); + }); + + test("does not cache to worktrees table for branch workspaces", async () => { + const branchWorkspace = { + id: "ws-branch-2", + projectId: "proj-1", + worktreeId: null, + type: "branch" as const, + branch: "main", + }; + + mockGetWorkspace.mockReturnValue(branchWorkspace); + mockGetWorkspacePath.mockReturnValue("/repos/my-project"); + mockFetchGitHubPRStatus.mockResolvedValue(fakeGitHubStatus); + mockLocalDb.update.mockClear(); + + await procedures.getGitHubStatus({ + input: { workspaceId: "ws-branch-2" }, + }); + + expect(mockLocalDb.update).not.toHaveBeenCalled(); + }); +}); + +describe("getWorktreeInfo", () => { + test("returns info for branch workspaces", async () => { + const branchWorkspace = { + id: "ws-branch-3", + projectId: "proj-1", + worktreeId: null, + type: "branch" as const, + branch: "feature/my-branch", + name: "My Branch Workspace", + createdAt: 1234567890, + }; + + mockGetWorkspace.mockReturnValue(branchWorkspace); + + const result = await procedures.getWorktreeInfo({ + input: { workspaceId: "ws-branch-3" }, + }); + + expect(result).toEqual({ + worktreeName: "My Branch Workspace", + branchName: "feature/my-branch", + createdAt: 1234567890, + gitStatus: null, + githubStatus: null, + }); + }); +}); diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts index 3d3ba00ffe6..c3229e1dc1e 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts @@ -1,389 +1,40 @@ -import { existsSync, readFileSync } from "node:fs"; -import path from "node:path"; +import { existsSync } from "node:fs"; import type { GitHubStatus } from "@superset/local-db"; import { workspaces, worktrees } from "@superset/local-db"; -import { TRPCError } from "@trpc/server"; import { and, eq, isNull } from "drizzle-orm"; -import yaml from "js-yaml"; import { localDb } from "main/lib/local-db"; -import { workspaceInitManager } from "main/lib/workspace-init-manager"; -import { getWorkspaceRuntimeRegistry } from "main/lib/workspace-runtime"; import { z } from "zod"; import { publicProcedure, router } from "../../.."; import { - clearWorkspaceDeletingStatus, - deleteWorkspace, - deleteWorktreeRecord, getProject, getWorkspace, getWorktree, - hideProjectIfNoWorkspaces, - markWorkspaceAsDeleting, - updateActiveWorkspaceIfRemoved, updateProjectDefaultBranch, } from "../utils/db-helpers"; import { - branchExistsOnRemote, fetchDefaultBranch, getAheadBehindCount, - getCurrentBranch, getDefaultBranch, listExternalWorktrees, refreshDefaultBranch, } from "../utils/git"; import { - addPullRequestConversationComment, clearGitHubCachesForWorktree, - extractNwoFromUrl, - fetchCheckJobSteps, fetchGitHubPRComments, fetchGitHubPRStatus, - fetchGitHubPreviewUrl, - fetchJobStatuses, - fetchStructuredJobLogs, - getRepoContext, type PullRequestCommentsTarget, - replyToReviewThread, + resolveReviewThread, } from "../utils/github"; -import { githubSyncService } from "../utils/github/github-sync-service"; -import { GHIdentityCandidatesResponseSchema } from "../utils/github/types"; -import { execWithShellEnv } from "../utils/shell-env"; +import { getWorkspacePath } from "../utils/worktree"; const gitHubPRCommentsInputSchema = z.object({ workspaceId: z.string(), prNumber: z.number().int().positive().optional(), - prUrl: z.string().optional(), repoUrl: z.string().optional(), upstreamUrl: z.string().optional(), isFork: z.boolean().optional(), - forceFresh: z.boolean().optional(), }); -const ghRepositoryPullRequestSchema = z.object({ - number: z.number(), - title: z.string(), - url: z.string(), - state: z.enum(["OPEN", "CLOSED", "MERGED"]), - isDraft: z.boolean().optional().default(false), - headRefName: z.string().optional(), - updatedAt: z.string().nullable().optional(), - author: z - .object({ - login: z.string().optional(), - }) - .nullable() - .optional(), -}); - -const ghRepositoryWorkflowSchema = z.object({ - id: z.number(), - name: z.string(), - path: z.string().optional(), - state: z.string().optional(), -}); - -const ghRepositoryWorkflowsResponseSchema = z.object({ - workflows: z.array(ghRepositoryWorkflowSchema).optional(), -}); - -const ghRepositoryWorkflowRunSchema = z.object({ - id: z.number(), - name: z.string().nullable().optional(), - display_title: z.string().nullable().optional(), - html_url: z.string().optional(), - status: z.string().nullable().optional(), - conclusion: z.string().nullable().optional(), - event: z.string().nullable().optional(), - created_at: z.string().nullable().optional(), - updated_at: z.string().nullable().optional(), - run_started_at: z.string().nullable().optional(), - head_branch: z.string().nullable().optional(), - head_sha: z.string().nullable().optional(), - run_number: z.number().optional(), - workflow_id: z.number().optional(), -}); - -const ghRepositoryWorkflowRunsResponseSchema = z.object({ - workflow_runs: z.array(ghRepositoryWorkflowRunSchema).optional(), -}); - -const ghRepositoryLabelSchema = z.object({ - name: z.string(), - color: z.string().optional(), - description: z.string().nullable().optional(), -}); - -const ghRepositoryAssigneeSchema = z.object({ - login: z.string(), - avatar_url: z.string().optional(), -}); - -async function loadGitHubOverviewSegment({ - label, - load, - fallback, - workspaceId, - repositoryNameWithOwner, -}: { - label: string; - load: () => Promise; - fallback: T; - workspaceId: string; - repositoryNameWithOwner: string; -}): Promise { - try { - return await load(); - } catch (error) { - // Overview data is best-effort. A flaky GitHub endpoint should degrade this - // segment to empty data rather than failing the entire repository overview. - console.warn("[git-status/github-overview] Falling back to empty segment", { - label, - workspaceId, - repositoryNameWithOwner, - error, - }); - return fallback; - } -} - -function sanitizeIssueAssetBasename(value: string): string { - return value - .toLowerCase() - .replace(/[^a-z0-9._-]+/g, "-") - .replace(/-+/g, "-") - .replace(/^-|-$/g, "") - .slice(0, 80); -} - -function getIssueAssetExtension({ - filename, - mimeType, -}: { - filename?: string; - mimeType?: string; -}): string { - const lower = filename?.toLowerCase() ?? ""; - if (lower.endsWith(".png")) return "png"; - if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "jpg"; - if (lower.endsWith(".gif")) return "gif"; - if (lower.endsWith(".webp")) return "webp"; - - if (mimeType === "image/jpeg") return "jpg"; - if (mimeType === "image/gif") return "gif"; - if (mimeType === "image/webp") return "webp"; - return "png"; -} - -async function ensureGitHubBranchExists({ - repoPath, - repositoryNameWithOwner, - branchName, - baseBranch, -}: { - repoPath: string; - repositoryNameWithOwner: string; - branchName: string; - baseBranch: string; -}) { - try { - await execWithShellEnv( - "gh", - ["api", `repos/${repositoryNameWithOwner}/git/ref/heads/${branchName}`], - { cwd: repoPath }, - ); - return; - } catch (error) { - const errorText = - error instanceof Error - ? [ - error.message, - "stderr" in error && typeof error.stderr === "string" - ? error.stderr - : "", - "stdout" in error && typeof error.stdout === "string" - ? error.stdout - : "", - ] - .join("\n") - .toLowerCase() - : String(error).toLowerCase(); - const isMissingRefError = - errorText.includes("404") || - errorText.includes("not found") || - errorText.includes("no ref found"); - - if (!isMissingRefError) { - console.warn("[git-status] GitHub branch probe failed", { - repoPath, - repositoryNameWithOwner, - branchName, - baseBranch, - error, - }); - throw error; - } - - console.warn("[git-status] GitHub branch not found, creating branch", { - repoPath, - repositoryNameWithOwner, - branchName, - baseBranch, - error, - }); - } - - const { stdout } = await execWithShellEnv( - "gh", - ["api", `repos/${repositoryNameWithOwner}/git/ref/heads/${baseBranch}`], - { cwd: repoPath }, - ); - const raw = JSON.parse(stdout) as { - object?: { sha?: string }; - }; - const sha = raw.object?.sha; - if (!sha) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "Could not determine the base branch SHA for issue assets.", - }); - } - - await execWithShellEnv( - "gh", - [ - "api", - "--method", - "POST", - `repos/${repositoryNameWithOwner}/git/refs`, - "-f", - `ref=refs/heads/${branchName}`, - "-f", - `sha=${sha}`, - ], - { cwd: repoPath }, - ); -} - -function parseRunIdFromActionsUrl(detailsUrl?: string): string | null { - if (!detailsUrl) { - return null; - } - - try { - const url = new URL(detailsUrl); - const match = url.pathname.match(/\/actions\/runs\/(\d+)(?:\/|$)/); - return match?.[1] ?? null; - } catch { - return null; - } -} - -function isGitHubActionsUrl(url?: string): boolean { - return parseRunIdFromActionsUrl(url) !== null; -} - -interface WorkflowDispatchInput { - name: string; - description: string; - required: boolean; - default: string; - type: "string" | "choice" | "boolean" | "number" | "environment"; - options: string[]; -} - -interface WorkflowDispatchInfo { - supportsDispatch: boolean; - inputs: WorkflowDispatchInput[]; -} - -function parseWorkflowDispatchInfo({ - repoPath, - workflowPath, -}: { - repoPath: string; - workflowPath?: string; -}): WorkflowDispatchInfo { - const noDispatch: WorkflowDispatchInfo = { - supportsDispatch: false, - inputs: [], - }; - - if (!workflowPath) { - return noDispatch; - } - - const absolutePath = path.join(repoPath, workflowPath); - if (!existsSync(absolutePath)) { - return noDispatch; - } - - let content: string; - try { - content = readFileSync(absolutePath, "utf8"); - } catch { - return noDispatch; - } - - const hasDispatch = - /^\s*workflow_dispatch\s*:/m.test(content) || - /^\s*on\s*:\s*workflow_dispatch\s*$/m.test(content) || - /^\s*on\s*:\s*\[[^\]]*\bworkflow_dispatch\b[^\]]*\]/m.test(content); - - if (!hasDispatch) { - return noDispatch; - } - - try { - const parsed = yaml.load(content) as Record | null; - if (!parsed || typeof parsed !== "object") { - return { supportsDispatch: true, inputs: [] }; - } - - const onBlock = parsed.on ?? parsed.true; - if (!onBlock || typeof onBlock !== "object") { - return { supportsDispatch: true, inputs: [] }; - } - - const dispatchBlock = (onBlock as Record) - .workflow_dispatch; - if (!dispatchBlock || typeof dispatchBlock !== "object") { - return { supportsDispatch: true, inputs: [] }; - } - - const rawInputs = (dispatchBlock as Record).inputs; - if (!rawInputs || typeof rawInputs !== "object") { - return { supportsDispatch: true, inputs: [] }; - } - - const inputs: WorkflowDispatchInput[] = Object.entries( - rawInputs as Record, - ).map(([name, value]) => { - const input = (value ?? {}) as Record; - const inputType = String(input.type ?? "string"); - const options: string[] = Array.isArray(input.options) - ? input.options.map(String) - : []; - - return { - name, - description: String(input.description ?? ""), - required: Boolean(input.required ?? false), - default: String(input.default ?? ""), - type: ( - ["string", "choice", "boolean", "number", "environment"] as const - ).includes(inputType as never) - ? (inputType as WorkflowDispatchInput["type"]) - : "string", - options, - }; - }); - - return { supportsDispatch: true, inputs }; - } catch { - return { supportsDispatch: true, inputs: [] }; - } -} - function resolveCommentsPullRequestTarget({ input, githubStatus, @@ -409,7 +60,6 @@ function resolveCommentsPullRequestTarget({ return { prNumber, - prUrl: input.prUrl ?? githubStatus?.pr?.url, repoContext: { repoUrl, upstreamUrl, @@ -434,7 +84,7 @@ function hasMeaningfulGitHubStatusChange({ next, }: { current: GitHubStatus | null | undefined; - next: GitHubStatus | null; + next: GitHubStatus; }): boolean { return ( JSON.stringify(stripGitHubStatusTimestamp(current)) !== @@ -442,845 +92,6 @@ function hasMeaningfulGitHubStatusChange({ ); } -function resolveRepoPathForWorkspace(workspaceId: string): { - workspace: NonNullable>; - worktree: NonNullable> | null; - repoPath: string; -} { - const workspace = getWorkspace(workspaceId); - if (!workspace) { - throw new TRPCError({ - code: "NOT_FOUND", - message: `Workspace ${workspaceId} not found`, - }); - } - - const worktree = workspace.worktreeId - ? (getWorktree(workspace.worktreeId) ?? null) - : null; - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } - - if (!repoPath) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "GitHub is not available for this workspace.", - }); - } - - return { workspace, worktree, repoPath }; -} - -async function getFreshPullRequestForWorkspace(workspaceId: string): Promise<{ - repoPath: string; - worktree: NonNullable> | null; - pullRequest: NonNullable; -}> { - const { repoPath, worktree } = resolveRepoPathForWorkspace(workspaceId); - clearGitHubCachesForWorktree(repoPath); - const githubStatus = await fetchGitHubPRStatus(repoPath); - const pullRequest = githubStatus?.pr ?? null; - - if (!pullRequest) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "No pull request found for this workspace.", - }); - } - - return { repoPath, worktree, pullRequest }; -} - -async function resolveRepositoryTargetForWorkspace( - workspaceId: string, -): Promise<{ - repoPath: string; - worktree: NonNullable> | null; - repositoryUrl: string; - repositoryNameWithOwner: string; - upstreamUrl: string; - upstreamNameWithOwner: string; - isFork: boolean; - branchExistsOnRemote: boolean; - currentBranch: string; - defaultBranch: string; -}> { - const { repoPath, worktree } = resolveRepoPathForWorkspace(workspaceId); - const [githubStatus, repoContext, currentBranch, defaultBranch] = - await Promise.all([ - fetchGitHubPRStatus(repoPath), - getRepoContext(repoPath), - getCurrentBranch(repoPath), - getDefaultBranch(repoPath), - ]); - - const repoUrl = githubStatus?.repoUrl ?? repoContext?.repoUrl; - const upstreamUrl = - githubStatus?.upstreamUrl ?? repoContext?.upstreamUrl ?? repoUrl; - const isFork = githubStatus?.isFork ?? repoContext?.isFork ?? false; - const repositoryUrl = repoUrl; - const repositoryNameWithOwner = repositoryUrl - ? extractNwoFromUrl(repositoryUrl) - : null; - const upstreamNameWithOwner = upstreamUrl - ? extractNwoFromUrl(upstreamUrl) - : null; - - if ( - !repoUrl || - !upstreamUrl || - !repositoryUrl || - !repositoryNameWithOwner || - !upstreamNameWithOwner - ) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "Could not determine the GitHub repository for this workspace.", - }); - } - - if (!currentBranch) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "Could not determine the current branch for this workspace.", - }); - } - - return { - repoPath, - worktree, - repositoryUrl, - repositoryNameWithOwner, - upstreamUrl, - upstreamNameWithOwner, - isFork, - branchExistsOnRemote: githubStatus?.branchExistsOnRemote ?? false, - currentBranch, - defaultBranch, - }; -} - -async function getGitHubRepositoryOverview(workspaceId: string) { - const { - repoPath, - repositoryNameWithOwner, - repositoryUrl, - upstreamUrl, - upstreamNameWithOwner, - isFork, - branchExistsOnRemote, - currentBranch, - defaultBranch, - } = await resolveRepositoryTargetForWorkspace(workspaceId); - - const [pullRequests, workflows, labels, assignees] = await Promise.all([ - loadGitHubOverviewSegment({ - label: "pullRequests", - workspaceId, - repositoryNameWithOwner, - fallback: [] as Array>, - load: async () => { - const result = await execWithShellEnv( - "gh", - [ - "pr", - "list", - "--repo", - repositoryNameWithOwner, - "--state", - "open", - "--limit", - "8", - "--json", - "number,title,url,state,isDraft,headRefName,updatedAt,author", - ], - { cwd: repoPath }, - ); - return z - .array(ghRepositoryPullRequestSchema) - .parse(JSON.parse(result.stdout) as unknown); - }, - }), - loadGitHubOverviewSegment({ - label: "workflows", - workspaceId, - repositoryNameWithOwner, - fallback: [] as Array>, - load: async () => { - const result = await execWithShellEnv( - "gh", - [ - "api", - `repos/${repositoryNameWithOwner}/actions/workflows?per_page=100`, - ], - { cwd: repoPath }, - ); - return ( - ghRepositoryWorkflowsResponseSchema.parse( - JSON.parse(result.stdout) as unknown, - ).workflows ?? [] - ); - }, - }), - loadGitHubOverviewSegment({ - label: "labels", - workspaceId, - repositoryNameWithOwner, - fallback: [] as Array>, - load: async () => { - const result = await execWithShellEnv( - "gh", - ["api", `repos/${repositoryNameWithOwner}/labels?per_page=100`], - { cwd: repoPath }, - ); - return z - .array(ghRepositoryLabelSchema) - .parse(JSON.parse(result.stdout) as unknown); - }, - }), - loadGitHubOverviewSegment({ - label: "assignees", - workspaceId, - repositoryNameWithOwner, - fallback: [] as Array>, - load: async () => { - const result = await execWithShellEnv( - "gh", - ["api", `repos/${repositoryNameWithOwner}/assignees?per_page=100`], - { cwd: repoPath }, - ); - return z - .array(ghRepositoryAssigneeSchema) - .parse(JSON.parse(result.stdout) as unknown); - }, - }), - ]); - - return { - repositoryNameWithOwner, - repositoryUrl, - upstreamUrl, - upstreamNameWithOwner, - isFork, - branchExistsOnRemote, - currentBranch, - defaultBranch, - issueAssignees: assignees.map((assignee) => ({ - login: assignee.login, - avatarUrl: assignee.avatar_url ?? null, - })), - issueLabels: labels.map((label) => ({ - name: label.name, - color: label.color ?? "", - description: label.description ?? "", - })), - pullsUrl: `${repositoryUrl}/pulls`, - issuesUrl: `${repositoryUrl}/issues`, - actionsUrl: `${repositoryUrl}/actions`, - newIssueUrl: `${repositoryUrl}/issues/new`, - pullRequests: pullRequests.map((pullRequest) => ({ - number: pullRequest.number, - title: pullRequest.title, - url: pullRequest.url, - state: pullRequest.isDraft ? "draft" : pullRequest.state.toLowerCase(), - headRefName: pullRequest.headRefName ?? "", - updatedAt: pullRequest.updatedAt ?? null, - authorLogin: pullRequest.author?.login ?? null, - })), - workflows: workflows - .filter((workflow) => workflow.state !== "disabled_manually") - .map((workflow) => { - const dispatchInfo = parseWorkflowDispatchInfo({ - repoPath, - workflowPath: workflow.path, - }); - return { - id: workflow.id, - name: workflow.name, - path: workflow.path ?? "", - state: workflow.state ?? "unknown", - supportsDispatch: dispatchInfo.supportsDispatch, - inputs: dispatchInfo.inputs, - }; - }) - .filter((workflow) => workflow.supportsDispatch), - }; -} - -async function createGitHubIssueForWorkspace({ - workspaceId, - title, - body, - assignees, - labels, -}: { - workspaceId: string; - title: string; - body?: string; - assignees?: string[]; - labels?: string[]; -}) { - const { repoPath, repositoryNameWithOwner } = - await resolveRepositoryTargetForWorkspace(workspaceId); - const args = [ - "issue", - "create", - "--repo", - repositoryNameWithOwner, - "--title", - title.trim(), - "--body", - body?.trim() || "", - ]; - const normalizedAssignees = normalizeIdentityList(assignees ?? []); - const normalizedLabels = normalizeIdentityList(labels ?? []); - if (normalizedAssignees.length > 0) { - args.push("--assignee", normalizedAssignees.join(",")); - } - if (normalizedLabels.length > 0) { - args.push("--label", normalizedLabels.join(",")); - } - const { stdout } = await execWithShellEnv("gh", args, { cwd: repoPath }); - - return { - url: stdout.trim(), - }; -} - -async function uploadIssueAssetForWorkspace({ - workspaceId, - filename, - contentBase64, - mimeType, -}: { - workspaceId: string; - filename: string; - contentBase64: string; - mimeType?: string; -}) { - const { repoPath, repositoryNameWithOwner, defaultBranch } = - await resolveRepositoryTargetForWorkspace(workspaceId); - const assetBranch = "superset-issue-assets"; - await ensureGitHubBranchExists({ - repoPath, - repositoryNameWithOwner, - branchName: assetBranch, - baseBranch: defaultBranch, - }); - - const now = new Date(); - const extension = getIssueAssetExtension({ filename, mimeType }); - const basename = - sanitizeIssueAssetBasename(filename.replace(/\.[^.]+$/, "")) || - "pasted-image"; - const timestamp = now.toISOString().replace(/[:.]/g, "-"); - const assetPath = [ - ".superset", - "issue-assets", - String(now.getUTCFullYear()), - String(now.getUTCMonth() + 1).padStart(2, "0"), - `${timestamp}-${basename}.${extension}`, - ].join("/"); - - await execWithShellEnv( - "gh", - [ - "api", - "--method", - "PUT", - `repos/${repositoryNameWithOwner}/contents/${assetPath}`, - "-f", - `message=Add issue asset ${assetPath}`, - "-f", - `content=${contentBase64}`, - "-f", - `branch=${assetBranch}`, - ], - { cwd: repoPath }, - ); - - const assetUrl = `https://github.com/${repositoryNameWithOwner}/raw/${assetBranch}/${assetPath}`; - - return { - name: `${basename}.${extension}`, - url: assetUrl, - markdown: `![${basename}](${assetUrl})`, - }; -} - -async function dispatchGitHubWorkflowForWorkspace({ - workspaceId, - workflowId, - ref, - inputs, -}: { - workspaceId: string; - workflowId: number; - ref?: string; - inputs?: Record; -}) { - const { repoPath, repositoryNameWithOwner, currentBranch, defaultBranch } = - await resolveRepositoryTargetForWorkspace(workspaceId); - const requestedRef = ref?.trim() || currentBranch || defaultBranch; - let targetRef = requestedRef; - if (requestedRef === currentBranch) { - const branchCheck = await branchExistsOnRemote( - repoPath, - currentBranch, - "origin", - ); - if (branchCheck.status !== "exists") { - targetRef = defaultBranch; - } - } - - const args = [ - "api", - "--method", - "POST", - `repos/${repositoryNameWithOwner}/actions/workflows/${workflowId}/dispatches`, - "-f", - `ref=${targetRef}`, - ]; - - if (inputs) { - for (const [key, value] of Object.entries(inputs)) { - args.push("-f", `inputs[${key}]=${value}`); - } - } - - await execWithShellEnv("gh", args, { cwd: repoPath }); - - return { - success: true as const, - ref: targetRef, - dispatchedAt: new Date().toISOString(), - }; -} - -async function getGitHubWorkflowRunsForWorkspace({ - workspaceId, - workflowId, -}: { - workspaceId: string; - workflowId: number; -}) { - const { repoPath, repositoryNameWithOwner } = - await resolveRepositoryTargetForWorkspace(workspaceId); - const { stdout } = await execWithShellEnv( - "gh", - [ - "api", - `repos/${repositoryNameWithOwner}/actions/workflows/${workflowId}/runs?per_page=10&event=workflow_dispatch`, - ], - { cwd: repoPath }, - ); - - const rawRuns = JSON.parse(stdout) as unknown; - const runs = - ghRepositoryWorkflowRunsResponseSchema.parse(rawRuns).workflow_runs ?? []; - - return runs.map((run) => ({ - id: run.id, - name: run.name ?? "", - displayTitle: run.display_title ?? "", - url: run.html_url ?? "", - status: run.status ?? "unknown", - conclusion: run.conclusion ?? null, - event: run.event ?? null, - createdAt: run.created_at ?? null, - updatedAt: run.updated_at ?? null, - runStartedAt: run.run_started_at ?? null, - headBranch: run.head_branch ?? null, - headSha: run.head_sha ?? null, - runNumber: run.run_number ?? null, - workflowId: run.workflow_id ?? workflowId, - })); -} - -async function getWorkflowRunJobsForWorkspace({ - workspaceId, - runId, -}: { - workspaceId: string; - runId: number; -}) { - const { repoPath, repositoryNameWithOwner } = - await resolveRepositoryTargetForWorkspace(workspaceId); - const { stdout } = await execWithShellEnv( - "gh", - [ - "api", - `repos/${repositoryNameWithOwner}/actions/runs/${runId}/jobs?per_page=100`, - ], - { cwd: repoPath }, - ); - - const raw: unknown = JSON.parse(stdout); - const parsed = z - .object({ - jobs: z - .array( - z.object({ - id: z.number(), - name: z.string(), - status: z.string(), - conclusion: z.string().nullable(), - html_url: z.string().nullable().optional(), - }), - ) - .optional(), - }) - .parse(raw); - - return (parsed.jobs ?? []).map((job) => ({ - detailsUrl: job.html_url ?? "", - name: job.name, - status: mapJobStatus(job.status, job.conclusion), - })); -} - -function mapJobStatus( - status: string, - conclusion: string | null, -): "success" | "failure" | "pending" | "skipped" | "cancelled" { - if (status !== "completed") { - return "pending"; - } - switch (conclusion) { - case "success": - return "success"; - case "failure": - case "timed_out": - return "failure"; - case "cancelled": - return "cancelled"; - case "skipped": - return "skipped"; - default: - return "pending"; - } -} - -async function rerunPullRequestChecksForWorkspace({ - workspaceId, - mode, -}: { - workspaceId: string; - mode: "all" | "failed"; -}) { - const { repoPath, worktree, pullRequest } = - await getFreshPullRequestForWorkspace(workspaceId); - const checksToRerun = pullRequest.checks.filter((check) => { - if (!isGitHubActionsUrl(check.url)) { - return false; - } - - if (mode === "failed") { - return check.status === "failure"; - } - - return true; - }); - - if (checksToRerun.length === 0) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: - mode === "failed" - ? "No failed GitHub Actions jobs found for this pull request." - : "No GitHub Actions jobs found for this pull request.", - }); - } - - const runTargets = new Map(); - for (const check of checksToRerun) { - const runId = parseRunIdFromActionsUrl(check.url); - const repositoryNameWithOwner = check.url - ? extractNwoFromUrl(check.url) - : null; - if (!runId || !repositoryNameWithOwner) { - continue; - } - - runTargets.set( - `${repositoryNameWithOwner}:${runId}`, - `${repositoryNameWithOwner}:${runId}`, - ); - } - - if (runTargets.size === 0) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "No rerunnable GitHub Actions runs were found.", - }); - } - - for (const target of runTargets.values()) { - const [repositoryNameWithOwner, runId] = target.split(":"); - if (!repositoryNameWithOwner || !runId) { - continue; - } - - await execWithShellEnv( - "gh", - [ - "api", - "--method", - "POST", - `repos/${repositoryNameWithOwner}/actions/runs/${runId}/${mode === "failed" ? "rerun-failed-jobs" : "rerun"}`, - ], - { cwd: repoPath }, - ); - } - - clearGitHubCachesForWorktree(repoPath); - if (worktree) { - localDb - .update(worktrees) - .set({ githubStatus: null }) - .where(eq(worktrees.id, worktree.id)) - .run(); - } - - return { - success: true as const, - rerunCount: runTargets.size, - }; -} - -function resolvePullRequestTarget({ - workspaceId, - pullRequestNumber, - pullRequestUrl, -}: { - workspaceId: string; - pullRequestNumber?: number; - pullRequestUrl?: string; -}): { - repoPath: string; - worktree: NonNullable> | null; - repoNameWithOwner: string; - pullRequestNumber: number; -} { - const { repoPath, worktree } = resolveRepoPathForWorkspace(workspaceId); - const repoNameWithOwner = pullRequestUrl - ? extractNwoFromUrl(pullRequestUrl) - : null; - - if (!repoNameWithOwner || !pullRequestNumber) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "Could not determine the pull request target.", - }); - } - - return { - repoPath, - worktree, - repoNameWithOwner, - pullRequestNumber, - }; -} - -function resolvePullRequestRepoTarget({ - workspaceId, - pullRequestUrl, -}: { - workspaceId: string; - pullRequestUrl?: string; -}): { - repoPath: string; - worktree: NonNullable> | null; - repoNameWithOwner: string; -} { - const { repoPath, worktree } = resolveRepoPathForWorkspace(workspaceId); - const repoNameWithOwner = pullRequestUrl - ? extractNwoFromUrl(pullRequestUrl) - : null; - - if (!repoNameWithOwner) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "Could not determine the pull request repository.", - }); - } - - return { - repoPath, - worktree, - repoNameWithOwner, - }; -} - -function normalizeIdentityList(values: string[]): string[] { - return Array.from( - new Set(values.map((value) => value.trim()).filter(Boolean)), - ); -} - -async function updatePullRequestMembers({ - workspaceId, - kind, - add, - remove, - pullRequestNumber, - pullRequestUrl, -}: { - workspaceId: string; - kind: "reviewer" | "assignee"; - add: string[]; - remove: string[]; - pullRequestNumber?: number; - pullRequestUrl?: string; -}): Promise<{ success: true }> { - const normalizedAdd = normalizeIdentityList(add); - const normalizedRemove = normalizeIdentityList(remove); - - if (normalizedAdd.length === 0 && normalizedRemove.length === 0) { - return { success: true }; - } - - const { - repoPath, - worktree, - repoNameWithOwner, - pullRequestNumber: resolvedPr, - } = resolvePullRequestTarget({ - workspaceId, - pullRequestNumber, - pullRequestUrl, - }); - - const args = ["pr", "edit", String(resolvedPr), "--repo", repoNameWithOwner]; - - if (normalizedAdd.length > 0) { - args.push( - kind === "reviewer" ? "--add-reviewer" : "--add-assignee", - normalizedAdd.join(","), - ); - } - - if (normalizedRemove.length > 0) { - args.push( - kind === "reviewer" ? "--remove-reviewer" : "--remove-assignee", - normalizedRemove.join(","), - ); - } - - await execWithShellEnv("gh", args, { cwd: repoPath }); - clearGitHubCachesForWorktree(repoPath); - - if (worktree) { - localDb - .update(worktrees) - .set({ githubStatus: null }) - .where(eq(worktrees.id, worktree.id)) - .run(); - } - - return { success: true }; -} - -async function getPullRequestIdentityCandidates({ - workspaceId, - kind, - pullRequestUrl, -}: { - workspaceId: string; - kind: "reviewer" | "assignee"; - pullRequestUrl?: string; -}): Promise> { - const { repoPath, repoNameWithOwner } = resolvePullRequestRepoTarget({ - workspaceId, - pullRequestUrl, - }); - - const [owner, name] = repoNameWithOwner.split("/"); - if (!owner || !name) { - return []; - } - - const fieldName = - kind === "assignee" ? "assignableUsers" : "mentionableUsers"; - const query = `query PullRequestIdentityCandidates($owner: String!, $name: String!, $after: String) { - repository(owner: $owner, name: $name) { - users: ${fieldName}(first: 100, after: $after) { - nodes { - login - avatarUrl - } - pageInfo { - hasNextPage - endCursor - } - } - } -}`; - - const usersByLogin = new Map(); - let afterCursor: string | null = null; - - while (true) { - const args = [ - "api", - "graphql", - "-f", - `query=${query}`, - "-F", - `owner=${owner}`, - "-F", - `name=${name}`, - ]; - if (afterCursor) { - args.push("-F", `after=${afterCursor}`); - } - - const { stdout } = await execWithShellEnv("gh", args, { cwd: repoPath }); - const raw = JSON.parse(stdout) as unknown; - const parsed = GHIdentityCandidatesResponseSchema.safeParse(raw); - if (!parsed.success) { - console.warn( - "[GitHub] Failed to parse pull request identity candidates:", - parsed.error.message, - ); - break; - } - - const users = parsed.data.data.repository?.users; - if (!users) { - break; - } - - for (const user of users.nodes ?? []) { - if (user?.login) { - usersByLogin.set(user.login, user.avatarUrl ?? null); - } - } - - if (!users.pageInfo.hasNextPage || !users.pageInfo.endCursor) { - break; - } - - afterCursor = users.pageInfo.endCursor; - } - - return [...usersByLogin.entries()].map(([login, avatarUrl]) => ({ - login, - avatarUrl, - })); -} - -// Initialize the SyncService with fetch dependencies (idempotent) -githubSyncService.initialize({ - fetchPRStatus: fetchGitHubPRStatus, - fetchPRComments: ({ worktreePath, pullRequest }) => - fetchGitHubPRComments({ worktreePath, pullRequest }), -}); - export const createGitStatusProcedures = () => { return router({ refreshGitStatus: publicProcedure @@ -1291,12 +102,10 @@ export const createGitStatusProcedures = () => { throw new Error(`Workspace ${input.workspaceId} not found`); } - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - if (!worktree) { + const repoPath = getWorkspacePath(workspace); + if (!repoPath) { throw new Error( - `Worktree for workspace ${input.workspaceId} not found`, + `Could not resolve path for workspace ${input.workspaceId}`, ); } @@ -1324,23 +133,25 @@ export const createGitStatusProcedures = () => { await fetchDefaultBranch(project.mainRepoPath, defaultBranch); const { ahead, behind } = await getAheadBehindCount({ - repoPath: worktree.path, + repoPath, defaultBranch, }); const gitStatus = { - branch: worktree.branch, + branch: workspace.branch, needsRebase: behind > 0, ahead, behind, lastRefreshed: Date.now(), }; - localDb - .update(worktrees) - .set({ gitStatus }) - .where(eq(worktrees.id, worktree.id)) - .run(); + if (workspace.worktreeId) { + localDb + .update(worktrees) + .set({ gitStatus }) + .where(eq(worktrees.id, workspace.worktreeId)) + .run(); + } return { gitStatus, defaultBranch }; }), @@ -1365,74 +176,42 @@ export const createGitStatusProcedures = () => { }), getGitHubStatus: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - forceFresh: z.boolean().optional(), - includePreview: z.boolean().optional(), - }), - ) + .input(z.object({ workspaceId: z.string() })) .query(async ({ input }) => { const workspace = getWorkspace(input.workspaceId); if (!workspace) { return null; } - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - // For "branch" type workspaces without a worktree record, - // fall back to the project's mainRepoPath - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } + const repoPath = getWorkspacePath(workspace); if (!repoPath) { return null; } - if (input.forceFresh) { - clearGitHubCachesForWorktree(repoPath); - } - - // Register workspace with SyncService for proactive cache warming - if (!githubSyncService.isRegistered(repoPath)) { - githubSyncService.registerWorkspace(repoPath); + const branchOverride = + workspace.type === "branch" ? workspace.branch : null; + + const freshStatus = await fetchGitHubPRStatus(repoPath, branchOverride); + + if (freshStatus && workspace.worktreeId) { + const worktree = getWorktree(workspace.worktreeId); + if ( + worktree && + hasMeaningfulGitHubStatusChange({ + current: worktree.githubStatus, + next: freshStatus, + }) + ) { + localDb + .update(worktrees) + .set({ githubStatus: freshStatus }) + .where(eq(worktrees.id, workspace.worktreeId)) + .run(); + } } - const freshStatus = await fetchGitHubPRStatus(repoPath); - - if ( - worktree && - hasMeaningfulGitHubStatusChange({ - current: worktree.githubStatus, - next: freshStatus, - }) - ) { - localDb - .update(worktrees) - .set({ githubStatus: freshStatus }) - .where(eq(worktrees.id, worktree.id)) - .run(); - } - - if (!input.includePreview || !freshStatus) { - return freshStatus; - } - - const previewUrl = await fetchGitHubPreviewUrl({ - worktreePath: repoPath, - githubStatus: freshStatus, - forceFresh: input.forceFresh, - }); - - return { - ...freshStatus, - previewUrl: previewUrl ?? undefined, - }; - }), + return freshStatus; + }), getGitHubPRComments: publicProcedure .input(gitHubPRCommentsInputSchema) @@ -1442,23 +221,14 @@ export const createGitStatusProcedures = () => { return []; } - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } + const repoPath = getWorkspacePath(workspace); if (!repoPath) { return []; } - if (input.forceFresh) { - clearGitHubCachesForWorktree(repoPath); - } - + const worktree = workspace.worktreeId + ? getWorktree(workspace.worktreeId) + : null; const cachedGitHubStatus = worktree?.githubStatus ?? null; return fetchGitHubPRComments({ @@ -1467,316 +237,38 @@ export const createGitStatusProcedures = () => { input, githubStatus: cachedGitHubStatus, }), + branchName: workspace.type === "branch" ? workspace.branch : null, }); }), - getPullRequestIdentityCandidates: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - kind: z.enum(["reviewer", "assignee"]), - pullRequestUrl: z.string().optional(), - }), - ) - .query(async ({ input }) => { - return getPullRequestIdentityCandidates(input); - }), - - getGitHubRepositoryOverview: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - }), - ) - .query(async ({ input }) => { - return getGitHubRepositoryOverview(input.workspaceId); - }), - - createGitHubIssue: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - title: z.string().trim().min(1), - body: z.string().optional(), - assignees: z.array(z.string()).optional(), - labels: z.array(z.string()).optional(), - }), - ) - .mutation(async ({ input }) => { - return createGitHubIssueForWorkspace(input); - }), - - uploadGitHubIssueAsset: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - filename: z.string().trim().min(1), - contentBase64: z.string().trim().min(1), - mimeType: z.string().optional(), - }), - ) - .mutation(async ({ input }) => { - return uploadIssueAssetForWorkspace(input); - }), - - dispatchGitHubWorkflow: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - workflowId: z.number().int().positive(), - ref: z.string().optional(), - inputs: z.record(z.string(), z.string()).optional(), - }), - ) - .mutation(async ({ input }) => { - return dispatchGitHubWorkflowForWorkspace(input); - }), - - getGitHubWorkflowRuns: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - workflowId: z.number().int().positive(), - }), - ) - .query(async ({ input }) => { - return getGitHubWorkflowRunsForWorkspace(input); - }), - - getWorkflowRunJobs: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - runId: z.number().int().positive(), - }), - ) - .query(async ({ input }) => { - return getWorkflowRunJobsForWorkspace(input); - }), - - rerunPullRequestChecks: publicProcedure + resolveReviewThread: publicProcedure .input( z.object({ workspaceId: z.string(), - mode: z.enum(["all", "failed"]), + threadId: z.string(), + resolve: z.boolean(), }), ) .mutation(async ({ input }) => { - return rerunPullRequestChecksForWorkspace(input); - }), - - setPullRequestDraftState: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - isDraft: z.boolean(), - }), - ) - .mutation(async ({ input }) => { - const { repoPath, worktree, pullRequest } = - await getFreshPullRequestForWorkspace(input.workspaceId); - - const isCurrentlyDraft = pullRequest.state === "draft"; - if (pullRequest.state !== "draft" && pullRequest.state !== "open") { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: - "Only open or draft pull requests can be updated from Review.", - }); - } - - if (input.isDraft === isCurrentlyDraft) { - return { success: true }; - } - - const repoNameWithOwner = extractNwoFromUrl(pullRequest.url); - if (!repoNameWithOwner) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "Could not determine the pull request repository.", - }); - } - - const args = [ - "pr", - "ready", - String(pullRequest.number), - "--repo", - repoNameWithOwner, - ]; - if (input.isDraft) { - args.push("--undo"); - } - - await execWithShellEnv("gh", args, { cwd: repoPath }); - clearGitHubCachesForWorktree(repoPath); - - if (worktree) { - localDb - .update(worktrees) - .set({ githubStatus: null }) - .where(eq(worktrees.id, worktree.id)) - .run(); - } - - return { success: true }; - }), - - setPullRequestThreadResolution: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - threadId: z.string().min(1), - isResolved: z.boolean(), - }), - ) - .mutation(async ({ input }) => { - const { repoPath, worktree } = resolveRepoPathForWorkspace( - input.workspaceId, - ); - const mutationName = input.isResolved - ? "resolveReviewThread" - : "unresolveReviewThread"; - const mutationQuery = `mutation ${mutationName}($threadId: ID!) { - ${mutationName}(input: { threadId: $threadId }) { - thread { - id - isResolved - } - } -}`; - - await execWithShellEnv( - "gh", - [ - "api", - "graphql", - "-f", - `query=${mutationQuery}`, - "-F", - `threadId=${input.threadId}`, - ], - { cwd: repoPath }, - ); - - clearGitHubCachesForWorktree(repoPath); - if (worktree) { - localDb - .update(worktrees) - .set({ githubStatus: null }) - .where(eq(worktrees.id, worktree.id)) - .run(); - } - - return { success: true }; - }), - - replyToPullRequestComment: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - body: z.string().trim().min(1), - threadId: z.string().min(1).optional(), - pullRequestNumber: z.number().int().positive().optional(), - pullRequestUrl: z.string().optional(), - }), - ) - .mutation(async ({ input }) => { - const { repoPath, worktree } = resolveRepoPathForWorkspace( - input.workspaceId, - ); - - if (input.threadId) { - await replyToReviewThread({ - worktreePath: repoPath, - threadId: input.threadId, - body: input.body, - }); - } else { - const githubStatus = await fetchGitHubPRStatus(repoPath); - const pullRequestNumber = - input.pullRequestNumber ?? githubStatus?.pr?.number; - if (!pullRequestNumber) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: "No pull request found for this workspace.", - }); - } - - const prUrl = input.pullRequestUrl ?? githubStatus?.pr?.url; - const repoNameWithOwner = prUrl - ? extractNwoFromUrl(prUrl) - : githubStatus?.repoUrl - ? extractNwoFromUrl(githubStatus.repoUrl) - : null; - if (!repoNameWithOwner) { - throw new TRPCError({ - code: "PRECONDITION_FAILED", - message: - "Could not determine the repository for this pull request.", - }); - } - - await addPullRequestConversationComment({ - worktreePath: repoPath, - repoNameWithOwner, - pullRequestNumber, - body: input.body, - }); + const workspace = getWorkspace(input.workspaceId); + if (!workspace) { + throw new Error(`Workspace ${input.workspaceId} not found`); } - clearGitHubCachesForWorktree(repoPath); - if (worktree) { - localDb - .update(worktrees) - .set({ githubStatus: null }) - .where(eq(worktrees.id, worktree.id)) - .run(); + const repoPath = getWorkspacePath(workspace); + if (!repoPath) { + throw new Error( + `Could not resolve path for workspace ${input.workspaceId}`, + ); } - return { success: true }; - }), - - updatePullRequestReviewers: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - add: z.array(z.string()).optional().default([]), - remove: z.array(z.string()).optional().default([]), - pullRequestNumber: z.number().int().positive().optional(), - pullRequestUrl: z.string().optional(), - }), - ) - .mutation(async ({ input }) => { - return updatePullRequestMembers({ - workspaceId: input.workspaceId, - kind: "reviewer", - add: input.add, - remove: input.remove, - pullRequestNumber: input.pullRequestNumber, - pullRequestUrl: input.pullRequestUrl, + await resolveReviewThread({ + worktreePath: repoPath, + threadId: input.threadId, + resolve: input.resolve, }); - }), - updatePullRequestAssignees: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - add: z.array(z.string()).optional().default([]), - remove: z.array(z.string()).optional().default([]), - pullRequestNumber: z.number().int().positive().optional(), - pullRequestUrl: z.string().optional(), - }), - ) - .mutation(async ({ input }) => { - return updatePullRequestMembers({ - workspaceId: input.workspaceId, - kind: "assignee", - add: input.add, - remove: input.remove, - pullRequestNumber: input.pullRequestNumber, - pullRequestUrl: input.pullRequestUrl, - }); + clearGitHubCachesForWorktree(repoPath); }), getWorktreeInfo: publicProcedure @@ -1787,6 +279,16 @@ export const createGitStatusProcedures = () => { return null; } + if (workspace.type === "branch") { + return { + worktreeName: workspace.name, + branchName: workspace.branch, + createdAt: workspace.createdAt, + gitStatus: null, + githubStatus: null, + }; + } + const worktree = workspace.worktreeId ? getWorktree(workspace.worktreeId) : null; @@ -1867,207 +369,5 @@ export const createGitStatusProcedures = () => { branch: wt.branch!, })); }), - - getMissingWorktrees: publicProcedure - .input(z.object({ projectId: z.string() })) - .query(({ input }) => { - const projectWorktrees = localDb - .select({ - id: worktrees.id, - path: worktrees.path, - branch: worktrees.branch, - }) - .from(worktrees) - .where(eq(worktrees.projectId, input.projectId)) - .all(); - - return projectWorktrees - .filter((wt) => !existsSync(wt.path)) - .map((wt) => ({ - worktreeId: wt.id, - path: wt.path, - branch: wt.branch, - })); - }), - - cleanupMissingWorktrees: publicProcedure - .input(z.object({ projectId: z.string() })) - .mutation(async ({ input }) => { - const projectWorktrees = localDb - .select() - .from(worktrees) - .where(eq(worktrees.projectId, input.projectId)) - .all(); - - const missing = projectWorktrees.filter((wt) => !existsSync(wt.path)); - - let removed = 0; - for (const wt of missing) { - const relatedWorkspaces = localDb - .select() - .from(workspaces) - .where(eq(workspaces.worktreeId, wt.id)) - .all(); - - // Tear down runtime state for each workspace before deleting DB rows. - // The worktree files are already gone (hence "missing"), so we skip - // disk teardown scripts but still kill terminals, unregister GitHub - // sync, and update active-workspace/project visibility so the app - // doesn't retain orphan state. - for (const ws of relatedWorkspaces) { - markWorkspaceAsDeleting(ws.id); - updateActiveWorkspaceIfRemoved(ws.id); - - try { - await getWorkspaceRuntimeRegistry() - .getForWorkspaceId(ws.id) - .terminal.killByWorkspaceId(ws.id); - } catch (err) { - console.warn( - `[cleanupMissingWorktrees] terminal kill failed for workspace ${ws.id}:`, - err, - ); - } - - githubSyncService.unregisterWorkspace(wt.path); - workspaceInitManager.clearJob(ws.id); - - deleteWorkspace(ws.id); - clearWorkspaceDeletingStatus(ws.id); - } - - deleteWorktreeRecord(wt.id); - hideProjectIfNoWorkspaces(input.projectId); - removed++; - } - - return { removed }; - }), - - getCheckJobSteps: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - detailsUrl: z.string(), - }), - ) - .query(async ({ input }) => { - const workspace = getWorkspace(input.workspaceId); - if (!workspace) { - return []; - } - - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } - if (!repoPath) { - return []; - } - - return fetchCheckJobSteps(repoPath, input.detailsUrl); - }), - - getJobLogs: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - detailsUrl: z.string(), - }), - ) - .query(async ({ input }) => { - const workspace = getWorkspace(input.workspaceId); - if (!workspace) { - return { - jobStatus: "queued" as const, - jobConclusion: null, - steps: [], - }; - } - - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } - if (!repoPath) { - return { - jobStatus: "queued" as const, - jobConclusion: null, - steps: [], - }; - } - - return fetchStructuredJobLogs(repoPath, input.detailsUrl); - }), - - getJobStatuses: publicProcedure - .input( - z.object({ - workspaceId: z.string(), - detailsUrls: z.array(z.string()), - }), - ) - .query(async ({ input }) => { - const workspace = getWorkspace(input.workspaceId); - if (!workspace) { - return []; - } - - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } - if (!repoPath) { - return []; - } - - return fetchJobStatuses(repoPath, input.detailsUrls); - }), - - /** - * Notify the SyncService which workspace is currently active. - * Deactivates all other workspaces to stop their polling timers. - * Pass empty workspaceId to deactivate all (e.g., dashboard view). - */ - setActiveSyncWorkspace: publicProcedure - .input(z.object({ workspaceId: z.string() })) - .mutation(({ input }) => { - if (!input.workspaceId) { - githubSyncService.deactivateAll(); - return { success: true }; - } - - const workspace = getWorkspace(input.workspaceId); - if (!workspace) return { success: false }; - - const worktree = workspace.worktreeId - ? getWorktree(workspace.worktreeId) - : null; - - let repoPath: string | null = worktree?.path ?? null; - if (!repoPath && workspace.type === "branch") { - const project = getProject(workspace.projectId); - repoPath = project?.mainRepoPath ?? null; - } - if (!repoPath) return { success: false }; - - githubSyncService.setActiveWorkspace(repoPath); - return { success: true }; - }), }); }; diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts index 7ad12334bab..65c1c7e5ca6 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-branch-name.ts @@ -3,7 +3,7 @@ import { getSmallModel } from "@superset/chat/server/shared"; import { sanitizeBranchNameWithMaxLength } from "shared/utils/branch"; const BRANCH_NAME_INSTRUCTIONS = - "Generate a concise git branch name (2-4 words, kebab-case, descriptive). Return ONLY the branch name, nothing else."; + "Generate a concise git branch name (2-4 words, kebab-case, descriptive, 20 characters or less). Return ONLY the branch name, nothing else."; const MAX_CONFLICT_RESOLUTION_ATTEMPTS = 1000; const INITIAL_CONFLICT_SUFFIX = 2; @@ -58,7 +58,7 @@ export async function generateBranchNameFromPrompt( existingBranches: string[], branchPrefix?: string, ): Promise { - const model = getSmallModel(); + const model = await getSmallModel(); if (!model) return null; let generated: string | null; diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts index 5fa3df6dff0..7926fa98075 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.test.ts @@ -1,7 +1,7 @@ import { afterAll, beforeEach, describe, expect, it, mock } from "bun:test"; const getSmallModelMock = mock( - (() => null) as (...args: unknown[]) => unknown | null, + (async () => null) as (...args: unknown[]) => Promise, ); const generateTitleFromMessageMock = mock( (async () => null) as (...args: unknown[]) => Promise, @@ -79,7 +79,7 @@ const { describe("generateWorkspaceNameFromPrompt", () => { beforeEach(() => { getSmallModelMock.mockClear(); - getSmallModelMock.mockReturnValue(null); + getSmallModelMock.mockResolvedValue(null); generateTitleFromMessageMock.mockClear(); generateTitleFromMessageMock.mockResolvedValue(null); selectGetMock.mockReset(); @@ -102,7 +102,7 @@ describe("generateWorkspaceNameFromPrompt", () => { }); it("returns the model-generated title when a model is available", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); + getSmallModelMock.mockResolvedValueOnce({ id: "test-model" }); generateTitleFromMessageMock.mockResolvedValueOnce("Checking In"); await expect( @@ -116,13 +116,14 @@ describe("generateWorkspaceNameFromPrompt", () => { agentModel: { id: "test-model" }, agentId: "workspace-namer", agentName: "Workspace Namer", - instructions: "You generate concise workspace titles.", + instructions: + "You generate concise workspace titles. 20 characters or less. Return ONLY the title, nothing else.", tracingContext: { surface: "workspace-auto-name" }, }); }); it("preserves empty-string model results instead of forcing fallback", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); + getSmallModelMock.mockResolvedValueOnce({ id: "test-model" }); generateTitleFromMessageMock.mockResolvedValueOnce(""); await expect( @@ -134,7 +135,7 @@ describe("generateWorkspaceNameFromPrompt", () => { }); it("falls back when generation throws", async () => { - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); + getSmallModelMock.mockResolvedValueOnce({ id: "test-model" }); generateTitleFromMessageMock.mockRejectedValueOnce(new Error("boom")); await expect( @@ -155,7 +156,7 @@ afterAll(() => { describe("attemptWorkspaceAutoRenameFromPrompt", () => { beforeEach(() => { getSmallModelMock.mockClear(); - getSmallModelMock.mockReturnValue(null); + getSmallModelMock.mockResolvedValue(null); generateTitleFromMessageMock.mockClear(); generateTitleFromMessageMock.mockResolvedValue(null); selectGetMock.mockReset(); @@ -196,7 +197,7 @@ describe("attemptWorkspaceAutoRenameFromPrompt", () => { isUnnamed: true, deletingAt: null, }); - getSmallModelMock.mockReturnValueOnce({ id: "test-model" }); + getSmallModelMock.mockResolvedValueOnce({ id: "test-model" }); generateTitleFromMessageMock.mockResolvedValueOnce(""); await expect( diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts index 1bb06606be5..0df5e43de28 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/ai-name.ts @@ -34,7 +34,7 @@ export async function generateWorkspaceNameFromPrompt(prompt: string): Promise<{ usedPromptFallback: boolean; warning?: string; }> { - const model = getSmallModel(); + const model = await getSmallModel(); if (model) { try { const generated = await generateTitleFromMessage({ @@ -42,7 +42,8 @@ export async function generateWorkspaceNameFromPrompt(prompt: string): Promise<{ agentModel: model, agentId: "workspace-namer", agentName: "Workspace Namer", - instructions: "You generate concise workspace titles.", + instructions: + "You generate concise workspace titles. 20 characters or less. Return ONLY the title, nothing else.", tracingContext: { surface: "workspace-auto-name" }, }); if (generated !== null && generated !== undefined) { diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts index 7f3058e6705..969f62be9ee 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts @@ -1807,18 +1807,45 @@ export async function createWorktreeFromPr({ }); } - await execWithShellEnv( - "gh", - [ - "pr", - "checkout", - String(prInfo.number), - "--branch", - localBranchName, - "--force", - ], - { cwd: worktreePath, timeout: 120_000 }, - ); + try { + await execWithShellEnv( + "gh", + [ + "pr", + "checkout", + String(prInfo.number), + "--branch", + localBranchName, + "--force", + ], + { cwd: worktreePath, timeout: 120_000 }, + ); + } catch (ghError) { + const ghMsg = ghError instanceof Error ? ghError.message : String(ghError); + // `gh pr checkout` can fail with "is not a branch" when the branch name + // contains '/' (e.g. "user/feature-branch"). Git has trouble resolving + // "origin/user/feature-branch" as a tracking ref inside a worktree. + // gh already fetched the remote successfully, so FETCH_HEAD points to + // the right commit โ€” fall back to creating the branch without tracking. + if (!ghMsg.includes("is not a branch")) { + throw ghError; + } + console.log( + `[git] gh pr checkout failed with tracking error for PR #${prInfo.number}, falling back to FETCH_HEAD checkout`, + ); + await execGitWithShellPath( + [ + "-C", + worktreePath, + "checkout", + "-B", + localBranchName, + "--no-track", + "FETCH_HEAD", + ], + { timeout: 30_000 }, + ); + } // Enable autoSetupRemote so `git push` just works without -u flag. await execGitWithShellPath( diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/cache.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/cache.ts index 04edaed046f..f1712477e25 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/cache.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/cache.ts @@ -4,22 +4,15 @@ import { type CacheState, createCachedResource, } from "./cached-resource"; -import { recordGitHubCacheMetric } from "./github-metrics"; import type { RepoContext } from "./types"; -const GITHUB_STATUS_CACHE_TTL_MS = 30_000; -const GITHUB_PR_COMMENTS_CACHE_TTL_MS = 60_000; -const GITHUB_PREVIEW_URL_CACHE_TTL_MS = 10 * 60 * 1000; +const GITHUB_STATUS_CACHE_TTL_MS = 10_000; +const GITHUB_PR_COMMENTS_CACHE_TTL_MS = 30_000; const GITHUB_REPO_CONTEXT_CACHE_TTL_MS = 300_000; -const GITHUB_COMMIT_AUTHOR_CACHE_TTL_MS = 300_000; -const GITHUB_NO_PR_MATCH_CACHE_TTL_MS = 120_000; const MAX_GITHUB_STATUS_CACHE_ENTRIES = 256; const MAX_GITHUB_PR_COMMENTS_CACHE_ENTRIES = 512; -const MAX_GITHUB_PREVIEW_URL_CACHE_ENTRIES = 512; const MAX_GITHUB_REPO_CONTEXT_CACHE_ENTRIES = 256; -const MAX_GITHUB_COMMIT_AUTHOR_CACHE_ENTRIES = 2048; -const MAX_GITHUB_NO_PR_MATCH_CACHE_ENTRIES = 512; const githubStatusResource = createCachedResource({ ttlMs: GITHUB_STATUS_CACHE_TTL_MS, @@ -31,42 +24,15 @@ const pullRequestCommentsResource = createCachedResource({ maxEntries: MAX_GITHUB_PR_COMMENTS_CACHE_ENTRIES, }); -const previewUrlResource = createCachedResource({ - ttlMs: GITHUB_PREVIEW_URL_CACHE_TTL_MS, - maxEntries: MAX_GITHUB_PREVIEW_URL_CACHE_ENTRIES, -}); - const repoContextResource = createCachedResource({ ttlMs: GITHUB_REPO_CONTEXT_CACHE_TTL_MS, maxEntries: MAX_GITHUB_REPO_CONTEXT_CACHE_ENTRIES, }); -const noPullRequestMatchResource = createCachedResource({ - ttlMs: GITHUB_NO_PR_MATCH_CACHE_TTL_MS, - maxEntries: MAX_GITHUB_NO_PR_MATCH_CACHE_ENTRIES, -}); - -export interface GitHubCommitAuthor { - login: string | null; - avatarUrl: string | null; -} - -const commitAuthorResource = createCachedResource({ - ttlMs: GITHUB_COMMIT_AUTHOR_CACHE_TTL_MS, - maxEntries: MAX_GITHUB_COMMIT_AUTHOR_CACHE_ENTRIES, -}); - export function getCachedGitHubStatus( worktreePath: string, ): GitHubStatus | null { - const cachedState = githubStatusResource.getState(worktreePath); - const cached = cachedState?.isFresh ? cachedState.value : null; - recordGitHubCacheMetric({ - kind: "status", - event: cachedState?.isFresh ? "fresh_hit" : "miss", - worktreePath, - }); - return cached; + return githubStatusResource.get(worktreePath); } export function getCachedGitHubStatusState( @@ -80,11 +46,6 @@ export function setCachedGitHubStatus( value: GitHubStatus, ): void { githubStatusResource.set(worktreePath, value); - recordGitHubCacheMetric({ - kind: "status", - event: "write", - worktreePath, - }); } export function readCachedGitHubStatus( @@ -92,34 +53,9 @@ export function readCachedGitHubStatus( load: () => Promise, options?: CachedResourceReadOptions, ): Promise { - const cached = githubStatusResource.getState(worktreePath); - recordGitHubCacheMetric({ - kind: "status", - event: options?.forceFresh - ? "force_fresh" - : cached?.isFresh - ? "fresh_hit" - : cached - ? "stale_hit" - : "miss", - worktreePath, - }); - return githubStatusResource.read(worktreePath, load, { ...options, - shouldCache: - options?.shouldCache ?? - ((value) => { - const shouldCache = value !== null; - if (shouldCache) { - recordGitHubCacheMetric({ - kind: "status", - event: "write", - worktreePath, - }); - } - return shouldCache; - }), + shouldCache: options?.shouldCache ?? ((value) => value !== null), }); } @@ -144,14 +80,7 @@ export function makePullRequestCommentsCacheKey({ export function getCachedPullRequestComments( cacheKey: string, ): PullRequestComment[] | null { - const cachedState = pullRequestCommentsResource.getState(cacheKey); - const cached = cachedState?.isFresh ? cachedState.value : null; - recordGitHubCacheMetric({ - kind: "comments", - event: cachedState?.isFresh ? "fresh_hit" : "miss", - worktreePath: extractWorktreePathFromCacheKey(cacheKey), - }); - return cached; + return pullRequestCommentsResource.get(cacheKey); } export function getCachedPullRequestCommentsState( @@ -165,11 +94,6 @@ export function setCachedPullRequestComments( value: PullRequestComment[], ): void { pullRequestCommentsResource.set(cacheKey, value); - recordGitHubCacheMetric({ - kind: "comments", - event: "write", - worktreePath: extractWorktreePathFromCacheKey(cacheKey), - }); } export function readCachedPullRequestComments( @@ -177,129 +101,7 @@ export function readCachedPullRequestComments( load: () => Promise, options?: CachedResourceReadOptions, ): Promise { - const worktreePath = extractWorktreePathFromCacheKey(cacheKey); - const cached = pullRequestCommentsResource.getState(cacheKey); - recordGitHubCacheMetric({ - kind: "comments", - event: options?.forceFresh - ? "force_fresh" - : cached?.isFresh - ? "fresh_hit" - : cached - ? "stale_hit" - : "miss", - worktreePath, - }); - - return pullRequestCommentsResource.read( - cacheKey, - async () => { - const value = await load(); - recordGitHubCacheMetric({ - kind: "comments", - event: "write", - worktreePath, - }); - return value; - }, - options, - ); -} - -export function makeGitHubPreviewCachePrefix(worktreePath: string): string { - return `${worktreePath}::preview::`; -} - -export function makeGitHubNoPullRequestCachePrefix( - worktreePath: string, -): string { - return `${worktreePath}::no-pr::`; -} - -export function makeGitHubNoPullRequestCacheKey({ - worktreePath, - localBranch, - headSha, -}: { - worktreePath: string; - localBranch: string; - headSha?: string; -}): string { - return `${makeGitHubNoPullRequestCachePrefix(worktreePath)}${localBranch}::${headSha ?? "no-head"}`; -} - -export function hasCachedNoPullRequestMatch(cacheKey: string): boolean { - return noPullRequestMatchResource.get(cacheKey) === true; -} - -export function setCachedNoPullRequestMatch(cacheKey: string): void { - noPullRequestMatchResource.set(cacheKey, true); -} - -export function clearCachedNoPullRequestMatch(cacheKey: string): void { - noPullRequestMatchResource.invalidate(cacheKey); -} - -export function makeGitHubPreviewCacheKey({ - worktreePath, - repoNameWithOwner, - branchName, - headSha, - pullRequestNumber, -}: { - worktreePath: string; - repoNameWithOwner: string; - branchName: string; - headSha?: string; - pullRequestNumber?: number | null; -}): string { - return `${makeGitHubPreviewCachePrefix(worktreePath)}${repoNameWithOwner}::${branchName}::${headSha ?? "no-head"}::pr-${pullRequestNumber ?? "none"}`; -} - -export function getCachedGitHubPreviewUrl(cacheKey: string): string | null { - const cachedState = previewUrlResource.getState(cacheKey); - const cached = cachedState?.isFresh ? cachedState.value : null; - recordGitHubCacheMetric({ - kind: "preview", - event: cachedState?.isFresh ? "fresh_hit" : "miss", - worktreePath: extractWorktreePathFromCacheKey(cacheKey), - }); - return cached; -} - -export function readCachedGitHubPreviewUrl( - cacheKey: string, - load: () => Promise, - options?: CachedResourceReadOptions, -): Promise { - const worktreePath = extractWorktreePathFromCacheKey(cacheKey); - const cached = previewUrlResource.getState(cacheKey); - recordGitHubCacheMetric({ - kind: "preview", - event: options?.forceFresh - ? "force_fresh" - : cached?.isFresh - ? "fresh_hit" - : cached - ? "stale_hit" - : "miss", - worktreePath, - }); - - return previewUrlResource.read(cacheKey, load, { - ...options, - // Cache misses too so preview-less branches don't repeatedly hit deployments. - shouldCache: - options?.shouldCache ?? - (() => { - recordGitHubCacheMetric({ - kind: "preview", - event: "write", - worktreePath, - }); - return true; - }), - }); + return pullRequestCommentsResource.read(cacheKey, load, options); } export function getCachedRepoContext(worktreePath: string): RepoContext | null { @@ -330,64 +132,10 @@ export function readCachedRepoContext( }); } -export function makeGitHubCommitAuthorCacheKey({ - repoNameWithOwner, - commitHash, -}: { - repoNameWithOwner: string; - commitHash: string; -}): string { - return `${repoNameWithOwner}#${commitHash}`; -} - -export function readCachedGitHubCommitAuthor( - cacheKey: string, - load: () => Promise, - options?: CachedResourceReadOptions, -): Promise { - return commitAuthorResource.read(cacheKey, load, options); -} - export function clearGitHubCachesForWorktree(worktreePath: string): void { - githubStatusResource.invalidate(worktreePath); + githubStatusResource.invalidatePrefix(worktreePath); repoContextResource.invalidate(worktreePath); - recordGitHubCacheMetric({ - kind: "status", - event: "invalidate", - worktreePath, - }); - previewUrlResource.invalidatePrefix( - makeGitHubPreviewCachePrefix(worktreePath), - ); - recordGitHubCacheMetric({ - kind: "preview", - event: "invalidate", - worktreePath, - }); pullRequestCommentsResource.invalidatePrefix( makePullRequestCommentsCachePrefix(worktreePath), ); - noPullRequestMatchResource.invalidatePrefix( - makeGitHubNoPullRequestCachePrefix(worktreePath), - ); - recordGitHubCacheMetric({ - kind: "comments", - event: "invalidate", - worktreePath, - }); -} - -function extractWorktreePathFromCacheKey(cacheKey: string): string | null { - const commentsSeparator = "::comments::"; - const previewSeparator = "::preview::"; - - if (cacheKey.includes(commentsSeparator)) { - return cacheKey.split(commentsSeparator)[0] || null; - } - - if (cacheKey.includes(previewSeparator)) { - return cacheKey.split(previewSeparator)[0] || null; - } - - return cacheKey || null; } diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.ts index ba55a18d290..e4291c632a2 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.ts @@ -4,73 +4,35 @@ import { getCurrentBranch, isUnbornHeadError, } from "../git"; -import { execGitWithShellPath, getSimpleGitWithShellPath } from "../git-client"; +import { execGitWithShellPath } from "../git-client"; import { execWithShellEnv } from "../shell-env"; import { parseUpstreamRef } from "../upstream-ref"; import { clearGitHubCachesForWorktree, - getCachedGitHubPreviewUrl, - getCachedGitHubStatus, - getCachedGitHubStatusState, getCachedPullRequestCommentsState, - makeGitHubPreviewCacheKey, makePullRequestCommentsCacheKey, - readCachedGitHubPreviewUrl, readCachedGitHubStatus, readCachedPullRequestComments, } from "./cache"; -import { - addPullRequestConversationComment, - fetchPullRequestComments, - replyToReviewThread, - resolveReviewThread, -} from "./comments"; -import { - trackGitHubOperation, - trackGitHubOperationEvent, -} from "./github-metrics"; -import { - isRateLimited, - isSecondaryRateLimitError, - onRateLimitHit, - onRateLimitSuccess, -} from "./github-rate-limiter"; -import { - canAttachPullRequestToWorkspace, - type GitRemoteInfo, -} from "./pr-attachment"; +import { fetchPullRequestComments, resolveReviewThread } from "./comments"; import { getPRForBranch } from "./pr-resolution"; import { extractNwoFromUrl, getRepoContext } from "./repo-context"; import { GHDeploymentSchema, GHDeploymentStatusSchema, - GHJobResponseSchema, type RepoContext, } from "./types"; export interface PullRequestCommentsTarget { prNumber: number; repoContext: Pick; - prUrl?: string | null; } -export { - addPullRequestConversationComment, - clearGitHubCachesForWorktree, - replyToReviewThread, - resolveReviewThread, -}; +export { clearGitHubCachesForWorktree, resolveReviewThread }; function getPullRequestCommentsRepoNameWithOwner( target: PullRequestCommentsTarget, ): string | null { - const prRepoNameWithOwner = target.prUrl - ? extractNwoFromUrl(target.prUrl) - : null; - if (prRepoNameWithOwner) { - return prRepoNameWithOwner; - } - const targetUrl = target.repoContext.isFork ? target.repoContext.upstreamUrl : target.repoContext.repoUrl; @@ -78,34 +40,41 @@ function getPullRequestCommentsRepoNameWithOwner( return extractNwoFromUrl(targetUrl); } -async function getGitRemoteInfos( +async function resolvePullRequestCommentsTarget( worktreePath: string, -): Promise { - const git = await getSimpleGitWithShellPath(worktreePath); - const remotes = await git.getRemotes(true); - return remotes.map((remote) => ({ - name: remote.name, - fetchUrl: remote.refs.fetch, - pushUrl: remote.refs.push, - })); -} + branchOverride?: string | null, +): Promise { + const repoContext = await getRepoContext(worktreePath); + if (!repoContext) { + return null; + } -async function resolveAttachedPullRequest({ - worktreePath, - localBranch, - repoContext, - headSha, - fallbackRemote, -}: { - worktreePath: string; - localBranch: string; - repoContext: RepoContext; - headSha?: string; - fallbackRemote: string; -}): Promise { + const branchName = + branchOverride?.trim() || (await getCurrentBranch(worktreePath)); + if (!branchName) { + return null; + } + + const revParseTarget = branchOverride ? `refs/heads/${branchName}` : "HEAD"; + const shaResult = await execGitWithShellPath(["rev-parse", revParseTarget], { + cwd: worktreePath, + }).catch((error) => { + if (isUnbornHeadError(error)) { + return { stdout: "", stderr: "" }; + } + if (branchOverride) { + return { stdout: "", stderr: "" }; + } + throw error; + }); + const headSha = shaResult.stdout.trim() || undefined; + + if (branchOverride && !headSha) { + return null; + } const prInfo = await getPRForBranch( worktreePath, - localBranch, + branchName, repoContext, headSha, ); @@ -113,32 +82,9 @@ async function resolveAttachedPullRequest({ return null; } - const remotes = await getGitRemoteInfos(worktreePath); - return canAttachPullRequestToWorkspace({ - pr: prInfo, - remotes, - fallbackRemote, - }) - ? prInfo - : null; -} - -async function resolvePullRequestCommentsTarget( - worktreePath: string, -): Promise { - const githubStatus = await fetchGitHubPRStatus(worktreePath); - if (!githubStatus?.pr) { - return null; - } - return { - prNumber: githubStatus.pr.number, - repoContext: { - repoUrl: githubStatus.repoUrl, - upstreamUrl: githubStatus.upstreamUrl ?? githubStatus.repoUrl, - isFork: githubStatus.isFork ?? false, - }, - prUrl: githubStatus.pr.url, + prNumber: prInfo.number, + repoContext, }; } @@ -154,95 +100,106 @@ export function resolveRemoteBranchNameForGitHubStatus({ return upstreamBranchName?.trim() || prHeadRefName?.trim() || localBranchName; } -interface ResolvedGitHubStatusContext { - repoContext: RepoContext; - branchName: string; - headSha?: string; - trackingRemote: string; - previewBranchName: string; - parsedUpstreamBranchName?: string | null; -} - -async function resolveGitHubStatusContext( - worktreePath: string, -): Promise { - const repoContext = await getRepoContext(worktreePath); - if (!repoContext) { - return null; - } - - const branchName = await getCurrentBranch(worktreePath); - if (!branchName) { - return null; - } - - const [shaResult, upstreamResult] = await Promise.all([ - execGitWithShellPath(["rev-parse", "HEAD"], { - cwd: worktreePath, - }).catch((error) => { - if (isUnbornHeadError(error)) { - return { stdout: "", stderr: "" }; - } - throw error; - }), - execGitWithShellPath(["rev-parse", "--abbrev-ref", "@{upstream}"], { - cwd: worktreePath, - }).catch(() => ({ stdout: "", stderr: "" })), - ]); - - const headSha = shaResult.stdout.trim() || undefined; - const parsedUpstreamRef = parseUpstreamRef(upstreamResult.stdout.trim()); - - return { - repoContext, - branchName, - headSha, - trackingRemote: parsedUpstreamRef?.remoteName ?? "origin", - previewBranchName: resolveRemoteBranchNameForGitHubStatus({ - localBranchName: branchName, - upstreamBranchName: parsedUpstreamRef?.branchName, - }), - parsedUpstreamBranchName: parsedUpstreamRef?.branchName, - }; -} - async function refreshGitHubPRStatus( worktreePath: string, + branchOverride?: string | null, ): Promise { try { - const context = await resolveGitHubStatusContext(worktreePath); - if (!context) { + const repoContext = await getRepoContext(worktreePath); + if (!repoContext) { return null; } - const prInfo = await resolveAttachedPullRequest({ - worktreePath, - localBranch: context.branchName, - repoContext: context.repoContext, - headSha: context.headSha, - fallbackRemote: context.trackingRemote, + const branchName = + branchOverride?.trim() || (await getCurrentBranch(worktreePath)); + if (!branchName) { + return null; + } + + const revParseTarget = branchOverride ? `refs/heads/${branchName}` : "HEAD"; + const upstreamTarget = branchOverride + ? `${branchName}@{upstream}` + : "@{upstream}"; + + const [shaResult, upstreamResult] = await Promise.all([ + execGitWithShellPath(["rev-parse", revParseTarget], { + cwd: worktreePath, + }).catch((error) => { + if (isUnbornHeadError(error)) { + return { stdout: "", stderr: "" }; + } + if (branchOverride) { + return { stdout: "", stderr: "" }; + } + throw error; + }), + execGitWithShellPath(["rev-parse", "--abbrev-ref", upstreamTarget], { + cwd: worktreePath, + }).catch(() => ({ stdout: "", stderr: "" })), + ]); + const headSha = shaResult.stdout.trim() || undefined; + + // When using a branch override, we must have a valid SHA to avoid + // getPRForBranch falling back to HEAD (which is a different branch). + if (branchOverride && !headSha) { + return null; + } + + const parsedUpstreamRef = parseUpstreamRef(upstreamResult.stdout.trim()); + const trackingRemote = parsedUpstreamRef?.remoteName ?? "origin"; + const previewBranchName = resolveRemoteBranchNameForGitHubStatus({ + localBranchName: branchName, + upstreamBranchName: parsedUpstreamRef?.branchName, }); + const [prInfo, previewUrl] = await Promise.all([ + getPRForBranch(worktreePath, branchName, repoContext, headSha), + fetchPreviewDeploymentUrl( + worktreePath, + headSha, + previewBranchName, + repoContext, + ), + ]); + const remoteBranchName = resolveRemoteBranchNameForGitHubStatus({ - localBranchName: context.branchName, - upstreamBranchName: context.parsedUpstreamBranchName, + localBranchName: branchName, + upstreamBranchName: parsedUpstreamRef?.branchName, prHeadRefName: prInfo?.headRefName, }); const branchCheck = await branchExistsOnRemote( worktreePath, remoteBranchName, - context.trackingRemote, + trackingRemote, ); - return { + let finalPreviewUrl = previewUrl; + if (!finalPreviewUrl && prInfo?.number) { + const targetUrl = repoContext.isFork + ? repoContext.upstreamUrl + : repoContext.repoUrl; + const nwo = extractNwoFromUrl(targetUrl); + if (nwo) { + finalPreviewUrl = await queryDeploymentUrl( + worktreePath, + nwo, + `ref=${encodeURIComponent(`refs/pull/${prInfo.number}/merge`)}`, + ); + } + } + + const result: GitHubStatus = { pr: prInfo, - repoUrl: context.repoContext.repoUrl, - upstreamUrl: context.repoContext.upstreamUrl, - isFork: context.repoContext.isFork, + repoUrl: repoContext.repoUrl, + upstreamUrl: repoContext.upstreamUrl, + isFork: repoContext.isFork, branchExistsOnRemote: branchCheck.status === "exists", + previewUrl: finalPreviewUrl, lastRefreshed: Date.now(), }; + + return result; } catch { return null; } @@ -265,193 +222,76 @@ async function refreshGitHubPRComments({ } /** - * Fetches GitHub PR status for a worktree using the `gh` CLI. + * Fetches GitHub PR status for a worktree or branch workspace using the `gh` CLI. * Returns null if `gh` is not installed, not authenticated, or on error. + * + * @param branchName - Optional branch name override. When provided (for branch + * workspaces), resolves the SHA and upstream for that branch instead of using + * HEAD / the checked-out branch. Also used to scope the cache key. */ export async function fetchGitHubPRStatus( worktreePath: string, + branchName?: string | null, ): Promise { - if (isRateLimited()) { - // When rate limited, return stale cache or null โ€” never throw, - // and never overwrite stale cache with null - const cached = getCachedGitHubStatus(worktreePath); - trackGitHubOperationEvent({ - name: "status_refresh", - category: "sync", - worktreePath, - success: - cached !== null || getCachedGitHubStatusState(worktreePath) !== null, - durationMs: 0, - rateLimited: true, - error: - cached === null && getCachedGitHubStatusState(worktreePath) === null - ? "Rate limited without cached status" - : undefined, - }); - return cached; - } - return trackGitHubOperation({ - name: "status_refresh", - category: "sync", - worktreePath, - fn: () => - readCachedGitHubStatus(worktreePath, () => - rateLimitedRefresh(() => refreshGitHubPRStatus(worktreePath)), - ), - }); -} - -async function rateLimitedRefresh(fn: () => Promise): Promise { - try { - const result = await fn(); - onRateLimitSuccess(); - return result; - } catch (error) { - if (isSecondaryRateLimitError(error)) { - onRateLimitHit(); - } - throw error; - } + const cacheKey = branchName ? `${worktreePath}::${branchName}` : worktreePath; + return readCachedGitHubStatus(cacheKey, () => + refreshGitHubPRStatus(worktreePath, branchName), + ); } export async function fetchGitHubPRComments({ worktreePath, pullRequest, + branchName, }: { worktreePath: string; pullRequest?: PullRequestCommentsTarget | null; + branchName?: string | null; }): Promise { - if (isRateLimited()) { - trackGitHubOperationEvent({ - name: "comments_refresh", - category: "sync", - worktreePath, - success: true, - durationMs: 0, - rateLimited: true, - }); - return []; - } try { - return await trackGitHubOperation({ - name: "comments_refresh", - category: "sync", - worktreePath, - fn: async () => { - const pullRequestTarget = - pullRequest ?? (await resolvePullRequestCommentsTarget(worktreePath)); - if (!pullRequestTarget) { - return []; - } + const pullRequestTarget = + pullRequest ?? + (await resolvePullRequestCommentsTarget(worktreePath, branchName)); + if (!pullRequestTarget) { + return []; + } - const repoNameWithOwner = - getPullRequestCommentsRepoNameWithOwner(pullRequestTarget); - if (!repoNameWithOwner) { - return []; - } + const repoNameWithOwner = + getPullRequestCommentsRepoNameWithOwner(pullRequestTarget); + if (!repoNameWithOwner) { + return []; + } - const cacheKey = makePullRequestCommentsCacheKey({ + const cacheKey = makePullRequestCommentsCacheKey({ + worktreePath, + repoNameWithOwner, + pullRequestNumber: pullRequestTarget.prNumber, + }); + try { + return await readCachedPullRequestComments(cacheKey, () => + refreshGitHubPRComments({ worktreePath, repoNameWithOwner, pullRequestNumber: pullRequestTarget.prNumber, - }); - try { - return await readCachedPullRequestComments(cacheKey, () => - rateLimitedRefresh(() => - refreshGitHubPRComments({ - worktreePath, - repoNameWithOwner, - pullRequestNumber: pullRequestTarget.prNumber, - }), - ), - ); - } catch (error) { - const cached = getCachedPullRequestCommentsState(cacheKey); - if (cached) { - console.warn( - "[GitHub] Failed to refresh pull request comments; using cached value:", - error, - ); - return cached.value; - } - - throw error; - } - }, - }); + }), + ); + } catch (error) { + const cached = getCachedPullRequestCommentsState(cacheKey); + if (cached) { + console.warn( + "[GitHub] Failed to refresh pull request comments; using cached value:", + error, + ); + return cached.value; + } + + throw error; + } } catch { return []; } } -export async function fetchGitHubPreviewUrl({ - worktreePath, - githubStatus, - forceFresh = false, -}: { - worktreePath: string; - githubStatus?: GitHubStatus | null; - forceFresh?: boolean; -}): Promise { - const context = await resolveGitHubStatusContext(worktreePath); - if (!context) { - return null; - } - - const targetUrl = context.repoContext.isFork - ? context.repoContext.upstreamUrl - : context.repoContext.repoUrl; - const repoNameWithOwner = extractNwoFromUrl(targetUrl); - if (!repoNameWithOwner) { - return null; - } - - const cacheKey = makeGitHubPreviewCacheKey({ - worktreePath, - repoNameWithOwner, - branchName: context.previewBranchName, - headSha: context.headSha, - pullRequestNumber: githubStatus?.pr?.number, - }); - - if (isRateLimited()) { - const cached = getCachedGitHubPreviewUrl(cacheKey); - trackGitHubOperationEvent({ - name: "preview_refresh", - category: "sync", - worktreePath, - success: true, - durationMs: 0, - rateLimited: true, - }); - return cached; - } - - return trackGitHubOperation({ - name: "preview_refresh", - category: "sync", - worktreePath, - fn: async () => { - return readCachedGitHubPreviewUrl( - cacheKey, - () => - rateLimitedRefresh(() => - refreshGitHubPreviewUrl({ - worktreePath, - repoNameWithOwner, - branchName: context.previewBranchName, - headSha: context.headSha, - pullRequestNumber: githubStatus?.pr?.number, - }), - ), - { - forceFresh, - }, - ); - }, - }); -} - function isSafeHttpUrl(url: string): boolean { try { const parsed = new URL(url); @@ -471,17 +311,11 @@ async function queryDeploymentUrl( nwo: string, queryParams: string, ): Promise { - const { stdout } = await trackGitHubOperation({ - name: "gh_api_deployments", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - ["api", `repos/${nwo}/deployments?${queryParams}&per_page=5`], - { cwd: worktreePath }, - ), - }); + const { stdout } = await execWithShellEnv( + "gh", + ["api", `repos/${nwo}/deployments?${queryParams}&per_page=5`], + { cwd: worktreePath }, + ); const rawDeployments: unknown = JSON.parse(stdout.trim()); if (!Array.isArray(rawDeployments) || rawDeployments.length === 0) { @@ -502,17 +336,11 @@ async function queryDeploymentUrl( const urls = await Promise.all( deploymentIds.map(async (id): Promise => { try { - const { stdout: out } = await trackGitHubOperation({ - name: "gh_api_deployment_status", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - ["api", `repos/${nwo}/deployments/${id}/statuses?per_page=1`], - { cwd: worktreePath }, - ), - }); + const { stdout: out } = await execWithShellEnv( + "gh", + ["api", `repos/${nwo}/deployments/${id}/statuses?per_page=1`], + { cwd: worktreePath }, + ); const rawStatuses: unknown = JSON.parse(out.trim()); if (!Array.isArray(rawStatuses) || rawStatuses.length === 0) { return undefined; @@ -543,26 +371,29 @@ async function queryDeploymentUrl( * Fetches the preview deployment URL by trying multiple query strategies: * 1. By commit SHA (works for Vercel, Netlify official integrations) * 2. By branch name ref (works for some CI configurations) - * 3. By PR merge ref when the PR number is already known + * The PR merge ref (refs/pull/N/merge) is handled in fetchGitHubPRStatus + * after the PR number is known. */ -async function refreshGitHubPreviewUrl({ - worktreePath, - repoNameWithOwner, - headSha, - branchName, - pullRequestNumber, -}: { - worktreePath: string; - repoNameWithOwner: string; - headSha?: string; - branchName: string; - pullRequestNumber?: number; -}): Promise { +async function fetchPreviewDeploymentUrl( + worktreePath: string, + headSha: string | undefined, + branchName: string, + repoContext: RepoContext, +): Promise { try { + const targetUrl = repoContext.isFork + ? repoContext.upstreamUrl + : repoContext.repoUrl; + const nwo = extractNwoFromUrl(targetUrl); + if (!nwo) { + return undefined; + } + if (headSha) { + // Try by commit SHA (works for Vercel, Netlify official integrations) const bySha = await queryDeploymentUrl( worktreePath, - repoNameWithOwner, + nwo, `sha=${headSha}`, ); if (bySha) { @@ -570,297 +401,13 @@ async function refreshGitHubPreviewUrl({ } } - const byBranch = await queryDeploymentUrl( + // Fall back to branch name (works for some CI configurations) + return await queryDeploymentUrl( worktreePath, - repoNameWithOwner, + nwo, `ref=${encodeURIComponent(branchName)}`, ); - if (byBranch) { - return byBranch; - } - - if (!pullRequestNumber) { - return null; - } - - return ( - (await queryDeploymentUrl( - worktreePath, - repoNameWithOwner, - `ref=${encodeURIComponent(`refs/pull/${pullRequestNumber}/merge`)}`, - )) ?? null - ); - } catch { - return null; - } -} - -export interface JobStepInfo { - name: string; - status: "queued" | "in_progress" | "completed"; - conclusion: string | null; - number: number; -} - -/** - * Extracts job ID from a GitHub Actions details URL. - * URL format: https://github.com/{owner}/{repo}/actions/runs/{run_id}/job/{job_id} - */ -function parseJobIdFromUrl(detailsUrl: string): string | null { - try { - const url = new URL(detailsUrl); - const match = url.pathname.match(/\/actions\/runs\/\d+\/job\/(\d+)/); - return match?.[1] ?? null; - } catch { - return null; - } -} - -/** - * Extracts nwo (owner/repo) from a GitHub Actions details URL. - */ -function parseNwoFromActionsUrl(detailsUrl: string): string | null { - try { - const url = new URL(detailsUrl); - const match = url.pathname.match(/^\/([^/]+\/[^/]+)\/actions\//); - return match?.[1] ?? null; } catch { - return null; - } -} - -/** - * Fetches job steps for a given GitHub Actions check using its details URL. - */ -export async function fetchCheckJobSteps( - worktreePath: string, - detailsUrl: string, -): Promise { - const jobId = parseJobIdFromUrl(detailsUrl); - const nwo = parseNwoFromActionsUrl(detailsUrl); - if (!jobId || !nwo) { - return []; - } - - try { - const { stdout } = await trackGitHubOperation({ - name: "gh_api_actions_job", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv("gh", ["api", `repos/${nwo}/actions/jobs/${jobId}`], { - cwd: worktreePath, - }), - }); - - const raw: unknown = JSON.parse(stdout.trim()); - const result = GHJobResponseSchema.safeParse(raw); - if (!result.success) { - return []; - } - - return (result.data.steps ?? []).map((step) => ({ - name: step.name, - status: step.status, - conclusion: step.conclusion ?? null, - number: step.number, - })); - } catch { - return []; - } -} - -export interface StructuredJobStep { - name: string; - number: number; - status: "queued" | "in_progress" | "completed"; - conclusion: string | null; - durationSeconds: number | null; - logs: string; -} - -export interface StructuredJobResult { - jobStatus: "queued" | "in_progress" | "completed" | "waiting"; - jobConclusion: string | null; - steps: StructuredJobStep[]; -} - -/** - * Fetches job step metadata and logs, returning structured per-step data. - */ -export async function fetchStructuredJobLogs( - worktreePath: string, - detailsUrl: string, -): Promise { - const jobId = parseJobIdFromUrl(detailsUrl); - const nwo = parseNwoFromActionsUrl(detailsUrl); - const emptyResult: StructuredJobResult = { - jobStatus: "queued", - jobConclusion: null, - steps: [], - }; - if (!jobId || !nwo) { - return emptyResult; - } - - try { - // Always fetch job metadata; logs may 404 for in-progress jobs - const jobResult = await trackGitHubOperation({ - name: "gh_api_actions_job", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv("gh", ["api", `repos/${nwo}/actions/jobs/${jobId}`], { - cwd: worktreePath, - }), - }); - - const raw: unknown = JSON.parse(jobResult.stdout.trim()); - const result = GHJobResponseSchema.safeParse(raw); - if (!result.success || !result.data.steps) { - return emptyResult; - } - - const jobData = result.data; - const steps = jobData.steps ?? []; - const jobCompleted = jobData.status === "completed"; - - // Only fetch logs if job is completed (API returns 404 for in-progress) - let rawLogs = ""; - if (jobCompleted) { - try { - const logsResult = await trackGitHubOperation({ - name: "gh_api_actions_job_logs", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - ["api", `repos/${nwo}/actions/jobs/${jobId}/logs`], - { cwd: worktreePath, maxBuffer: 10 * 1024 * 1024 }, - ), - }); - rawLogs = logsResult.stdout; - } catch { - // Logs not yet available - } - } - - // Parse raw logs into per-step sections. - // GitHub log format: each line starts with a timestamp like "2024-01-01T00:00:00.0000000Z " - // Steps are separated by ##[group] / ##[endgroup] markers, but these aren't always reliable. - // Instead, match by step started_at/completed_at time ranges. - const logLines = rawLogs.split("\n"); - const stepLogs: Map = new Map(); - - // Build time ranges for each step - const stepRanges = steps.map((step) => ({ - number: step.number, - start: step.started_at ? new Date(step.started_at).getTime() : 0, - end: step.completed_at - ? new Date(step.completed_at).getTime() - : Number.POSITIVE_INFINITY, - })); - - for (const line of logLines) { - const tsMatch = line.match( - /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z)\s/, - ); - if (!tsMatch) continue; - const lineTime = new Date(tsMatch[1]).getTime(); - const lineContent = line.slice(tsMatch[0].length); - - // Find which step this line belongs to - for (const range of stepRanges) { - if (lineTime >= range.start && lineTime <= range.end + 1000) { - if (!stepLogs.has(range.number)) { - stepLogs.set(range.number, []); - } - stepLogs.get(range.number)?.push(lineContent); - break; - } - } - } - - return { - jobStatus: jobData.status, - jobConclusion: jobData.conclusion ?? null, - steps: steps.map((step) => { - let durationSeconds: number | null = null; - if (step.started_at && step.completed_at) { - durationSeconds = Math.round( - (new Date(step.completed_at).getTime() - - new Date(step.started_at).getTime()) / - 1000, - ); - } - return { - name: step.name, - number: step.number, - status: step.status, - conclusion: step.conclusion ?? null, - durationSeconds, - logs: stepLogs.get(step.number)?.join("\n") ?? "", - }; - }), - }; - } catch (err) { - console.error("[fetchStructuredJobLogs] Failed:", err); - return emptyResult; + return undefined; } } - -export interface JobStatusInfo { - detailsUrl: string; - status: "queued" | "in_progress" | "completed" | "waiting"; - conclusion: string | null; -} - -/** - * Fetches current status for multiple jobs in parallel. - */ -export async function fetchJobStatuses( - worktreePath: string, - detailsUrls: string[], -): Promise { - const results = await Promise.allSettled( - detailsUrls.map(async (detailsUrl) => { - const jobId = parseJobIdFromUrl(detailsUrl); - const nwo = parseNwoFromActionsUrl(detailsUrl); - if (!jobId || !nwo) { - return { detailsUrl, status: "queued" as const, conclusion: null }; - } - const { stdout } = await trackGitHubOperation({ - name: "gh_api_actions_job_status", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - [ - "api", - `repos/${nwo}/actions/jobs/${jobId}`, - "--jq", - '.status + "|" + (.conclusion // "")', - ], - { cwd: worktreePath }, - ), - }); - const [status, conclusion] = stdout.trim().split("|"); - return { - detailsUrl, - status: (status || "queued") as JobStatusInfo["status"], - conclusion: conclusion || null, - }; - }), - ); - return results.map((r, i) => - r.status === "fulfilled" - ? r.value - : { - detailsUrl: detailsUrls[i], - status: "queued" as const, - conclusion: null, - }, - ); -} diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts index ac2809dd786..60808ff763f 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts @@ -1,17 +1,12 @@ +// v1-only. Dies with the v1 UI sunset. Don't evolve this module โ€” v2 already +// resolves PRs via host-service (`packages/host-service/src/runtime/pull-requests` +// backing `git.getPullRequest` + `pullRequests.getByWorkspaces`). Everything +// under `renderer/screens/main/` + `routes/_authenticated/_dashboard/workspace/` +// gets deleted together; no port needed. import type { CheckItem, GitHubStatus } from "@superset/local-db"; import { execGitWithShellPath } from "../git-client"; import { execWithShellEnv } from "../shell-env"; -import { - clearCachedNoPullRequestMatch, - hasCachedNoPullRequestMatch, - makeGitHubNoPullRequestCacheKey, - setCachedNoPullRequestMatch, -} from "./cache"; -import { - trackGitHubOperation, - trackGitHubOperationEvent, -} from "./github-metrics"; -import { getPullRequestRepoNamesForWorktree } from "./repo-context"; +import { getPullRequestRepoArgs } from "./repo-context"; import { type GHPRResponse, GHPRResponseSchema, @@ -19,20 +14,7 @@ import { } from "./types"; const PR_JSON_FIELDS = - "number,title,url,state,isDraft,mergedAt,additions,deletions,headRefOid,headRefName,headRepository,headRepositoryOwner,isCrossRepository,reviewDecision,statusCheckRollup,reviewRequests,assignees"; - -function getPullRequestRepoArgSets(repoNames: string[]): string[][] { - if (repoNames.length === 0) { - return [[]]; - } - - return repoNames.map((repoName) => ["--repo", repoName]); -} - -interface PullRequestLookupResult { - pr: GitHubStatus["pr"]; - hadLookupFailure: boolean; -} + "number,title,url,state,isDraft,mergedAt,additions,deletions,headRefOid,headRefName,headRepository,headRepositoryOwner,isCrossRepository,reviewDecision,statusCheckRollup,reviewRequests"; export async function getPRForBranch( worktreePath: string, @@ -40,55 +22,26 @@ export async function getPRForBranch( repoContext?: RepoContext, headSha?: string, ): Promise { - const noPullRequestCacheKey = makeGitHubNoPullRequestCacheKey({ - worktreePath, - localBranch, - headSha, - }); - if (hasCachedNoPullRequestMatch(noPullRequestCacheKey)) { - return null; - } - const byTracking = await getPRByBranchTracking( worktreePath, localBranch, headSha, ); if (byTracking) { - clearCachedNoPullRequestMatch(noPullRequestCacheKey); return byTracking; } - const repoNames = await getPullRequestRepoNamesForWorktree({ - worktreePath, - repoContext, - }); - const byHeadBranch = await findPRByHeadBranch( worktreePath, localBranch, - repoNames, - headSha, - ); - if (byHeadBranch.pr) { - clearCachedNoPullRequestMatch(noPullRequestCacheKey); - return byHeadBranch.pr; - } - - const byHeadCommit = await findPRByHeadCommit( - worktreePath, - repoNames, + repoContext, headSha, ); - if (byHeadCommit.pr) { - clearCachedNoPullRequestMatch(noPullRequestCacheKey); - return byHeadCommit.pr; + if (byHeadBranch) { + return byHeadBranch; } - if (!byHeadBranch.hadLookupFailure && !byHeadCommit.hadLookupFailure) { - setCachedNoPullRequestMatch(noPullRequestCacheKey); - } - return null; + return findPRByHeadCommit(worktreePath, repoContext, headSha); } /** @@ -132,7 +85,10 @@ function getForkOwnerPrefix( export function prMatchesLocalBranch( localBranch: string, - pr: Pick, + pr: Pick< + GHPRResponse, + "headRefName" | "headRepositoryOwner" | "isCrossRepository" + >, ): boolean { if (!branchMatchesPR(localBranch, pr.headRefName)) { return false; @@ -140,6 +96,9 @@ export function prMatchesLocalBranch( const ownerPrefix = getForkOwnerPrefix(localBranch, pr.headRefName); if (!ownerPrefix) { + // Without a fork-owner prefix in the local branch, a cross-fork PR whose + // headRefName collides (e.g. fork:main โ†’ base:main) would misattribute. + if (pr.isCrossRepository) return false; return localBranch === pr.headRefName; } @@ -221,20 +180,12 @@ async function getPRByBranchTracking( localBranch: string, headSha?: string, ): Promise { - const startedAt = Date.now(); try { const { stdout } = await execWithShellEnv( "gh", ["pr", "view", "--json", PR_JSON_FIELDS], { cwd: worktreePath }, ); - trackGitHubOperationEvent({ - name: "gh_pr_view", - category: "gh", - worktreePath, - success: true, - durationMs: Date.now() - startedAt, - }); const data = parsePRResponse(stdout); if (!data) { @@ -255,23 +206,8 @@ async function getPRByBranchTracking( error instanceof Error && error.message.toLowerCase().includes("no pull requests found") ) { - trackGitHubOperationEvent({ - name: "gh_pr_view_no_match", - category: "gh", - worktreePath, - success: true, - durationMs: Date.now() - startedAt, - }); return null; } - trackGitHubOperationEvent({ - name: "gh_pr_view", - category: "gh", - worktreePath, - success: false, - durationMs: Date.now() - startedAt, - error, - }); throw error; } } @@ -283,73 +219,42 @@ async function getPRByBranchTracking( async function findPRByHeadBranch( worktreePath: string, localBranch: string, - repoNames: string[], + repoContext?: RepoContext, headSha?: string, -): Promise { +): Promise { try { const matches = new Map(); - const repoArgSets = getPullRequestRepoArgSets(repoNames); - let hadLookupFailure = false; - - for (const repoArgs of repoArgSets) { - for (const branchCandidate of getPRHeadBranchCandidates(localBranch)) { - let stdout: string; - try { - ({ stdout } = await trackGitHubOperation({ - name: "gh_pr_list_by_head_branch", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - [ - "pr", - "list", - ...repoArgs, - "--state", - "all", - "--head", - branchCandidate, - "--limit", - "20", - "--json", - PR_JSON_FIELDS, - ], - { cwd: worktreePath }, - ), - })); - } catch (error) { - hadLookupFailure = true; - console.warn( - "[GitHub/findPRByHeadBranch] Failed repo-scoped PR lookup:", - { - worktreePath, - repoArgs, - branchCandidate, - message: error instanceof Error ? error.message : String(error), - }, - ); - continue; - } - for (const candidate of parsePRListResponse(stdout)) { - if (shouldAcceptPRMatch({ localBranch, pr: candidate, headSha })) { - matches.set(candidate.number, candidate); - } + for (const branchCandidate of getPRHeadBranchCandidates(localBranch)) { + const { stdout } = await execWithShellEnv( + "gh", + [ + "pr", + "list", + ...getPullRequestRepoArgs(repoContext), + "--state", + "all", + "--head", + branchCandidate, + "--limit", + "20", + "--json", + PR_JSON_FIELDS, + ], + { cwd: worktreePath }, + ); + + for (const candidate of parsePRListResponse(stdout)) { + if (shouldAcceptPRMatch({ localBranch, pr: candidate, headSha })) { + matches.set(candidate.number, candidate); } } } const bestMatch = sortPRCandidates([...matches.values()], headSha)[0]; - return { - pr: bestMatch ? formatPRData(bestMatch) : null, - hadLookupFailure, - }; + return bestMatch ? formatPRData(bestMatch) : null; } catch { - return { - pr: null, - hadLookupFailure: true, - }; + return null; } } @@ -359,9 +264,9 @@ async function findPRByHeadBranch( */ async function findPRByHeadCommit( worktreePath: string, - repoNames: string[], + repoContext?: RepoContext, providedSha?: string, -): Promise { +): Promise { try { let headSha = providedSha; if (!headSha) { @@ -372,70 +277,39 @@ async function findPRByHeadCommit( headSha = headOutput.trim(); } if (!headSha) { - return { - pr: null, - hadLookupFailure: false, - }; + return null; } - const exactHeadMatches: GHPRResponse[] = []; - let hadLookupFailure = false; - for (const repoArgs of getPullRequestRepoArgSets(repoNames)) { - let stdout: string; - try { - ({ stdout } = await trackGitHubOperation({ - name: "gh_pr_list_by_head_commit", - category: "gh", - worktreePath, - fn: () => - execWithShellEnv( - "gh", - [ - "pr", - "list", - ...repoArgs, - "--state", - "all", - "--search", - `${headSha} is:pr`, - "--limit", - "20", - "--json", - PR_JSON_FIELDS, - ], - { cwd: worktreePath }, - ), - })); - } catch (error) { - hadLookupFailure = true; - console.warn( - "[GitHub/findPRByHeadCommit] Failed repo-scoped PR lookup:", - { - worktreePath, - repoArgs, - headSha, - message: error instanceof Error ? error.message : String(error), - }, - ); - continue; - } + const { stdout } = await execWithShellEnv( + "gh", + [ + "pr", + "list", + ...getPullRequestRepoArgs(repoContext), + "--state", + "all", + "--search", + `${headSha} is:pr`, + "--limit", + "20", + "--json", + PR_JSON_FIELDS, + ], + { cwd: worktreePath }, + ); - const candidates = parsePRListResponse(stdout); - exactHeadMatches.push( - ...candidates.filter((candidate) => candidate.headRefOid === headSha), - ); + const candidates = parsePRListResponse(stdout); + const exactHeadMatches = candidates.filter( + (candidate) => candidate.headRefOid === headSha, + ); + const bestMatch = sortPRCandidates(exactHeadMatches, headSha)[0]; + if (bestMatch) { + return formatPRData(bestMatch); } - const bestMatch = sortPRCandidates(exactHeadMatches, headSha)[0]; - return { - pr: bestMatch ? formatPRData(bestMatch) : null, - hadLookupFailure, - }; + return null; } catch { - return { - pr: null, - hadLookupFailure: true, - }; + return null; } } @@ -512,7 +386,6 @@ function formatPRData(data: GHPRResponse): NonNullable { checksStatus: computeChecksStatus(data.statusCheckRollup), checks: parseChecks(data.statusCheckRollup), requestedReviewers: parseReviewRequests(data.reviewRequests), - assignees: parseAssignees(data.assignees), }; } @@ -523,11 +396,6 @@ function parseReviewRequests( return requests.map((r) => r.login || r.slug || r.name || "").filter(Boolean); } -function parseAssignees(assignees: GHPRResponse["assignees"]): string[] { - if (!assignees || assignees.length === 0) return []; - return assignees.map((assignee) => assignee.login || "").filter(Boolean); -} - function mapPRState( state: GHPRResponse["state"], isDraft: boolean, diff --git a/apps/desktop/src/main/lib/browser/browser-manager.ts b/apps/desktop/src/main/lib/browser/browser-manager.ts index 4012ce15d87..9b960041cb5 100644 --- a/apps/desktop/src/main/lib/browser/browser-manager.ts +++ b/apps/desktop/src/main/lib/browser/browser-manager.ts @@ -10,6 +10,7 @@ import { shell, webContents, } from "electron"; +import { safeOpenExternal } from "main/lib/safe-url"; interface ConsoleEntry { level: "log" | "warn" | "error" | "info" | "debug"; @@ -975,7 +976,9 @@ class BrowserManager extends EventEmitter { menuItems.push( { label: "Open Link in Default Browser", - click: () => shell.openExternal(linkURL), + click: () => { + void safeOpenExternal(linkURL); + }, }, { label: "Open Link as New Split", @@ -1049,7 +1052,7 @@ class BrowserManager extends EventEmitter { label: "Open Page in Default Browser", click: () => { if (pageURL && pageURL !== "about:blank") { - shell.openExternal(pageURL); + void safeOpenExternal(pageURL); } }, enabled: !!pageURL && pageURL !== "about:blank", diff --git a/apps/desktop/src/main/lib/safe-url/index.ts b/apps/desktop/src/main/lib/safe-url/index.ts new file mode 100644 index 00000000000..cec73bbf341 --- /dev/null +++ b/apps/desktop/src/main/lib/safe-url/index.ts @@ -0,0 +1,2 @@ +export { safeOpenExternal } from "./safe-url"; +export { externalUrlLogLabel, isSafeExternalUrl } from "./scheme"; diff --git a/apps/desktop/src/main/lib/safe-url/safe-url.test.ts b/apps/desktop/src/main/lib/safe-url/safe-url.test.ts new file mode 100644 index 00000000000..33340bd175f --- /dev/null +++ b/apps/desktop/src/main/lib/safe-url/safe-url.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "bun:test"; +import { externalUrlLogLabel, isSafeExternalUrl } from "./scheme"; + +describe("isSafeExternalUrl", () => { + it("allows http, https, and mailto URLs", () => { + expect(isSafeExternalUrl("http://example.com")).toBe(true); + expect(isSafeExternalUrl("https://example.com/path?q=1")).toBe(true); + expect(isSafeExternalUrl("mailto:user@example.com")).toBe(true); + expect(isSafeExternalUrl("HTTPS://EXAMPLE.COM")).toBe(true); + }); + + it("blocks file, javascript, data, and custom-scheme URLs", () => { + expect( + isSafeExternalUrl("file:///System/Applications/Calculator.app"), + ).toBe(false); + expect(isSafeExternalUrl("file:///etc/passwd")).toBe(false); + expect(isSafeExternalUrl("javascript:alert(1)")).toBe(false); + expect(isSafeExternalUrl("data:text/html,")).toBe( + false, + ); + expect(isSafeExternalUrl("vscode://open?url=evil")).toBe(false); + expect(isSafeExternalUrl("ssh://user@host")).toBe(false); + expect(isSafeExternalUrl("ftp://example.com")).toBe(false); + }); + + it("blocks malformed input", () => { + expect(isSafeExternalUrl("")).toBe(false); + expect(isSafeExternalUrl("not a url")).toBe(false); + expect(isSafeExternalUrl("/etc/passwd")).toBe(false); + }); +}); + +describe("externalUrlLogLabel", () => { + it("returns only the scheme, never the full URL", () => { + expect(externalUrlLogLabel("https://example.com/path?token=secret")).toBe( + "https:", + ); + expect(externalUrlLogLabel("file:///etc/passwd")).toBe("file:"); + expect(externalUrlLogLabel("mailto:user@example.com")).toBe("mailto:"); + }); + + it("returns sentinels for empty and malformed input", () => { + expect(externalUrlLogLabel("")).toBe("empty"); + expect(externalUrlLogLabel("not a url")).toBe("malformed"); + }); +}); diff --git a/apps/desktop/src/main/lib/safe-url/safe-url.ts b/apps/desktop/src/main/lib/safe-url/safe-url.ts new file mode 100644 index 00000000000..3ac8fb349d5 --- /dev/null +++ b/apps/desktop/src/main/lib/safe-url/safe-url.ts @@ -0,0 +1,29 @@ +import { shell } from "electron"; +import { externalUrlLogLabel, isSafeExternalUrl } from "./scheme"; + +/** + * Wraps `shell.openExternal` with a scheme allowlist. Returns false and + * refuses to dispatch when the URL is not http(s)/mailto. Catches + * `shell.openExternal` rejections so callers can fire-and-forget without + * risking an unhandled rejection in the Electron main process. + */ +export async function safeOpenExternal(url: string): Promise { + if (!isSafeExternalUrl(url)) { + console.warn( + "[safeOpenExternal] blocked unsafe URL scheme:", + externalUrlLogLabel(url), + ); + return false; + } + try { + await shell.openExternal(url); + return true; + } catch (error) { + console.error( + "[safeOpenExternal] openExternal failed:", + externalUrlLogLabel(url), + error, + ); + return false; + } +} diff --git a/apps/desktop/src/main/lib/safe-url/scheme.ts b/apps/desktop/src/main/lib/safe-url/scheme.ts new file mode 100644 index 00000000000..0ca05a82aac --- /dev/null +++ b/apps/desktop/src/main/lib/safe-url/scheme.ts @@ -0,0 +1,24 @@ +/** + * Schemes safe to hand to Electron's `shell.openExternal`. + * Anything else (file:, javascript:, custom handlers, etc.) can execute + * binaries or scripts via the OS URL handler registry. + */ +const ALLOWED_SCHEMES = new Set(["http:", "https:", "mailto:"]); + +export function isSafeExternalUrl(url: string): boolean { + if (typeof url !== "string" || url.length === 0) return false; + try { + return ALLOWED_SCHEMES.has(new URL(url).protocol); + } catch { + return false; + } +} + +export function externalUrlLogLabel(url: string): string { + if (typeof url !== "string" || url.length === 0) return "empty"; + try { + return new URL(url).protocol || "unknown:"; + } catch { + return "malformed"; + } +} diff --git a/apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts b/apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts index f04d7d75a50..b4fb5cffe70 100644 --- a/apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts +++ b/apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts @@ -11,8 +11,7 @@ import { } from "../../terminal-host/client"; import type { ListSessionsResponse } from "../../terminal-host/types"; import { raceWithAbort, throwIfAborted } from "../abort"; -import { getDefaultShell } from "../env"; -import { buildTerminalEnv } from "../env-terminal"; +import { buildTerminalEnv, getDefaultShell } from "../env"; import { TerminalKilledError } from "../errors"; import { portManager } from "../port-manager"; import type { CreateSessionParams, SessionResult } from "../types"; @@ -30,8 +29,6 @@ import type { ColdRestoreInfo, SessionInfo } from "./types"; interface PendingCreateOrAttach { requestId: string; joinPending: boolean; - cols?: number; - rows?: number; abortController: AbortController; promise: Promise; } @@ -194,7 +191,7 @@ export class DaemonTerminalManager extends EventEmitter { session.lastActive = Date.now(); } - portManager.checkOutputForHint(data, paneId); + portManager.checkOutputForHint(data); this.historyManager.writeToHistory(paneId, data, () => this.sessions.get(paneId), ); @@ -302,52 +299,16 @@ export class DaemonTerminalManager extends EventEmitter { const requestId = params.requestId ?? `${paneId}:${Date.now()}`; const joinPending = params.joinPending ?? false; const pending = this.pendingSessions.get(paneId); - const requestHasExplicitSize = - Number.isInteger(params.cols) && - Number.isInteger(params.rows) && - (params.cols ?? 0) > 0 && - (params.rows ?? 0) > 0; if (pending) { - const pendingHasExplicitSize = - Number.isInteger(pending.cols) && - Number.isInteger(pending.rows) && - (pending.cols ?? 0) > 0 && - (pending.rows ?? 0) > 0; - const pendingSizeMatchesRequest = - pending.cols === params.cols && pending.rows === params.rows; - const shouldSupersedePending = - requestHasExplicitSize && - (!pendingHasExplicitSize || !pendingSizeMatchesRequest); - - if (shouldSupersedePending) { - if (DEBUG_TERMINAL) { - console.log( - "[DaemonTerminalManager] Superseding pending createOrAttach with explicit size", - { - paneId, - requestId, - pendingRequestId: pending.requestId, - pendingCols: pending.cols ?? null, - pendingRows: pending.rows ?? null, - nextCols: params.cols ?? null, - nextRows: params.rows ?? null, - pendingJoinPending: pending.joinPending, - joinPending, - }, - ); - } - pending.abortController.abort(); - this.pendingSessions.delete(paneId); - } else if ( + if ( pending.requestId === requestId || joinPending || pending.joinPending ) { return pending.promise; - } else { - pending.abortController.abort(); - this.pendingSessions.delete(paneId); } + pending.abortController.abort(); + this.pendingSessions.delete(paneId); } const abortController = new AbortController(); @@ -358,8 +319,6 @@ export class DaemonTerminalManager extends EventEmitter { const entry: PendingCreateOrAttach = { requestId, joinPending, - cols: params.cols, - rows: params.rows, abortController, promise, }; @@ -682,28 +641,15 @@ export class DaemonTerminalManager extends EventEmitter { } } - write(params: { - paneId: string; - data: string; - requireAck?: boolean; - interactive?: boolean; - }): Promise | void { - const { paneId, data, requireAck = false, interactive } = params; + write(params: { paneId: string; data: string }): void { + const { paneId, data } = params; const session = this.sessions.get(paneId); if (!session || !session.isAlive) { throw new Error(`Terminal session ${paneId} not found or not alive`); } - // Critical one-shot commands like workspace setup should fail loudly if - // the daemon didn't actually accept the write. - if (requireAck) { - return this.client - .write({ sessionId: paneId, data, interactive }) - .then(() => {}); - } - - this.client.writeNoAck({ sessionId: paneId, data, interactive }); + this.client.writeNoAck({ sessionId: paneId, data }); } ackColdRestore(paneId: string): void { diff --git a/apps/desktop/src/main/lib/terminal/port-manager.test.ts b/apps/desktop/src/main/lib/terminal/port-manager.test.ts new file mode 100644 index 00000000000..c70a09e6a88 --- /dev/null +++ b/apps/desktop/src/main/lib/terminal/port-manager.test.ts @@ -0,0 +1,261 @@ +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; +import type { TerminalSession } from "./types"; + +/** + * Regression tests for #3372 ("excessive lsof spawning"). + * + * Three behaviors the fix guarantees: + * 1. No scans run when there are no registered sessions (lifecycle). + * 2. At most one scan is in flight at any moment, even under a flood of + * hint-matching output (concurrency / coalescing). + * 3. stopPeriodicScan aborts any in-flight child so it cannot outlive us + * (no orphan lsof). + * + * The hint regexes that previously matched routine log noise ("port 22", + * trailing ":12345") must no longer trigger scans; the three "listening on โ€ฆ" + * patterns still must. + */ + +interface ScannerSpy { + getProcessTree: number; + getListeningPortsForPids: number; + inFlight: number; + maxInFlight: number; + lastSignal: AbortSignal | undefined; + aborted: number; +} + +const spy: ScannerSpy = { + getProcessTree: 0, + getListeningPortsForPids: 0, + inFlight: 0, + maxInFlight: 0, + lastSignal: undefined, + aborted: 0, +}; + +let lsofDelayMs = 0; + +mock.module("./port-scanner", () => ({ + getProcessTree: async (pid: number) => { + spy.getProcessTree++; + return [pid, pid + 1]; + }, + getListeningPortsForPids: async (_pids: number[], signal?: AbortSignal) => { + spy.getListeningPortsForPids++; + spy.inFlight++; + spy.maxInFlight = Math.max(spy.maxInFlight, spy.inFlight); + spy.lastSignal = signal; + try { + if (lsofDelayMs > 0) { + // Match production: getListeningPortsLsof catches all errors and + // returns []. If we get aborted we just resolve with [] early. + await new Promise((resolve) => { + const timer = setTimeout(resolve, lsofDelayMs); + signal?.addEventListener("abort", () => { + clearTimeout(timer); + spy.aborted++; + resolve(); + }); + }); + } + return []; + } finally { + spy.inFlight--; + } + }, +})); + +mock.module("../tree-kill", () => ({ + treeKillWithEscalation: async () => ({ success: true }), +})); + +const { portManager } = await import("./port-manager"); + +const HINT_DEBOUNCE_MS = 500; +const PAST_DEBOUNCE_MS = HINT_DEBOUNCE_MS + 50; + +const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); + +const makeSession = (paneId: string, pid: number): TerminalSession => + ({ paneId, isAlive: true, pty: { pid } }) as unknown as TerminalSession; + +// biome-ignore lint/suspicious/noExplicitAny: reach into private singleton state +const pmInternals = () => portManager as any; + +function resetSpy(): void { + spy.getProcessTree = 0; + spy.getListeningPortsForPids = 0; + spy.inFlight = 0; + spy.maxInFlight = 0; + spy.lastSignal = undefined; + spy.aborted = 0; + lsofDelayMs = 0; +} + +function resetManager(): void { + const internals = pmInternals(); + for (const paneId of Array.from(internals.sessions.keys())) { + portManager.unregisterSession(paneId); + } + for (const paneId of Array.from(internals.daemonSessions.keys())) { + portManager.unregisterDaemonSession(paneId); + } + portManager.stopPeriodicScan(); +} + +beforeEach(() => { + resetSpy(); + resetManager(); +}); + +afterEach(() => { + resetManager(); +}); + +describe("PortManager โ€” #3372 lifecycle (interval runs only with sessions)", () => { + it("forceScan is a no-op when no sessions are registered", async () => { + await portManager.forceScan(); + expect(spy.getProcessTree).toBe(0); + expect(spy.getListeningPortsForPids).toBe(0); + }); + + it("first registered session starts the interval; last unregister stops it", () => { + expect(pmInternals().scanInterval).toBeNull(); + + portManager.registerSession(makeSession("p1", 1000), "ws1"); + expect(pmInternals().scanInterval).not.toBeNull(); + + portManager.unregisterSession("p1"); + expect(pmInternals().scanInterval).toBeNull(); + }); + + it("daemon sessions control the interval the same way", () => { + portManager.upsertDaemonSession("pd1", "ws1", 2000); + expect(pmInternals().scanInterval).not.toBeNull(); + + portManager.unregisterDaemonSession("pd1"); + expect(pmInternals().scanInterval).toBeNull(); + }); + + it("mixed session types: interval stops only when all are gone", () => { + portManager.registerSession(makeSession("p1", 1000), "ws1"); + portManager.upsertDaemonSession("pd1", "ws2", 2000); + + portManager.unregisterSession("p1"); + expect(pmInternals().scanInterval).not.toBeNull(); + + portManager.unregisterDaemonSession("pd1"); + expect(pmInternals().scanInterval).toBeNull(); + }); + + it("re-registering after idle restarts the interval", () => { + portManager.registerSession(makeSession("p1", 1000), "ws1"); + portManager.unregisterSession("p1"); + expect(pmInternals().scanInterval).toBeNull(); + + portManager.registerSession(makeSession("p2", 1001), "ws1"); + expect(pmInternals().scanInterval).not.toBeNull(); + }); +}); + +describe("PortManager โ€” #3372 concurrency (at most one lsof in flight)", () => { + it("bulk scan batches every session into a single lsof call", async () => { + for (let i = 0; i < 10; i++) { + portManager.registerSession(makeSession(`p${i}`, 1000 + i), `ws${i}`); + } + await portManager.forceScan(); + + expect(spy.getListeningPortsForPids).toBe(1); + expect(spy.maxInFlight).toBe(1); + }); + + it("a flood of hints coalesces into one follow-up, never concurrent", async () => { + lsofDelayMs = 30; + portManager.registerSession(makeSession("p1", 1000), "ws1"); + + const firstScan = portManager.forceScan(); + + // 100 hints while the first scan is running โ€” all on the hot path. + for (let i = 0; i < 100; i++) { + portManager.checkOutputForHint("listening on port 3000\n"); + } + + await firstScan; + await sleep(PAST_DEBOUNCE_MS); // let the single debounced follow-up run + + expect(spy.maxInFlight).toBe(1); + // Exact โ€” one initial scan + one coalesced follow-up, never more, never fewer. + expect(spy.getListeningPortsForPids).toBe(2); + }); +}); + +describe("PortManager โ€” #3372 hint regex narrowing", () => { + beforeEach(() => { + portManager.registerSession(makeSession("p1", 1000), "ws1"); + resetSpy(); + }); + + it("does NOT scan on a bare 'port 22' (old loose pattern)", async () => { + portManager.checkOutputForHint("connection reached port 22\n"); + await sleep(PAST_DEBOUNCE_MS); + expect(spy.getListeningPortsForPids).toBe(0); + }); + + it("does NOT scan on a trailing ':12345' (old loose pattern)", async () => { + portManager.checkOutputForHint("commit abc123def:12345\n"); + await sleep(PAST_DEBOUNCE_MS); + expect(spy.getListeningPortsForPids).toBe(0); + }); + + it("DOES scan on 'listening on port 3000'", async () => { + portManager.checkOutputForHint("listening on port 3000\n"); + await sleep(PAST_DEBOUNCE_MS); + expect(spy.getListeningPortsForPids).toBe(1); + }); + + it("DOES scan on 'server running at http://localhost:3000'", async () => { + portManager.checkOutputForHint("server running at http://localhost:3000\n"); + await sleep(PAST_DEBOUNCE_MS); + expect(spy.getListeningPortsForPids).toBe(1); + }); + + it("DOES scan on 'ready on http://localhost:5173' (Vite-style)", async () => { + portManager.checkOutputForHint("ready on http://localhost:5173\n"); + await sleep(PAST_DEBOUNCE_MS); + expect(spy.getListeningPortsForPids).toBe(1); + }); +}); + +describe("PortManager โ€” #3372 teardown (no orphan children)", () => { + it("stopPeriodicScan aborts any in-flight lsof", async () => { + lsofDelayMs = 200; + portManager.registerSession(makeSession("p1", 1000), "ws1"); + + const scanPromise = portManager.forceScan(); + // Wait for the lsof stub to start. + await sleep(10); + expect(spy.inFlight).toBe(1); + + portManager.stopPeriodicScan(); + + // The promise resolves (port-scanner swallows its own errors). + await scanPromise; + + expect(spy.aborted).toBeGreaterThanOrEqual(1); + expect(spy.inFlight).toBe(0); + }); + + it("in-flight lsof receives the AbortSignal from the manager", async () => { + lsofDelayMs = 50; + portManager.registerSession(makeSession("p1", 1000), "ws1"); + + const scanPromise = portManager.forceScan(); + await sleep(10); + + expect(spy.lastSignal).toBeDefined(); + expect(spy.lastSignal?.aborted).toBe(false); + + await scanPromise; + }); +}); diff --git a/apps/desktop/src/main/lib/terminal/port-manager.ts b/apps/desktop/src/main/lib/terminal/port-manager.ts index 4b7fdaf8e7b..eca34d43ac9 100644 --- a/apps/desktop/src/main/lib/terminal/port-manager.ts +++ b/apps/desktop/src/main/lib/terminal/port-manager.ts @@ -19,16 +19,16 @@ const IGNORED_PORTS = new Set([22, 80, 443, 5432, 3306, 6379, 27017]); /** * Check if terminal output contains hints that a port may have been opened. - * Common patterns from dev servers, test frameworks, etc. + * Restricted to phrases that strongly imply a server just started listening; + * looser patterns like a bare "port 22" or trailing ":12345" are omitted + * because they match routine log output (ssh banners, timestamps, etc.) and + * triggered excessive lsof scans โ€” see issue #3372. */ function containsPortHint(data: string): boolean { - // Common patterns: "listening on port X", "server started on :X", etc. const portPatterns = [ /listening\s+on\s+(?:port\s+)?(\d+)/i, /server\s+(?:started|running)\s+(?:on|at)\s+(?:http:\/\/)?(?:localhost|127\.0\.0\.1|0\.0\.0\.0)?:?(\d+)/i, /ready\s+on\s+(?:http:\/\/)?(?:localhost|127\.0\.0\.1|0\.0\.0\.0)?:?(\d+)/i, - /port\s+(\d+)/i, - /:(\d{4,5})\s*$/, ]; return portPatterns.some((pattern) => pattern.test(data)); } @@ -62,19 +62,19 @@ class PortManager extends EventEmitter { /** Daemon-mode sessions: paneId โ†’ { workspaceId, pid } */ private daemonSessions = new Map(); private scanInterval: ReturnType | null = null; - private pendingHintScans = new Map>(); + private hintScanTimeout: ReturnType | null = null; private isScanning = false; - - constructor() { - super(); - this.startPeriodicScan(); - } + /** Set when a hint arrives during a scan; triggers one follow-up scan. */ + private scanRequested = false; + /** Aborts any in-flight scan children (lsof/netstat) on teardown. */ + private scanAbort: AbortController | null = null; /** * Register a terminal session for port scanning */ registerSession(session: TerminalSession, workspaceId: string): void { this.sessions.set(session.paneId, { session, workspaceId }); + this.ensurePeriodicScanRunning(); } /** @@ -83,7 +83,7 @@ class PortManager extends EventEmitter { unregisterSession(paneId: string): void { this.sessions.delete(paneId); this.removePortsForPane(paneId); - this.clearPendingHintScan(paneId); + this.stopPeriodicScanIfIdle(); } /** @@ -97,6 +97,7 @@ class PortManager extends EventEmitter { pid: number | null, ): void { this.daemonSessions.set(paneId, { workspaceId, pid }); + this.ensurePeriodicScanRunning(); } /** @@ -105,17 +106,22 @@ class PortManager extends EventEmitter { unregisterDaemonSession(paneId: string): void { this.daemonSessions.delete(paneId); this.removePortsForPane(paneId); - this.clearPendingHintScan(paneId); + this.stopPeriodicScanIfIdle(); } - checkOutputForHint(data: string, paneId: string): void { + checkOutputForHint(data: string): void { if (!containsPortHint(data)) return; - this.scheduleHintScan(paneId); + this.scheduleHintScan(); + } + + private hasAnySessions(): boolean { + return this.sessions.size > 0 || this.daemonSessions.size > 0; } - private startPeriodicScan(): void { + private ensurePeriodicScanRunning(): void { if (this.scanInterval) return; + this.scanAbort = new AbortController(); this.scanInterval = setInterval(() => { this.scanAllSessions().catch((error) => { console.error("[PortManager] Scan error:", error); @@ -126,89 +132,42 @@ class PortManager extends EventEmitter { this.scanInterval.unref(); } + private stopPeriodicScanIfIdle(): void { + if (!this.hasAnySessions()) this.stopPeriodicScan(); + } + stopPeriodicScan(): void { if (this.scanInterval) { clearInterval(this.scanInterval); this.scanInterval = null; } - for (const timeout of this.pendingHintScans.values()) { - clearTimeout(timeout); + if (this.hintScanTimeout) { + clearTimeout(this.hintScanTimeout); + this.hintScanTimeout = null; } - this.pendingHintScans.clear(); - } - private clearPendingHintScan(paneId: string): void { - const pendingTimeout = this.pendingHintScans.get(paneId); - if (pendingTimeout) { - clearTimeout(pendingTimeout); - this.pendingHintScans.delete(paneId); + // Kill any in-flight lsof/netstat so it can't outlive us. + if (this.scanAbort) { + this.scanAbort.abort(); + this.scanAbort = null; } - } - - private scheduleHintScan(paneId: string): void { - this.clearPendingHintScan(paneId); - - const timeout = setTimeout(() => { - this.pendingHintScans.delete(paneId); - this.scanPane(paneId).catch(() => {}); - }, HINT_SCAN_DELAY_MS); - // Don't keep Electron alive just for port scanning - timeout.unref(); - this.pendingHintScans.set(paneId, timeout); + this.scanRequested = false; } - private async scanPidTreeAndUpdate({ - paneId, - workspaceId, - pid, - errorContext, - }: { - paneId: string; - workspaceId: string; - pid: number; - errorContext: string; - }): Promise { - try { - const pids = await getProcessTree(pid); - if (pids.length === 0) { - this.removePortsForPane(paneId); - return; - } - - const portInfos = await getListeningPortsForPids(pids); - this.updatePortsForPane({ paneId, workspaceId, portInfos }); - } catch (error) { - console.error(`[PortManager] Error scanning ${errorContext}:`, error); - } - } - - private async scanPane(paneId: string): Promise { - const registered = this.sessions.get(paneId); - if (registered) { - const { session, workspaceId } = registered; - if (!session.isAlive) return; - await this.scanPidTreeAndUpdate({ - paneId, - workspaceId, - pid: session.pty.pid, - errorContext: `pane ${paneId}`, - }); - return; - } + /** + * Debounce hint-triggered scans into a single follow-up bulk scan. + * Hints arrive on every PTY data chunk; we only need one scan per burst. + */ + private scheduleHintScan(): void { + if (this.hintScanTimeout) return; - const daemonSession = this.daemonSessions.get(paneId); - if (daemonSession) { - const { workspaceId, pid } = daemonSession; - if (pid === null) return; - await this.scanPidTreeAndUpdate({ - paneId, - workspaceId, - pid, - errorContext: `daemon pane ${paneId}`, - }); - } + this.hintScanTimeout = setTimeout(() => { + this.hintScanTimeout = null; + this.scanAllSessions().catch(() => {}); + }, HINT_SCAN_DELAY_MS); + this.hintScanTimeout.unref(); } private createScanState(): ScanState { @@ -307,7 +266,10 @@ class PortManager extends EventEmitter { const allPidList = Array.from(allPids); if (allPidList.length === 0) return portsByPane; - const portInfos = await getListeningPortsForPids(allPidList); + const portInfos = await getListeningPortsForPids( + allPidList, + this.scanAbort?.signal, + ); for (const info of portInfos) { const owner = pidOwnerMap.get(info.pid); if (!owner) continue; @@ -353,7 +315,12 @@ class PortManager extends EventEmitter { } private async scanAllSessions(): Promise { - if (this.isScanning) return; + if (this.isScanning) { + // A hint or tick fired mid-scan; queue exactly one follow-up. + this.scanRequested = true; + return; + } + if (!this.hasAnySessions()) return; this.isScanning = true; try { @@ -375,6 +342,11 @@ class PortManager extends EventEmitter { } finally { this.isScanning = false; } + + if (this.scanRequested && this.hasAnySessions()) { + this.scanRequested = false; + await this.scanAllSessions(); + } } private updatePortsForPane({ diff --git a/apps/desktop/src/main/lib/terminal/port-scanner.ts b/apps/desktop/src/main/lib/terminal/port-scanner.ts index 49247491d46..748cf187961 100644 --- a/apps/desktop/src/main/lib/terminal/port-scanner.ts +++ b/apps/desktop/src/main/lib/terminal/port-scanner.ts @@ -1,9 +1,49 @@ -import { exec } from "node:child_process"; +import { execFile } from "node:child_process"; import os from "node:os"; import { promisify } from "node:util"; import pidtree from "pidtree"; -const execAsync = promisify(exec); +const execFileAsync = promisify(execFile); + +/** + * Run execFile and tolerate a plain non-zero exit by returning its stdout. + * lsof exits 1 when no PIDs match the filter โ€” a legitimate "empty" result. + * Aborts, timeouts, and signal-kills are NOT tolerated: partial stdout from a + * killed child is not a trustworthy snapshot, so rethrow and let the caller's + * outer catch turn it into `[]`. + */ +async function runTolerant( + file: string, + args: string[], + options: { maxBuffer: number; timeout: number; signal?: AbortSignal }, +): Promise { + try { + const { stdout } = await execFileAsync(file, args, options); + return stdout; + } catch (err) { + if (err && typeof err === "object") { + const execErr = err as { + stdout?: string | Buffer; + code?: unknown; + killed?: boolean; + signal?: unknown; + name?: string; + }; + if ( + execErr.name === "AbortError" || + execErr.code === "ABORT_ERR" || + execErr.killed || + execErr.signal + ) { + throw err; + } + if ("stdout" in execErr) { + return String(execErr.stdout ?? ""); + } + } + throw err; + } +} /** Timeout for shell commands to prevent hanging (ms) */ const EXEC_TIMEOUT_MS = 5000; @@ -33,16 +73,17 @@ export async function getProcessTree(pid: number): Promise { */ export async function getListeningPortsForPids( pids: number[], + signal?: AbortSignal, ): Promise { if (pids.length === 0) return []; const platform = os.platform(); if (platform === "darwin" || platform === "linux") { - return getListeningPortsLsof(pids); + return getListeningPortsLsof(pids, signal); } if (platform === "win32") { - return getListeningPortsWindows(pids); + return getListeningPortsWindows(pids, signal); } return []; @@ -51,7 +92,10 @@ export async function getListeningPortsForPids( /** * macOS/Linux implementation using lsof */ -async function getListeningPortsLsof(pids: number[]): Promise { +async function getListeningPortsLsof( + pids: number[], + signal?: AbortSignal, +): Promise { try { const pidArg = pids.join(","); const pidSet = new Set(pids); @@ -62,9 +106,10 @@ async function getListeningPortsLsof(pids: number[]): Promise { // -n: don't resolve hostnames // Note: lsof may ignore -p filter if PIDs don't exist or have no matches, // so we must validate PIDs in the output against our requested set - const { stdout: output } = await execAsync( - `lsof -p ${pidArg} -iTCP -sTCP:LISTEN -P -n 2>/dev/null || true`, - { maxBuffer: 10 * 1024 * 1024, timeout: EXEC_TIMEOUT_MS }, + const output = await runTolerant( + "lsof", + ["-p", pidArg, "-iTCP", "-sTCP:LISTEN", "-P", "-n"], + { maxBuffer: 10 * 1024 * 1024, timeout: EXEC_TIMEOUT_MS, signal }, ); if (!output.trim()) return []; @@ -116,11 +161,15 @@ async function getListeningPortsLsof(pids: number[]): Promise { /** * Windows implementation using netstat */ -async function getListeningPortsWindows(pids: number[]): Promise { +async function getListeningPortsWindows( + pids: number[], + signal?: AbortSignal, +): Promise { try { - const { stdout: output } = await execAsync("netstat -ano", { + const { stdout: output } = await execFileAsync("netstat", ["-ano"], { maxBuffer: 10 * 1024 * 1024, timeout: EXEC_TIMEOUT_MS, + signal, }); const pidSet = new Set(pids); @@ -149,7 +198,7 @@ async function getListeningPortsWindows(pids: number[]): Promise { const nameResults = await Promise.all( pidsToLookup.map(async (pid) => ({ pid, - name: await getProcessNameWindows(pid), + name: await getProcessNameWindows(pid, signal), })), ); for (const { pid, name } of nameResults) { @@ -195,11 +244,15 @@ async function getListeningPortsWindows(pids: number[]): Promise { /** * Get process name for a PID on Windows */ -async function getProcessNameWindows(pid: number): Promise { +async function getProcessNameWindows( + pid: number, + signal?: AbortSignal, +): Promise { try { - const { stdout: output } = await execAsync( - `wmic process where processid=${pid} get name 2>nul`, - { timeout: EXEC_TIMEOUT_MS }, + const { stdout: output } = await execFileAsync( + "wmic", + ["process", "where", `processid=${pid}`, "get", "name"], + { timeout: EXEC_TIMEOUT_MS, signal }, ); const lines = output.trim().split("\n"); if (lines.length >= 2) { @@ -209,67 +262,13 @@ async function getProcessNameWindows(pid: number): Promise { } catch { // wmic is deprecated, try PowerShell as fallback try { - const { stdout: output } = await execAsync( - `powershell -Command "(Get-Process -Id ${pid}).ProcessName"`, - { timeout: EXEC_TIMEOUT_MS }, + const { stdout: output } = await execFileAsync( + "powershell", + ["-Command", `(Get-Process -Id ${pid}).ProcessName`], + { timeout: EXEC_TIMEOUT_MS, signal }, ); return output.trim() || "unknown"; } catch {} } return "unknown"; } - -/** - * Get process name for a PID (cross-platform) - */ -export async function getProcessName(pid: number): Promise { - const platform = os.platform(); - - if (platform === "win32") { - return getProcessNameWindows(pid); - } - - // macOS/Linux - try { - const { stdout: output } = await execAsync( - `ps -p ${pid} -o comm= 2>/dev/null || true`, - { timeout: EXEC_TIMEOUT_MS }, - ); - const name = output.trim(); - // On macOS, comm may be truncated. The full path can be gotten with -o command= - // but comm is usually sufficient for display purposes - return name || "unknown"; - } catch { - return "unknown"; - } -} - -/** - * Full argv of a process (space-joined). Useful when `comm` alone is - * ambiguous โ€” e.g. the `claude` / `codex` CLIs often appear under - * `comm=node` because they are spawned as `node /path/to/bin/claude โ€ฆ`. - */ -export async function getProcessCommand(pid: number): Promise { - const platform = os.platform(); - if (platform === "win32") { - try { - const { stdout } = await execAsync( - `wmic process where processid=${pid} get commandline 2>nul`, - { timeout: EXEC_TIMEOUT_MS }, - ); - const lines = stdout.trim().split("\n"); - return lines.length >= 2 ? lines.slice(1).join(" ").trim() : ""; - } catch { - return ""; - } - } - try { - const { stdout } = await execAsync( - `ps -p ${pid} -o args= 2>/dev/null || true`, - { timeout: EXEC_TIMEOUT_MS }, - ); - return stdout.trim(); - } catch { - return ""; - } -} diff --git a/apps/desktop/src/main/terminal-host/session-shell-ready.test.ts b/apps/desktop/src/main/terminal-host/session-shell-ready.test.ts index 6c79e31d161..6d5876eb8fe 100644 --- a/apps/desktop/src/main/terminal-host/session-shell-ready.test.ts +++ b/apps/desktop/src/main/terminal-host/session-shell-ready.test.ts @@ -121,39 +121,22 @@ function spawnAndReady( // Tests // ============================================================================= -describe("Session shell-ready: write buffering", () => { - it("buffers non-interactive writes while shell is pending and flushes after marker", () => { +describe("Session shell-ready: write pass-through", () => { + it("passes writes through immediately while shell is pending (#3478)", () => { const { session, proc } = createTestSession("/bin/zsh"); spawnAndReady(session, proc); - // Preset/programmatic writes before shell is ready โ€” should be buffered - session.write("echo hello\n"); - session.write("echo world\n"); + // User keystrokes answering a shell-init prompt (e.g. fnm's + // "install missing Node version?") must reach the PTY without + // waiting for OSC 133;A. + session.write("y\n"); + session.write("echo ready\n"); - // No write frames should have been sent yet - expect(getWrittenData(proc)).toEqual([]); + expect(getWrittenData(proc)).toEqual(["y\n", "echo ready\n"]); - // Shell emits the ready marker + // The ready marker arriving later must not re-emit anything. sendData(proc, `direnv output...${SHELL_READY_MARKER}prompt$ `); - - // Now the buffered writes should be flushed in order - const writes = getWrittenData(proc); - expect(writes).toEqual(["echo hello\n", "echo world\n"]); - }); - - it("forwards interactive writes directly to PTY while shell is pending", () => { - const { session, proc } = createTestSession("/bin/zsh"); - spawnAndReady(session, proc); - - // Interactive write (user keyboard input) โ€” forwarded immediately - session.write("y", { interactive: true }); - - expect(getWrittenData(proc)).toEqual(["y"]); - - // Shell emits the ready marker โ€” interactive writes continue to work - sendData(proc, `direnv output...${SHELL_READY_MARKER}prompt$ `); - session.write("n", { interactive: true }); - expect(getWrittenData(proc)).toEqual(["y", "n"]); + expect(getWrittenData(proc)).toEqual(["y\n", "echo ready\n"]); }); it("passes writes through immediately for unsupported shells (sh)", () => { @@ -183,45 +166,28 @@ describe("Session shell-ready: write buffering", () => { session.write("\x1b[?62;4;9;22c"); // Simulate cursor position report session.write("\x1b[1;1R"); - // Queue a real preset command + // Regular command also arriving during pending session.write("claude\n"); - // Only the preset command should be in the queue - expect(getWrittenData(proc)).toEqual([]); + // Escape sequences are dropped; the command passes through. + expect(getWrittenData(proc)).toEqual(["claude\n"]); sendData(proc, SHELL_READY_MARKER); - // Only the command should flush โ€” escape sequences dropped + // Nothing new to emit after the marker. expect(getWrittenData(proc)).toEqual(["claude\n"]); }); - it("drops escape sequences even for interactive writes during pending state", () => { - const { session, proc } = createTestSession("/bin/zsh"); - spawnAndReady(session, proc); - - // Escape sequences are always dropped during pending, even if interactive - session.write("\x1b[?62;4;9;22c", { interactive: true }); - expect(getWrittenData(proc)).toEqual([]); - - // Regular interactive write goes through - session.write("y", { interactive: true }); - expect(getWrittenData(proc)).toEqual(["y"]); - }); - - it("flushes buffered writes on subprocess exit", async () => { + it("forwards escape sequences once shell is ready", () => { const { session, proc } = createTestSession("/bin/zsh"); spawnAndReady(session, proc); - session.write("echo delayed\n"); - expect(getWrittenData(proc)).toEqual([]); - - // Simulate exit which resolves shell readiness as timed_out - sendExit(proc, 0); - proc.emit("exit", 0); + sendData(proc, SHELL_READY_MARKER); - // Buffered write should now be flushed - const writes = getWrittenData(proc); - expect(writes).toEqual(["echo delayed\n"]); + // After the marker, escape sequences are no longer stale init noise, + // so they pass through (e.g. user pressing arrow keys). + session.write("\x1b[A"); + expect(getWrittenData(proc)).toEqual(["\x1b[A"]); }); }); @@ -250,16 +216,16 @@ describe("Session shell-ready: marker detection", () => { // Send first half โ€” shell should still be pending sendData(proc, `output${firstHalf}`); - // Interactive write forwarded; non-interactive buffered (still pending) - session.write("buffered\n"); - session.write("y", { interactive: true }); - expect(getWrittenData(proc)).toEqual(["y"]); + // Writes pass through even while pending + session.write("first\n"); + expect(getWrittenData(proc)).toEqual(["first\n"]); // Send second half โ€” should complete the marker sendData(proc, `${secondHalf}prompt`); - // Now the buffered write flushes - expect(getWrittenData(proc)).toEqual(["y", "buffered\n"]); + // Post-marker writes still pass through + session.write("second\n"); + expect(getWrittenData(proc)).toEqual(["first\n", "second\n"]); }); it("handles marker at start of data frame", () => { @@ -290,13 +256,13 @@ describe("Session shell-ready: marker detection", () => { const partialMarker = SHELL_READY_MARKER.slice(0, 5); sendData(proc, `${partialMarker}not-a-marker`); - // Shell should still be pending โ€” non-interactive write buffered - session.write("buffered\n"); - expect(getWrittenData(proc)).toEqual([]); + // Writes pass through regardless of marker state. + session.write("first\n"); + expect(getWrittenData(proc)).toEqual(["first\n"]); - // Now send the real marker + // Now send the real marker โ€” no backlog to flush. sendData(proc, SHELL_READY_MARKER); - expect(getWrittenData(proc)).toEqual(["buffered\n"]); + expect(getWrittenData(proc)).toEqual(["first\n"]); }); // Wrappers now emit both the legacy OSC 777 and the current OSC 133;A in @@ -310,45 +276,46 @@ describe("Session shell-ready: marker detection", () => { const { session, proc } = createTestSession("/bin/zsh"); spawnAndReady(session, proc); - session.write("buffered\n"); - expect(getWrittenData(proc)).toEqual([]); - const COMBINED_MARKER = "\x1b]777;superset-shell-ready\x07\x1b]133;A\x07"; sendData(proc, `direnv output...${COMBINED_MARKER}prompt$ `); - expect(getWrittenData(proc)).toEqual(["buffered\n"]); + // Writes after the combined marker pass through (marker detection + // guards future behaviors that may depend on the ready state). + session.write("test\n"); + expect(getWrittenData(proc)).toEqual(["test\n"]); }); }); describe("Session shell-ready: kill/exit before readiness", () => { - it("flushes queue when subprocess exits before marker", () => { + it("accepts writes when subprocess exits before marker", () => { const { session, proc } = createTestSession("/bin/bash"); spawnAndReady(session, proc); + // Writes pass through even during pending. session.write("echo pending\n"); - expect(getWrittenData(proc)).toEqual([]); + expect(getWrittenData(proc)).toEqual(["echo pending\n"]); - // Subprocess exits without ever sending the marker + // Subprocess exits without ever sending the marker โ€” no replay, + // no duplicate writes. sendExit(proc, 1); proc.emit("exit", 1); - // Queue should be flushed on exit expect(getWrittenData(proc)).toEqual(["echo pending\n"]); }); - it("resolves readiness when session is killed", () => { + it("accepts writes when session is killed before marker", () => { const { session, proc } = createTestSession("/bin/zsh"); spawnAndReady(session, proc); session.write("echo pending\n"); - expect(getWrittenData(proc)).toEqual([]); + expect(getWrittenData(proc)).toEqual(["echo pending\n"]); - // Kill triggers termination โ†’ subprocess exit โ†’ readiness resolved + // Kill triggers termination โ†’ subprocess exit โ†’ readiness resolved. + // No buffered replay on exit. session.kill(); sendExit(proc, 0); proc.emit("exit", 0); - // Writes should be flushed expect(getWrittenData(proc)).toEqual(["echo pending\n"]); }); }); @@ -360,24 +327,16 @@ describe("Session shell-ready: supported shells", () => { "/bin/bash", "/usr/local/bin/fish", ]) { - it(`buffers non-interactive writes for supported shell: ${shell}`, () => { + it(`passes writes through while pending for supported shell: ${shell}`, () => { const { session, proc } = createTestSession(shell); spawnAndReady(session, proc); session.write("test\n"); - expect(getWrittenData(proc)).toEqual([]); + expect(getWrittenData(proc)).toEqual(["test\n"]); sendData(proc, SHELL_READY_MARKER); expect(getWrittenData(proc)).toEqual(["test\n"]); }); - - it(`forwards interactive writes for supported shell: ${shell}`, () => { - const { session, proc } = createTestSession(shell); - spawnAndReady(session, proc); - - session.write("y", { interactive: true }); - expect(getWrittenData(proc)).toEqual(["y"]); - }); } for (const shell of ["/bin/sh", "/bin/ksh", "/usr/bin/dash"]) { diff --git a/apps/desktop/src/main/terminal-host/session.ts b/apps/desktop/src/main/terminal-host/session.ts index 4359a8248ec..32a1f5773be 100644 --- a/apps/desktop/src/main/terminal-host/session.ts +++ b/apps/desktop/src/main/terminal-host/session.ts @@ -115,9 +115,9 @@ const EMULATOR_WRITE_COALESCE_ENABLED = /** * Shell readiness lifecycle: - * - `pending` โ€” shell is initializing; user writes are buffered, escape sequences dropped - * - `ready` โ€” marker detected; buffered writes have been flushed - * - `timed_out` โ€” marker never arrived within timeout; writes unblocked + * - `pending` โ€” shell is initializing; escape sequences dropped, other writes pass through + * - `ready` โ€” marker detected; writes pass through + * - `timed_out` โ€” marker never arrived within timeout; writes pass through * - `unsupported` โ€” shell has no marker (sh, ksh); writes pass through from the start */ type ShellReadyState = "pending" | "ready" | "timed_out" | "unsupported"; @@ -191,11 +191,12 @@ export class Session { private ptyReadyPromise: Promise; private ptyReadyResolve: (() => void) | null = null; - // Shell readiness โ€” gates write() until the shell's first prompt. + // Shell readiness โ€” tracks the shell's init lifecycle. User input and + // preset commands pass through regardless; only stale xterm terminal-query + // responses (DA/DSR) are filtered while `pending`. // See ShellReadyState for lifecycle docs. private shellReadyState: ShellReadyState; private shellReadyTimeoutId: ReturnType | null = null; - private preReadyStdinQueue: string[] = []; // OSC 133;A scanner state โ€” shared with v2 host-service via @superset/shared private scanState: ShellReadyScanState = createScanState(); @@ -918,29 +919,23 @@ export class Session { /** * Write data to the PTY's stdin. * - * While the shell is initializing (`pending` state), writes are triaged: - * - **Escape sequences** (`\x1b`-prefixed) are dropped. These are stale - * responses from the renderer's xterm to terminal queries the shell - * sent during startup (DA, DSR). If queued and flushed later they - * appear as typed text like `?62;4;9;22c`. - * - **Interactive writes** (user keyboard input, `interactive: true`) are - * forwarded directly so prompts during initialization (e.g. oh-my-zsh - * update confirmation) can receive user input normally. - * - **Everything else** (preset/programmatic commands) is buffered and - * flushed in FIFO order once readiness resolves, ensuring they run at - * the first shell prompt rather than mid-initialization. + * Escape-sequence responses (`\x1b`-prefixed) are dropped while the shell + * is still initializing โ€” these are stale DA/DSR replies from the + * renderer's xterm to terminal queries the shell sent during startup. If + * forwarded, they appear as typed text like `?62;4;9;22c` at the shell + * prompt. The headless emulator answers those queries directly (see + * constructor), so dropping the renderer's duplicate is safe. + * + * All other data โ€” user keystrokes and preset commands alike โ€” passes + * through immediately. Buffering here previously froze workspaces when + * shell init commands (e.g. fnm's `use-on-cd` hook) opened an interactive + * prompt before the OSC 133;A marker fired. See #3478. */ write(data: string, options?: { interactive?: boolean }): void { if (!this.subprocess || !this.subprocessReady) { throw new Error("PTY not spawned"); } - if (this.shellReadyState === "pending") { - if (data.startsWith("\x1b")) return; - if (options?.interactive) { - this.sendWriteToSubprocess(data); - } else { - this.preReadyStdinQueue.push(data); - } + if (this.shellReadyState === "pending" && data.startsWith("\x1b")) { return; } this.sendWriteToSubprocess(data); @@ -1074,7 +1069,6 @@ export class Session { clearTimeout(this.shellReadyTimeoutId); this.shellReadyTimeoutId = null; } - this.preReadyStdinQueue = []; this.scanState = createScanState(); this.subprocessStdinQueue = []; this.subprocessStdinQueuedBytes = 0; @@ -1114,8 +1108,7 @@ export class Session { /** * Transition out of `pending`. Flushes any partially-matched marker - * bytes as terminal output (they weren't a real marker), then sends - * all buffered stdin writes to the PTY in order. Idempotent. + * bytes as terminal output (they weren't a real marker). Idempotent. */ private resolveShellReady(state: "ready" | "timed_out"): void { if (this.shellReadyState !== "pending") return; @@ -1131,12 +1124,6 @@ export class Session { this.scanState.heldBytes = ""; } this.scanState.matchPos = 0; - // Flush queued writes in FIFO order - const queue = this.preReadyStdinQueue; - this.preReadyStdinQueue = []; - for (const data of queue) { - this.sendWriteToSubprocess(data); - } } /** diff --git a/apps/desktop/src/renderer/components/MarkdownRenderer/components/TipTapMarkdownRenderer/components/EditableCodeBlockView/EditableCodeBlockView.tsx b/apps/desktop/src/renderer/components/MarkdownRenderer/components/TipTapMarkdownRenderer/components/EditableCodeBlockView/EditableCodeBlockView.tsx index 2e0a3e78a09..43bd13de0b5 100644 --- a/apps/desktop/src/renderer/components/MarkdownRenderer/components/TipTapMarkdownRenderer/components/EditableCodeBlockView/EditableCodeBlockView.tsx +++ b/apps/desktop/src/renderer/components/MarkdownRenderer/components/TipTapMarkdownRenderer/components/EditableCodeBlockView/EditableCodeBlockView.tsx @@ -1,3 +1,4 @@ +import { mermaid } from "@streamdown/mermaid"; import { DropdownMenu, DropdownMenuContent, @@ -7,12 +8,22 @@ import { import type { NodeViewProps } from "@tiptap/react"; import { NodeViewContent, NodeViewWrapper } from "@tiptap/react"; import { useState } from "react"; -import { HiCheck, HiChevronDown, HiOutlineClipboard } from "react-icons/hi2"; +import { + HiCheck, + HiChevronDown, + HiOutlineClipboard, + HiOutlineCodeBracket, + HiOutlineEye, +} from "react-icons/hi2"; import { useCopyToClipboard } from "renderer/hooks/useCopyToClipboard"; import { FILE_VIEW_CODE_BLOCK_LANGUAGES, getCodeBlockLanguageLabel, } from "renderer/lib/tiptap/code-block-languages"; +import { useTheme } from "renderer/stores"; +import { Streamdown } from "streamdown"; + +const mermaidPlugins = { mermaid }; export function EditableCodeBlockView({ node, @@ -20,6 +31,8 @@ export function EditableCodeBlockView({ extension, }: NodeViewProps) { const [menuOpen, setMenuOpen] = useState(false); + const theme = useTheme(); + const isDark = theme?.type !== "light"; const attrs = node.attrs as { language?: string }; const htmlAttrs = extension.options.HTMLAttributes as { class?: string }; @@ -30,6 +43,16 @@ export function EditableCodeBlockView({ currentLanguage, ); + const isMermaid = currentLanguage === "mermaid"; + const mermaidSource = node.textContent; + const mermaidHasContent = mermaidSource.trim().length > 0; + const [mermaidMode, setMermaidMode] = useState<"preview" | "source">(() => + mermaidHasContent ? "preview" : "source", + ); + const showMermaidPreview = + isMermaid && mermaidMode === "preview" && mermaidHasContent; + const showMermaidToggle = isMermaid && mermaidHasContent; + const { copyToClipboard, copied } = useCopyToClipboard(); const handleCopy = () => { copyToClipboard(node.textContent); @@ -41,15 +64,43 @@ export function EditableCodeBlockView({ }; return ( - +
+ {showMermaidToggle && ( + + )}
- + {showMermaidPreview && ( +
+ + {`\`\`\`\`mermaid\n${mermaidSource}\n\`\`\`\``} + +
+ )} + +
diff --git a/apps/desktop/src/renderer/hotkeys/registry.ts b/apps/desktop/src/renderer/hotkeys/registry.ts index d36558c9a10..24df63b4383 100644 --- a/apps/desktop/src/renderer/hotkeys/registry.ts +++ b/apps/desktop/src/renderer/hotkeys/registry.ts @@ -186,14 +186,16 @@ export const HOTKEYS_REGISTRY = { label: "Toggle Changes Tab", category: "Layout", }, - TOGGLE_EXPAND_SIDEBAR: { + OPEN_DIFF_VIEWER: { key: { mac: "meta+shift+l", windows: "ctrl+shift+alt+l", linux: "ctrl+shift+alt+l", }, - label: "Toggle Expand Sidebar", + label: "Open Diff Viewer", category: "Layout", + description: + "Open the diff viewer in a new tab, or focus the existing diff viewer", }, TOGGLE_WORKSPACE_SIDEBAR: { key: { mac: "meta+b", windows: "ctrl+shift+b", linux: "ctrl+shift+b" }, diff --git a/apps/desktop/src/renderer/lib/dev-chat.ts b/apps/desktop/src/renderer/lib/dev-chat.ts index b15e0897fd6..35e27230061 100644 --- a/apps/desktop/src/renderer/lib/dev-chat.ts +++ b/apps/desktop/src/renderer/lib/dev-chat.ts @@ -3,6 +3,11 @@ import { env } from "renderer/env.renderer"; import { MOCK_ORG_ID } from "shared/constants"; export const DEV_CHAT_MODELS: ModelOption[] = [ + { + id: "anthropic/claude-opus-4-7", + name: "Opus 4.7", + provider: "Anthropic", + }, { id: "anthropic/claude-opus-4-6", name: "Opus 4.6", diff --git a/apps/desktop/src/renderer/lib/terminal/appearance/appearance.test.ts b/apps/desktop/src/renderer/lib/terminal/appearance/appearance.test.ts new file mode 100644 index 00000000000..c68eba7ce7f --- /dev/null +++ b/apps/desktop/src/renderer/lib/terminal/appearance/appearance.test.ts @@ -0,0 +1,149 @@ +import { afterEach, describe, expect, mock, test } from "bun:test"; +import { + DEFAULT_TERMINAL_FONT_FAMILY, + sanitizeTerminalFontFamily, +} from "./index"; + +type MeasureFn = (text: string) => { width: number }; + +/** + * Stub `document.createElement("canvas")` so `getContext("2d").measureText` + * returns widths from `measureForFont`. Non-canvas tags defer to the + * existing test-setup stub. + */ +function stubCanvas(measureForFont: (font: string) => MeasureFn) { + const originalCreate = document.createElement; + // biome-ignore lint/suspicious/noExplicitAny: bun:test `mock` wraps arbitrary fns + (document as any).createElement = mock((tag: string) => { + if (tag !== "canvas") { + // biome-ignore lint/suspicious/noExplicitAny: delegating stub accepts any tag + return (originalCreate as any).call(document, tag); + } + let currentFont = ""; + return { + getContext: (kind: string) => { + if (kind !== "2d") return null; + return { + set font(value: string) { + currentFont = value; + }, + get font() { + return currentFont; + }, + measureText: (text: string) => measureForFont(currentFont)(text), + }; + }, + }; + }); + return () => { + // biome-ignore lint/suspicious/noExplicitAny: restoring stubbed method + (document as any).createElement = originalCreate; + }; +} + +const equalWidths: MeasureFn = (text) => ({ width: text.length * 10 }); +const proportionalWidths: MeasureFn = (text) => { + let width = 0; + for (const ch of text) width += ch === "M" ? 16 : 6; + return { width }; +}; + +describe("sanitizeTerminalFontFamily", () => { + let restore: (() => void) | null = null; + + afterEach(() => { + restore?.(); + restore = null; + }); + + test("returns default for null / empty / whitespace", () => { + expect(sanitizeTerminalFontFamily(null)).toBe(DEFAULT_TERMINAL_FONT_FAMILY); + expect(sanitizeTerminalFontFamily(undefined)).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + expect(sanitizeTerminalFontFamily("")).toBe(DEFAULT_TERMINAL_FONT_FAMILY); + expect(sanitizeTerminalFontFamily(" ")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + }); + + test("trusts all-generic monospace values without canvas", () => { + expect(sanitizeTerminalFontFamily("monospace")).toBe("monospace"); + expect(sanitizeTerminalFontFamily("ui-monospace")).toBe("ui-monospace"); + }); + + test("falls back when the primary family is a proportional generic", () => { + expect(sanitizeTerminalFontFamily("sans-serif")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + expect(sanitizeTerminalFontFamily("serif")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + expect(sanitizeTerminalFontFamily("cursive")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + // CSS resolves the first generic, so a later monospace entry never wins. + expect(sanitizeTerminalFontFamily("cursive, monospace")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + }); + + test("passes through a stack whose primary generic is monospace", () => { + // The browser resolves the first generic, so "monospace, sans-serif" + // actually renders as monospace โ€” safe. + expect(sanitizeTerminalFontFamily("monospace, sans-serif")).toBe( + "monospace, sans-serif", + ); + }); + + test("falls back when a concrete mono follows a proportional generic", () => { + // Regression: earlier logic picked the first non-generic as the primary, + // letting `sans-serif, "JetBrains Mono"` slip through even though CSS + // renders sans-serif. Validate the actual CSS primary instead. + expect(sanitizeTerminalFontFamily('sans-serif, "JetBrains Mono"')).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + }); + + test("passes a monospace font through when the stack already ends with monospace", () => { + restore = stubCanvas(() => equalWidths); + expect(sanitizeTerminalFontFamily('"JetBrains Mono", monospace')).toBe( + '"JetBrains Mono", monospace', + ); + }); + + test("appends a monospace fallback when the stack lacks one", () => { + // If the primary isn't installed, the browser otherwise falls back to a + // proportional default โ€” appending "monospace" forces OS monospace. + restore = stubCanvas(() => equalWidths); + expect(sanitizeTerminalFontFamily('"JetBrains Mono"')).toBe( + '"JetBrains Mono", monospace', + ); + expect(sanitizeTerminalFontFamily("Menlo")).toBe("Menlo, monospace"); + }); + + test("falls back to default for a proportional primary family (quoted)", () => { + restore = stubCanvas(() => proportionalWidths); + expect(sanitizeTerminalFontFamily('"Inter", sans-serif')).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + }); + + test("falls back to default for a proportional primary family (bare)", () => { + restore = stubCanvas(() => proportionalWidths); + expect(sanitizeTerminalFontFamily("Inter")).toBe( + DEFAULT_TERMINAL_FONT_FAMILY, + ); + }); + + test("trusts the value when canvas measurement throws", () => { + restore = stubCanvas(() => () => { + throw new Error("canvas unsupported"); + }); + // Use a unique family so the module-level monospace cache doesn't mask + // the canvas error path. + expect(sanitizeTerminalFontFamily('"UnmeasurableFont-ABC-123"')).toBe( + '"UnmeasurableFont-ABC-123", monospace', + ); + }); +}); diff --git a/apps/desktop/src/renderer/lib/terminal/appearance/index.ts b/apps/desktop/src/renderer/lib/terminal/appearance/index.ts index 147f29e9b3e..456e0896683 100644 --- a/apps/desktop/src/renderer/lib/terminal/appearance/index.ts +++ b/apps/desktop/src/renderer/lib/terminal/appearance/index.ts @@ -61,6 +61,114 @@ export const DEFAULT_TERMINAL_FONT_FAMILY = serializeFontFamilyList([ export const DEFAULT_TERMINAL_FONT_SIZE = 14; +const MONOSPACE_GENERIC_FAMILIES = new Set(["monospace", "ui-monospace"]); + +/** Parse a CSS font-family list into trimmed entries, respecting quoted names. */ +function parseFontFamilyList(cssValue: string): string[] { + const families: string[] = []; + let current = ""; + let inQuote: string | null = null; + + for (const ch of cssValue) { + if (inQuote) { + if (ch === inQuote) inQuote = null; + else current += ch; + } else if (ch === '"' || ch === "'") { + inQuote = ch; + } else if (ch === ",") { + const trimmed = current.trim(); + if (trimmed) families.push(trimmed); + current = ""; + } else { + current += ch; + } + } + const last = current.trim(); + if (last) families.push(last); + return families; +} + +const monospaceCheckCache = new Map(); + +/** + * Heuristically decide whether `family` is a monospace font using canvas + * measurement โ€” monospace fonts render narrow ("iiiiii") and wide ("MMMMMM") + * runs at the same width. Returns `true` (permissive) when the canvas API + * is unavailable (tests/SSR) so we never block a legitimate font. + */ +function isFontFamilyMonospace(family: string): boolean { + const key = family.toLowerCase(); + if (MONOSPACE_GENERIC_FAMILIES.has(key)) return true; + + const cached = monospaceCheckCache.get(key); + if (cached !== undefined) return cached; + + try { + if (typeof document === "undefined") return true; + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext?.("2d"); + if (!ctx) return true; + + ctx.font = `16px "${family}"`; + const narrow = ctx.measureText("iiiiii").width; + const wide = ctx.measureText("MMMMMM").width; + // Sub-pixel jitter tolerance. + const isMono = Math.abs(narrow - wide) < 1; + monospaceCheckCache.set(key, isMono); + return isMono; + } catch { + return true; + } +} + +/** + * Guard against a persisted terminal font that would break xterm rendering + * (e.g. a proportional font like "Inter"). Returns the raw CSS value when + * the primary family is monospace; otherwise falls back to the bundled + * default so a poisoned setting can never blank the app on startup. + * + * See issue #3513. The settings UI already prevents new non-monospace + * selections for the terminal, but this recovers users whose DB was + * poisoned before the UI restriction was added. + */ +export function sanitizeTerminalFontFamily( + cssValue: string | null | undefined, +): string { + if (!cssValue || !cssValue.trim()) return DEFAULT_TERMINAL_FONT_FAMILY; + const families = parseFontFamilyList(cssValue); + if (families.length === 0) return DEFAULT_TERMINAL_FONT_FAMILY; + + // Validate the actual CSS primary (first entry), not the first non-generic. + // A value like `sans-serif, "JetBrains Mono"` resolves to sans-serif in the + // browser regardless of what follows, so inspecting the later entry would + // let proportional stacks slip through. + const primary = families[0]; + const primaryKey = primary.toLowerCase(); + + if (GENERIC_FONT_FAMILIES.has(primaryKey)) { + if (MONOSPACE_GENERIC_FAMILIES.has(primaryKey)) return cssValue; + console.warn( + `[terminal] Font stack "${cssValue}" has no monospace primary family; falling back to default terminal font.`, + ); + return DEFAULT_TERMINAL_FONT_FAMILY; + } + + if (!isFontFamilyMonospace(primary)) { + console.warn( + `[terminal] Font "${primary}" is not monospace; falling back to default terminal font.`, + ); + return DEFAULT_TERMINAL_FONT_FAMILY; + } + // Ensure a generic monospace tail โ€” if the configured primary isn't + // installed on this machine, the browser falls back to the OS monospace + // generic instead of a proportional default (mirrors VS Code's behavior + // in src/vs/workbench/contrib/terminal/browser/terminalConfigurationService.ts). + const hasMonoTail = families.some((f) => + MONOSPACE_GENERIC_FAMILIES.has(f.toLowerCase()), + ); + return hasMonoTail ? cssValue : `${cssValue}, monospace`; +} + /** Reads localStorage theme cache for flash-free first paint. */ export function getDefaultTerminalAppearance(): TerminalAppearance { const theme = readCachedTerminalTheme(); diff --git a/apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts b/apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts index f0e9296f151..b29bff72a61 100644 --- a/apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts +++ b/apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts @@ -156,11 +156,13 @@ export function createRuntime( wrapper.style.width = "100%"; wrapper.style.height = "100%"; terminal.open(wrapper); - restoreBuffer(terminalId, terminal); terminal.attachCustomKeyEventHandler((event) => !isAppHotkey(event)); + // Activate Unicode 11 widths (inside loadAddons) before restoring the buffer, + // else CJK/emoji/ZWJ widths get baked wrong into the replay. (#3572) const addonsResult = loadAddons(terminal); + restoreBuffer(terminalId, terminal); return { terminalId, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts index a8a19b15a17..413a8489ee7 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts @@ -4,6 +4,7 @@ import { type DestroyWorkspaceError, useDestroyWorkspace, } from "renderer/hooks/host-service/useDestroyWorkspace"; +import { useDeletingWorkspaces } from "renderer/routes/_authenticated/providers/DeletingWorkspacesProvider"; interface UseDestroyDialogStateOptions { workspaceId: string; @@ -15,11 +16,16 @@ interface UseDestroyDialogStateOptions { /** * Drives the delete flow for `DashboardSidebarDeleteDialog`. * - * UX pattern (mirrors v1's deleteWithToast): - * - On confirm, close the dialog immediately and run the destroy - * in the background under a toast.loading โ†’ success/error. - * - For decision-required errors (CONFLICT, TEARDOWN_FAILED) we - * reopen the dialog in the matching error pane so the user can + * UX pattern: + * - On confirm, close the dialog immediately, mark the workspace as + * deleting (sidebar row hides optimistically), and run destroy in + * the background silently. No loading toast โ€” destroy can take + * 10โ€“20s and a persistent toast across that window feels bad. The + * hidden row is the feedback. + * - On success, `onDeleted` removes the row from sidebar state. + * - On error, `clearDeleting` runs in the `finally` block so the row + * reappears. For decision-required errors (CONFLICT, TEARDOWN_FAILED) + * we reopen the dialog in the matching error pane so the user can * force-retry with full context. The branch opt-in is preserved. * - For unknown errors we just toast.error โ€” no reopen. */ @@ -30,6 +36,7 @@ export function useDestroyDialogState({ onDeleted, }: UseDestroyDialogStateOptions) { const { destroy } = useDestroyWorkspace(workspaceId); + const { markDeleting, clearDeleting } = useDeletingWorkspaces(); const [deleteBranch, setDeleteBranch] = useState(false); const [error, setError] = useState(null); @@ -60,29 +67,36 @@ export function useDestroyDialogState({ // on a decision-required error. setError(null); onOpenChange(false); - - const loadingId = toast.loading(`Deleting ${workspaceName}...`); + markDeleting(workspaceId); try { const result = await destroy({ deleteBranch, force }); - toast.success(`Deleted ${workspaceName}`, { id: loadingId }); for (const warning of result.warnings) toast.warning(warning); setDeleteBranch(false); onDeleted?.(); } catch (err) { const e = err as DestroyWorkspaceError; if (e.kind === "conflict" || e.kind === "teardown-failed") { - toast.dismiss(loadingId); setError(e); onOpenChange(true); } else { - toast.error(`Failed to delete: ${e.message}`, { id: loadingId }); + toast.error(`Failed to delete ${workspaceName}: ${e.message}`); } } finally { + clearDeleting(workspaceId); inFlight.current = false; } }, - [destroy, deleteBranch, workspaceName, onOpenChange, onDeleted], + [ + destroy, + deleteBranch, + workspaceName, + workspaceId, + onOpenChange, + onDeleted, + markDeleting, + clearDeleting, + ], ); return { diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx index a8c6f2f03d1..dc6482eb1f3 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx @@ -1,10 +1,33 @@ +import { isPaidPlan } from "@superset/shared/billing"; +import { FEATURE_FLAGS } from "@superset/shared/constants"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@superset/ui/dropdown-menu"; +import { toast } from "@superset/ui/sonner"; import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip"; import { cn } from "@superset/ui/utils"; import { useMatchRoute, useNavigate } from "@tanstack/react-router"; -import { LuFolderPlus, LuLayers, LuPlus } from "react-icons/lu"; +import { useFeatureFlagEnabled } from "posthog-js/react"; +import { HiMiniPlus, HiOutlineClipboardDocumentList } from "react-icons/hi2"; +import { + LuClock, + LuFolderInput, + LuFolderPlus, + LuLayers, + LuPlus, +} from "react-icons/lu"; +import { GATED_FEATURES, usePaywall } from "renderer/components/Paywall"; +import { useCurrentPlan } from "renderer/hooks/useCurrentPlan"; import { useHotkeyDisplay } from "renderer/hotkeys"; +import { FolderFirstImportModal } from "renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/components/FolderFirstImportModal"; +import { useFolderFirstImport } from "renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/hooks/useFolderFirstImport"; import { OrganizationDropdown } from "renderer/routes/_authenticated/_dashboard/components/TopBar/components/OrganizationDropdown"; +import { useTasksFilterStore } from "renderer/routes/_authenticated/_dashboard/tasks/stores/tasks-filter-state"; import { STROKE_WIDTH_THICK } from "renderer/screens/main/components/WorkspaceSidebar/constants"; +import { useOpenNewProjectModal } from "renderer/stores/add-repository-modal"; import { useOpenNewWorkspaceModal } from "renderer/stores/new-workspace-modal"; interface DashboardSidebarHeaderProps { @@ -15,15 +38,53 @@ export function DashboardSidebarHeader({ isCollapsed = false, }: DashboardSidebarHeaderProps) { const openModal = useOpenNewWorkspaceModal(); + const openNewProject = useOpenNewProjectModal(); + const folderImport = useFolderFirstImport({ + onSuccess: () => { + toast.success("Project ready โ€” open it from the sidebar."); + }, + onError: (message) => { + toast.error(`Import failed: ${message}`); + }, + }); const shortcutText = useHotkeyDisplay("NEW_WORKSPACE").text; const navigate = useNavigate(); const matchRoute = useMatchRoute(); + const { gateFeature } = usePaywall(); const isWorkspacesListOpen = !!matchRoute({ to: "/v2-workspaces" }); + const isTasksOpen = !!matchRoute({ to: "/tasks", fuzzy: true }); + const isAutomationsOpen = !!matchRoute({ to: "/automations", fuzzy: true }); + + const automationsFlagEnabled = useFeatureFlagEnabled( + FEATURE_FLAGS.AUTOMATIONS_ACCESS, + ); + const plan = useCurrentPlan(); + const showAutomations = automationsFlagEnabled && isPaidPlan(plan); + + const { + tab: lastTab, + assignee: lastAssignee, + search: lastSearch, + } = useTasksFilterStore(); const handleWorkspacesClick = () => { navigate({ to: "/v2-workspaces" }); }; + const handleAutomationsClick = () => { + navigate({ to: "/automations" }); + }; + + const handleTasksClick = () => { + gateFeature(GATED_FEATURES.TASKS, () => { + const search: Record = {}; + if (lastTab !== "all") search.tab = lastTab; + if (lastAssignee) search.assignee = lastAssignee; + if (lastSearch) search.search = lastSearch; + navigate({ to: "/tasks", search }); + }); + }; + if (isCollapsed) { return (
@@ -51,14 +112,67 @@ export function DashboardSidebarHeader({ - Add Repository + Tasks + + + + + + + + Add repository + + + + + New project + + folderImport.start()}> + + Import existing folder + + + + + {showAutomations && ( + + + + + Automations + + )} +
); } @@ -83,17 +203,32 @@ export function DashboardSidebarHeader({
- - - - - Add Repository - + + + + + + + + Add repository + + + + + New project + + folderImport.start()}> + + Import existing folder + + + + {showAutomations && ( + + )} + + + + + ); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx index 0278602c92e..9a105f0d804 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx @@ -1,5 +1,6 @@ import { useNavigate } from "@tanstack/react-router"; import { useDiffStats } from "renderer/hooks/host-service/useDiffStats"; +import { useDeletingWorkspaces } from "renderer/routes/_authenticated/providers/DeletingWorkspacesProvider"; import type { DashboardSidebarWorkspace } from "../../types"; import { DashboardSidebarDeleteDialog } from "../DashboardSidebarDeleteDialog"; import { DashboardSidebarCollapsedWorkspaceButton } from "./components/DashboardSidebarCollapsedWorkspaceButton"; @@ -58,6 +59,9 @@ export function DashboardSidebarWorkspaceItem({ const navigate = useNavigate(); const isPending = !!creationStatus; + // Keep the delete dialog outside the hidden wrapper below โ€” the destroy + // flow reopens it into an error pane on conflict/teardown-failed. + const isDeleting = useDeletingWorkspaces().isDeleting(id); const handlePendingClick = isPending ? () => { void navigate({ @@ -92,35 +96,37 @@ export function DashboardSidebarWorkspaceItem({ return ( <> - {isPending ? ( - content - ) : ( - - } - isLocalWorkspace={hostType === "local-device"} - onCreateSection={handleCreateSection} - onMoveToSection={(targetSectionId) => - moveWorkspaceToSection(id, projectId, targetSectionId) - } - onOpenInFinder={handleOpenInFinder} - onCopyPath={handleCopyPath} - onRemoveFromSidebar={() => removeWorkspaceFromSidebar(id)} - onRename={startRename} - onDelete={() => setIsDeleteDialogOpen(true)} - > - {content} - - )} + {!isPending && ( - {isPending ? ( - expandedContent - ) : ( - - } - onCreateSection={handleCreateSection} - onMoveToSection={(targetSectionId) => - moveWorkspaceToSection(id, projectId, targetSectionId) - } - isLocalWorkspace={hostType === "local-device"} - onOpenInFinder={handleOpenInFinder} - onCopyPath={handleCopyPath} - onRemoveFromSidebar={() => removeWorkspaceFromSidebar(id)} - onRename={startRename} - onDelete={() => setIsDeleteDialogOpen(true)} - > - {expandedContent} - - )} + {!isPending && ( { hostType: DashboardSidebarWorkspaceHostType; + hostIsOnline: boolean | null; isActive: boolean; workspaceStatus?: ActivePaneStatus | null; creationStatus?: "preparing" | "generating-branch" | "creating" | "failed"; @@ -19,6 +20,7 @@ export const DashboardSidebarCollapsedWorkspaceButton = forwardRef< ( { hostType, + hostIsOnline, isActive, workspaceStatus = null, creationStatus, @@ -41,6 +43,7 @@ export const DashboardSidebarCollapsedWorkspaceButton = forwardRef< > -

Worktree workspace

+

+ {hostType === "local-device" + ? "Local workspace" + : hostType === "remote-device" + ? hostIsOnline === false + ? "Remote workspace โ€” device offline" + : "Remote workspace" + : "Cloud workspace"} +

- Isolated copy for parallel development + {hostType === "local-device" + ? "Running on this device" + : hostType === "remote-device" + ? hostIsOnline === false + ? "The associated device isn't reachable right now" + : "Running on a paired device" + : "Hosted in the cloud"}

diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx index 49dba6a2d97..550488fc0af 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceContextMenu/DashboardSidebarWorkspaceContextMenu.tsx @@ -22,6 +22,7 @@ import { LuCopy, LuFolderOpen, LuFolderPlus, + LuGitBranch, LuPencil, LuTrash2, LuX, @@ -38,6 +39,7 @@ interface DashboardSidebarWorkspaceContextMenuProps { onMoveToSection: (sectionId: string | null) => void; onOpenInFinder: () => void; onCopyPath: () => void; + onCopyBranchName: () => void; onRemoveFromSidebar: () => void; onRename: () => void; onDelete: () => void; @@ -54,6 +56,7 @@ export function DashboardSidebarWorkspaceContextMenu({ onMoveToSection, onOpenInFinder, onCopyPath, + onCopyBranchName, onRemoveFromSidebar, onRename, onDelete, @@ -96,6 +99,11 @@ export function DashboardSidebarWorkspaceContextMenu({ )} + {!isLocalWorkspace && } + + + Copy Branch Name + diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx index 85248582359..fb9df6f6d4f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx @@ -1,6 +1,6 @@ import { cn } from "@superset/ui/utils"; import { HiExclamationTriangle } from "react-icons/hi2"; -import { LuCloud, LuFolderGit2, LuLaptop } from "react-icons/lu"; +import { LuCloud, LuCloudOff } from "react-icons/lu"; import { AsciiSpinner } from "renderer/screens/main/components/AsciiSpinner"; import { StatusIndicator } from "renderer/screens/main/components/StatusIndicator"; import type { ActivePaneStatus } from "shared/tabs-types"; @@ -8,6 +8,7 @@ import type { DashboardSidebarWorkspaceHostType } from "../../../../types"; interface DashboardSidebarWorkspaceIconProps { hostType: DashboardSidebarWorkspaceHostType; + hostIsOnline: boolean | null; isActive: boolean; variant: "collapsed" | "expanded"; workspaceStatus?: ActivePaneStatus | null; @@ -21,12 +22,45 @@ const OVERLAY_POSITION = { export function DashboardSidebarWorkspaceIcon({ hostType, + hostIsOnline, isActive, variant, workspaceStatus = null, creationStatus, }: DashboardSidebarWorkspaceIconProps) { const overlayPosition = OVERLAY_POSITION[variant]; + const iconColor = isActive ? "text-foreground" : "text-muted-foreground"; + const isRemoteDeviceOffline = + hostType === "remote-device" && hostIsOnline === false; + + const renderHostIcon = () => { + if (hostType === "local-device") { + return ( + + ); + } + + if (isRemoteDeviceOffline) { + return ( + + ); + } + + return ( + + ); + }; return ( <> @@ -34,33 +68,8 @@ export function DashboardSidebarWorkspaceIcon({ ) : creationStatus || workspaceStatus === "working" ? ( - ) : hostType === "cloud" ? ( - - ) : hostType === "remote-device" ? ( - ) : ( - + renderHostIcon() )} {workspaceStatus && workspaceStatus !== "working" && ( diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts index a9296ede735..3eb9f4f059f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts @@ -16,12 +16,14 @@ interface UseDashboardSidebarWorkspaceItemActionsOptions { workspaceId: string; projectId: string; workspaceName: string; + branch: string; } export function useDashboardSidebarWorkspaceItemActions({ workspaceId, projectId, workspaceName, + branch, }: UseDashboardSidebarWorkspaceItemActionsOptions) { const navigate = useNavigate(); const matchRoute = useMatchRoute(); @@ -144,10 +146,26 @@ export function useDashboardSidebarWorkspaceItemActions({ } }; + const handleCopyBranchName = async () => { + if (!branch) { + toast.error("Branch name is not available"); + return; + } + try { + await copyToClipboard(branch); + toast.success("Branch name copied"); + } catch (error) { + toast.error( + `Failed to copy branch name: ${error instanceof Error ? error.message : "Unknown error"}`, + ); + } + }; + return { cancelRename, handleClick, handleCopyPath, + handleCopyBranchName, handleCreateSection, handleDeleted, handleOpenInFinder, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts index b9a8b6b5c3a..4f915b32ae2 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts @@ -16,8 +16,9 @@ import type { DashboardSidebarWorkspace, } from "../../types"; -// Pending workspaces are always rendered at the end of the project's workspace list -const PENDING_WORKSPACE_TAB_ORDER = Number.MAX_SAFE_INTEGER; +// Sits above every real workspace so the pending row lines up with the real one, +// which is inserted via getPrependTabOrder. +const PENDING_WORKSPACE_TAB_ORDER = Number.MIN_SAFE_INTEGER; export function useDashboardSidebarData() { const { data: session } = authClient.useSession(); @@ -120,6 +121,7 @@ export function useDashboardSidebarData() { projectId: sidebarWorkspaces.sidebarState.projectId, hostId: workspaces.hostId, hostMachineId: hosts?.machineId ?? null, + hostIsOnline: hosts?.isOnline ?? null, name: workspaces.name, branch: workspaces.branch, createdAt: workspaces.createdAt, @@ -239,6 +241,10 @@ export function useDashboardSidebarData() { projectId: workspace.projectId, hostId: workspace.hostId, hostType, + hostIsOnline: + hostType === "remote-device" + ? (workspace.hostIsOnline ?? null) + : null, accentColor: null, name: workspace.name, branch: workspace.branch, @@ -290,6 +296,7 @@ export function useDashboardSidebarData() { projectId: pw.projectId, hostId: "", hostType: "local-device", + hostIsOnline: null, accentColor: null, name: pw.name, branch: pw.branchName, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts index 329d90bd701..e2ff2406ec2 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts @@ -25,6 +25,7 @@ export interface DashboardSidebarWorkspace { projectId: string; hostId: string; hostType: DashboardSidebarWorkspaceHostType; + hostIsOnline: boolean | null; accentColor: string | null; name: string; branch: string; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/hooks/useWorkspaceChatDisplay/useWorkspaceChatDisplay.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/hooks/useWorkspaceChatDisplay/useWorkspaceChatDisplay.ts index 8bb6ac97efd..fb3965347ff 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/hooks/useWorkspaceChatDisplay/useWorkspaceChatDisplay.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/ChatPane/hooks/useWorkspaceChatDisplay/useWorkspaceChatDisplay.ts @@ -107,8 +107,7 @@ function getLegacyImagePayload( } export function useChatDisplay(options: UseChatDisplayOptions) { - const { sessionId, workspaceId, enabled = true, fps = 60 } = options; - const utils = workspaceTrpc.useUtils(); + const { sessionId, workspaceId, enabled = true, fps = 4 } = options; const [commandError, setCommandError] = useState(null); const queryInput = sessionId === null ? undefined : { sessionId, workspaceId }; @@ -119,8 +118,6 @@ export function useChatDisplay(options: UseChatDisplayOptions) { refetchInterval: refetchIntervalMs, refetchIntervalInBackground: true, refetchOnWindowFocus: false, - staleTime: 0, - gcTime: 0, } as const; const displayQuery = workspaceTrpc.chat.getDisplayState.useQuery( @@ -351,20 +348,6 @@ export function useChatDisplay(options: UseChatDisplayOptions) { ], ); - useEffect(() => { - if (!queryInput) return; - if (!isRunning) return; - void Promise.all([ - utils.chat.getDisplayState.invalidate(queryInput), - utils.chat.listMessages.invalidate(queryInput), - ]); - }, [ - isRunning, - queryInput, - utils.chat.getDisplayState, - utils.chat.listMessages, - ]); - return { ...displayState, messages, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/TerminalPane.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/TerminalPane.tsx index e346d860a81..54995d2629b 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/TerminalPane.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/TerminalPane.tsx @@ -32,6 +32,7 @@ import { DEFAULT_FILE_OPEN_MODE, } from "shared/constants"; import { LinkHoverTooltip } from "./components/LinkHoverTooltip"; +import { useLinkClickHint } from "./hooks/useLinkClickHint"; import { useLinkHoverState } from "./hooks/useLinkHoverState"; import { useTerminalAppearance } from "./hooks/useTerminalAppearance"; import { shellEscapePaths } from "./utils"; @@ -68,6 +69,7 @@ export function TerminalPane({ onHover: onLinkHover, onLeave: onLinkLeave, } = useLinkHoverState(); + const { hint, showHint } = useLinkClickHint(); const paneData = ctx.pane.data as TerminalPaneData; // FORK NOTE: Guard against legacy pane data format {sessionKey, cwd, launchMode} // saved in local DB before the terminalId migration. @@ -175,7 +177,10 @@ export function TerminalPane({ } }, onFileLinkClick: (event, link) => { - if (!event.metaKey && !event.ctrlKey) return; + if (!event.metaKey && !event.ctrlKey) { + showHint(event.clientX, event.clientY); + return; + } event.preventDefault(); if (event.shiftKey) { openInExternalEditor(link.resolvedPath, { @@ -218,6 +223,7 @@ export function TerminalPane({ openInExternalEditor, onLinkHover, onLinkLeave, + showHint, ]); useHotkey( @@ -343,7 +349,7 @@ export function TerminalPane({ Disconnected )} - + ); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/components/LinkHoverTooltip/LinkHoverTooltip.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/components/LinkHoverTooltip/LinkHoverTooltip.tsx index 87323399029..36cc26e390d 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/components/LinkHoverTooltip/LinkHoverTooltip.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/components/LinkHoverTooltip/LinkHoverTooltip.tsx @@ -1,75 +1,68 @@ -import type { ExternalApp } from "@superset/local-db"; -import { useEffect, useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; import { createPortal } from "react-dom"; -import { getAppOption } from "renderer/components/OpenInExternalDropdown/constants"; import type { LinkHoverInfo } from "renderer/lib/terminal/terminal-runtime-registry"; -import { electronTrpcClient } from "renderer/lib/trpc-client"; +import type { LinkClickHint } from "../../hooks/useLinkClickHint"; import type { HoveredLink } from "../../hooks/useLinkHoverState"; const TOOLTIP_OFFSET_PX = 14; +const TOOLTIP_CLASSES = + "pointer-events-none fixed z-50 w-fit rounded-md bg-foreground px-3 py-1.5 text-xs text-background"; + +const isMac = + typeof navigator !== "undefined" && + navigator.platform.toLowerCase().includes("mac"); +const MOD_LABEL = isMac ? "โŒ˜" : "Ctrl"; +const MOD_SHIFT_LABEL = isMac ? "โŒ˜โ‡ง" : "Ctrl+Shift"; +const HINT_LABEL = `Hold ${MOD_LABEL} to open ยท ${MOD_SHIFT_LABEL} for external`; interface LinkHoverTooltipProps { hoveredLink: HoveredLink | null; + hint: LinkClickHint | null; } -function getAppLabel(app: ExternalApp): string { - const option = getAppOption(app); - return option?.displayLabel ?? option?.label ?? "external editor"; -} - -function getLabel( - info: LinkHoverInfo, - shift: boolean, - defaultEditor: ExternalApp | null, -): string { +function getLabel(info: LinkHoverInfo, shift: boolean): string { if (info.kind === "url") { - return shift ? "Open in external browser" : "Open in browser"; - } - if (shift) { - return defaultEditor - ? `Open in ${getAppLabel(defaultEditor)}` - : "Open externally"; + return shift ? "Open in external browser" : "Open in pane"; } - return info.isDirectory ? "Reveal in sidebar" : "Open in editor"; + if (shift) return "Open in external editor"; + return info.isDirectory ? "Reveal in sidebar" : "Open in pane"; } -export function LinkHoverTooltip({ hoveredLink }: LinkHoverTooltipProps) { - const [defaultEditor, setDefaultEditor] = useState(null); - - useEffect(() => { - let cancelled = false; - electronTrpcClient.settings.getDefaultEditor - .query() - .then((editor) => { - if (!cancelled) setDefaultEditor(editor); - }) - .catch((error) => { - if (cancelled) return; - console.warn( - "[LinkHoverTooltip] Failed to fetch default editor:", - error, - ); - setDefaultEditor(null); - }); - return () => { - cancelled = true; - }; - }, []); - - if (!hoveredLink || !hoveredLink.modifier) return null; - - const label = getLabel(hoveredLink.info, hoveredLink.shift, defaultEditor); +export function LinkHoverTooltip({ hoveredLink, hint }: LinkHoverTooltipProps) { + const showingHover = Boolean(hoveredLink?.modifier); return createPortal( -
- {label} -
, + <> + {hoveredLink?.modifier && ( +
+ {getLabel(hoveredLink.info, hoveredLink.shift)} +
+ )} + + {hint && !showingHover && ( + + {HINT_LABEL} + + )} + + , document.body, ); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/index.ts new file mode 100644 index 00000000000..c9aacc8b15e --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/index.ts @@ -0,0 +1 @@ +export { type LinkClickHint, useLinkClickHint } from "./useLinkClickHint"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/useLinkClickHint.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/useLinkClickHint.ts new file mode 100644 index 00000000000..4c6d5286f58 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useLinkClickHint/useLinkClickHint.ts @@ -0,0 +1,35 @@ +import { useCallback, useEffect, useRef, useState } from "react"; + +export interface LinkClickHint { + clientX: number; + clientY: number; +} + +const HINT_DURATION_MS = 2000; +const MAX_HINTS_PER_SESSION = 2; + +let hintsRemaining = MAX_HINTS_PER_SESSION; + +export function useLinkClickHint() { + const [hint, setHint] = useState(null); + const timeoutRef = useRef | null>(null); + + const showHint = useCallback((clientX: number, clientY: number) => { + if (hintsRemaining <= 0) return; + hintsRemaining -= 1; + if (timeoutRef.current) clearTimeout(timeoutRef.current); + setHint({ clientX, clientY }); + timeoutRef.current = setTimeout(() => { + setHint(null); + timeoutRef.current = null; + }, HINT_DURATION_MS); + }, []); + + useEffect(() => { + return () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + }; + }, []); + + return { hint, showHint }; +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useTerminalAppearance/useTerminalAppearance.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useTerminalAppearance/useTerminalAppearance.ts index 55ff6314d7b..e6c9c8f9e21 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useTerminalAppearance/useTerminalAppearance.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/hooks/useTerminalAppearance/useTerminalAppearance.ts @@ -1,9 +1,9 @@ import { useQuery } from "@tanstack/react-query"; import { useMemo } from "react"; import { - DEFAULT_TERMINAL_FONT_FAMILY, DEFAULT_TERMINAL_FONT_SIZE, getDefaultTerminalAppearance, + sanitizeTerminalFontFamily, type TerminalAppearance, } from "renderer/lib/terminal/appearance"; import { electronTrpcClient } from "renderer/lib/trpc-client"; @@ -21,8 +21,9 @@ export function useTerminalAppearance(): TerminalAppearance { return useMemo(() => { const theme = terminalTheme ?? fallbackTheme; - const fontFamily = - fontSettings?.terminalFontFamily || DEFAULT_TERMINAL_FONT_FAMILY; + const fontFamily = sanitizeTerminalFontFamily( + fontSettings?.terminalFontFamily, + ); const fontSize = fontSettings?.terminalFontSize ?? DEFAULT_TERMINAL_FONT_SIZE; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts index 83308f52a08..205a334364c 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useWorkspaceHotkeys/useWorkspaceHotkeys.ts @@ -12,6 +12,7 @@ import type { StoreApi } from "zustand"; import type { BrowserPaneData, ChatPaneData, + DiffPaneData, PaneViewerData, TerminalPaneData, } from "../../types"; @@ -70,6 +71,33 @@ export function useWorkspaceHotkeys({ }); }); + useHotkey("OPEN_DIFF_VIEWER", () => { + if (collections.v2WorkspaceLocalState.get(workspaceId)) { + collections.v2WorkspaceLocalState.update(workspaceId, (draft) => { + draft.rightSidebarOpen = true; + draft.sidebarState.activeTab = "changes"; + }); + } + + const state = store.getState(); + for (const tab of state.tabs) { + for (const pane of Object.values(tab.panes)) { + if (pane.kind !== "diff") continue; + state.setActiveTab(tab.id); + state.setActivePane({ tabId: tab.id, paneId: pane.id }); + return; + } + } + state.addTab({ + panes: [ + { + kind: "diff", + data: { path: "", collapsedFiles: [] } as DiffPaneData, + }, + ], + }); + }); + // --- Tab management --- const isClosingPaneRef = useRef(false); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesHeader/V2WorkspacesHeader.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesHeader/V2WorkspacesHeader.tsx index 1acf3e0c45f..9417d6eea6f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesHeader/V2WorkspacesHeader.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesHeader/V2WorkspacesHeader.tsx @@ -58,52 +58,48 @@ export function V2WorkspacesHeader({ counts }: V2WorkspacesHeaderProps) { }; return ( -
-
-

Workspaces

-

- Every workspace you can access across your devices. Open one to jump - in, or add it to your sidebar. -

-
+
+
+

Workspaces

-
- - - - - setSearchQuery(event.target.value)} - /> - +
+ + + + + setSearchQuery(event.target.value)} + /> + - { - if (value) setDeviceFilter(value as V2WorkspacesDeviceFilter); - }} - > - {DEVICE_FILTER_OPTIONS.map(({ value, label, Icon }) => ( - - {Icon ? : null} - {label} - - {countForFilter(value)} - - - ))} - + { + if (value) setDeviceFilter(value as V2WorkspacesDeviceFilter); + }} + > + {DEVICE_FILTER_OPTIONS.map(({ value, label, Icon }) => ( + + {Icon ? : null} + {label} + + {countForFilter(value)} + + + ))} + +
); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/V2WorkspacesList.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/V2WorkspacesList.tsx index 10a29d40088..c237c351b1b 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/V2WorkspacesList.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/V2WorkspacesList.tsx @@ -7,10 +7,10 @@ import { EmptyMedia, EmptyTitle, } from "@superset/ui/empty"; -import { ItemGroup } from "@superset/ui/item"; import { ScrollArea } from "@superset/ui/scroll-area"; +import { cn } from "@superset/ui/utils"; import { useMatchRoute } from "@tanstack/react-router"; -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import { LuLayers, LuSearchX } from "react-icons/lu"; import type { AccessibleV2Workspace, @@ -20,18 +20,20 @@ import { useV2WorkspacesFilterStore, type V2WorkspacesDeviceFilter, } from "renderer/routes/_authenticated/_dashboard/v2-workspaces/stores/v2WorkspacesFilterStore"; +import { SortableHeader } from "./components/SortableHeader"; import { V2WorkspaceRow } from "./components/V2WorkspaceRow"; +import { V2_WORKSPACES_ROW_GRID } from "./constants"; +import type { SortDirection, SortField } from "./types"; interface V2WorkspacesListProps { - pinned: AccessibleV2Workspace[]; - others: AccessibleV2Workspace[]; - hasAnyAccessible: boolean; + workspaces: AccessibleV2Workspace[]; } interface ProjectGroup { projectId: string; projectName: string; workspaces: AccessibleV2Workspace[]; + latestCreatedAt: number; } function matchesDeviceFilter( @@ -50,36 +52,95 @@ function matchesDeviceFilter( } } -function groupByProject(workspaces: AccessibleV2Workspace[]): ProjectGroup[] { - const groupsById = new Map(); +// Host-type rank used as a tiebreaker when sorting by host โ€” keeps local +// device first, then remote devices, then cloud. +function hostTypeRank(hostType: V2WorkspaceHostType): number { + switch (hostType) { + case "local-device": + return 0; + case "remote-device": + return 1; + case "cloud": + return 2; + } +} + +function compareWorkspaces( + a: AccessibleV2Workspace, + b: AccessibleV2Workspace, + field: SortField, + direction: SortDirection, +): number { + let cmp = 0; + switch (field) { + case "sidebar": + cmp = Number(a.isInSidebar) - Number(b.isInSidebar); + break; + case "name": + cmp = a.name.localeCompare(b.name); + break; + case "host": + cmp = hostTypeRank(a.hostType) - hostTypeRank(b.hostType); + if (cmp === 0) cmp = a.hostName.localeCompare(b.hostName); + break; + case "branch": + cmp = a.branch.localeCompare(b.branch); + break; + case "created": + cmp = a.createdAt.getTime() - b.createdAt.getTime(); + break; + } + if (cmp === 0) { + cmp = b.createdAt.getTime() - a.createdAt.getTime(); + } + return direction === "asc" ? cmp : -cmp; +} + +function groupByProject( + workspaces: AccessibleV2Workspace[], + sortField: SortField, + sortDirection: SortDirection, +): ProjectGroup[] { + const projectsById = new Map(); + for (const workspace of workspaces) { - const existing = groupsById.get(workspace.projectId); - if (existing) { - existing.workspaces.push(workspace); - } else { - groupsById.set(workspace.projectId, { + let project = projectsById.get(workspace.projectId); + if (!project) { + project = { projectId: workspace.projectId, projectName: workspace.projectName, - workspaces: [workspace], - }); + workspaces: [], + latestCreatedAt: 0, + }; + projectsById.set(workspace.projectId, project); + } + project.workspaces.push(workspace); + const createdAt = workspace.createdAt.getTime(); + if (createdAt > project.latestCreatedAt) { + project.latestCreatedAt = createdAt; } } - return Array.from(groupsById.values()).sort((a, b) => { - const aLatest = Math.max( - ...a.workspaces.map((workspace) => workspace.createdAt.getTime()), - ); - const bLatest = Math.max( - ...b.workspaces.map((workspace) => workspace.createdAt.getTime()), + + for (const project of projectsById.values()) { + project.workspaces.sort((a, b) => + compareWorkspaces(a, b, sortField, sortDirection), ); - return bLatest - aLatest; - }); + } + + return Array.from(projectsById.values()).sort( + (a, b) => b.latestCreatedAt - a.latestCreatedAt, + ); } -export function V2WorkspacesList({ - pinned, - others, - hasAnyAccessible, -}: V2WorkspacesListProps) { +const DEFAULT_DIRECTION_BY_FIELD: Record = { + sidebar: "desc", + name: "asc", + host: "asc", + branch: "asc", + created: "desc", +}; + +export function V2WorkspacesList({ workspaces }: V2WorkspacesListProps) { const matchRoute = useMatchRoute(); const currentWorkspaceMatch = matchRoute({ to: "/v2-workspace/$workspaceId", @@ -93,136 +154,150 @@ export function V2WorkspacesList({ ); const resetFilters = useV2WorkspacesFilterStore((state) => state.reset); - // `pinned` / `others` already have the search filter applied upstream in - // useAccessibleV2Workspaces, so here we only narrow by device filter. - const filteredPinnedGroups = useMemo(() => { - const filtered = pinned.filter((workspace) => - matchesDeviceFilter(workspace.hostType, deviceFilter), - ); - return groupByProject(filtered); - }, [pinned, deviceFilter]); + const [sortField, setSortField] = useState("created"); + const [sortDirection, setSortDirection] = useState("desc"); - const filteredOtherGroups = useMemo(() => { - const filtered = others.filter((workspace) => + const handleSort = (field: SortField) => { + if (sortField === field) { + setSortDirection((prev) => (prev === "asc" ? "desc" : "asc")); + } else { + setSortField(field); + setSortDirection(DEFAULT_DIRECTION_BY_FIELD[field]); + } + }; + + const projectGroups = useMemo(() => { + const filtered = workspaces.filter((workspace) => matchesDeviceFilter(workspace.hostType, deviceFilter), ); - return groupByProject(filtered); - }, [others, deviceFilter]); + return groupByProject(filtered, sortField, sortDirection); + }, [workspaces, deviceFilter, sortField, sortDirection]); - const pinnedCount = filteredPinnedGroups.reduce( - (total, group) => total + group.workspaces.length, - 0, - ); - const othersCount = filteredOtherGroups.reduce( - (total, group) => total + group.workspaces.length, + const totalCount = projectGroups.reduce( + (total, project) => total + project.workspaces.length, 0, ); - const hasAnyMatches = pinnedCount > 0 || othersCount > 0; const hasActiveFilters = searchQuery.trim() !== "" || deviceFilter !== "all"; - if (!hasAnyAccessible) { - return ( - - - - - - No workspaces yet - - Create a workspace from the sidebar to get started. Workspaces you - have access to across all your devices will show up here. - - - - ); - } + const columnHeader = ( +
+ + + + + + +
+ ); - if (!hasAnyMatches) { + if (totalCount === 0) { return ( - - - - - - No workspaces match your filters - - Try a different search term or clear the device filter. - - - {hasActiveFilters ? ( - - - - ) : null} - +
+ {columnHeader} + + + + {hasActiveFilters ? : } + + + {hasActiveFilters + ? "No workspaces match your filters" + : "No workspaces yet"} + + + {hasActiveFilters + ? "Try a different search term or clear the device filter." + : "Workspaces you have access to across all your devices will show up here."} + + + {hasActiveFilters ? ( + + + + ) : null} + +
); } - const renderProjectGroups = (groups: ProjectGroup[]) => ( -
- {groups.map((group) => ( -
-
-

- {group.projectName} -

- - {group.workspaces.length} - -
- - {group.workspaces.map((workspace) => ( - - ))} - -
- ))} -
- ); - return ( - -
- {pinnedCount > 0 ? ( -
-
-

- In your sidebar -

- - {pinnedCount} - -
- {renderProjectGroups(filteredPinnedGroups)} -
- ) : null} - - {othersCount > 0 ? ( -
-
-

- Other workspaces -

- - {othersCount} + +
+ {columnHeader} + + {projectGroups.map((project) => ( +
+
+

+ {project.projectName} +

+ + {project.workspaces.length}
- {renderProjectGroups(filteredOtherGroups)} -
- ) : null} +
    + {project.workspaces.map((workspace) => ( + + ))} +
+
+ ))}
); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/SortableHeader.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/SortableHeader.tsx new file mode 100644 index 00000000000..3d5a0cf8de3 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/SortableHeader.tsx @@ -0,0 +1,60 @@ +import { cn } from "@superset/ui/utils"; +import { LuChevronDown, LuChevronsUpDown, LuChevronUp } from "react-icons/lu"; +import type { SortDirection, SortField } from "../../types"; + +interface SortableHeaderProps { + field: SortField; + label: string; + align?: "start" | "center"; + className?: string; + sortField: SortField; + sortDirection: SortDirection; + onSort: (field: SortField) => void; + srOnlyLabel?: boolean; +} + +export function SortableHeader({ + field, + label, + align = "start", + className, + sortField, + sortDirection, + onSort, + srOnlyLabel = false, +}: SortableHeaderProps) { + const isActive = sortField === field; + const Icon = !isActive + ? LuChevronsUpDown + : sortDirection === "asc" + ? LuChevronUp + : LuChevronDown; + const sortLabel = isActive + ? sortDirection === "asc" + ? "ascending" + : "descending" + : "not sorted"; + + return ( + + ); +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/index.ts new file mode 100644 index 00000000000..c85413e268f --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/SortableHeader/index.ts @@ -0,0 +1 @@ +export { SortableHeader } from "./SortableHeader"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/V2WorkspaceRow.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/V2WorkspaceRow.tsx index 4cc638df286..566c3bc3709 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/V2WorkspaceRow.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/V2WorkspaceRow.tsx @@ -1,13 +1,6 @@ -import { Badge } from "@superset/ui/badge"; import { Button } from "@superset/ui/button"; -import { - Item, - ItemActions, - ItemContent, - ItemDescription, - ItemMedia, - ItemTitle, -} from "@superset/ui/item"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip"; +import { cn } from "@superset/ui/utils"; import { useNavigate } from "@tanstack/react-router"; import { useCallback } from "react"; import { @@ -19,32 +12,44 @@ import { LuPlus, } from "react-icons/lu"; import { navigateToV2Workspace } from "renderer/routes/_authenticated/_dashboard/utils/workspace-navigation"; -import type { AccessibleV2Workspace } from "renderer/routes/_authenticated/_dashboard/v2-workspaces/hooks/useAccessibleV2Workspaces"; +import type { + AccessibleV2Workspace, + V2WorkspaceHostType, +} from "renderer/routes/_authenticated/_dashboard/v2-workspaces/hooks/useAccessibleV2Workspaces"; import { useDashboardSidebarState } from "renderer/routes/_authenticated/hooks/useDashboardSidebarState"; import { getRelativeTime } from "renderer/screens/main/components/WorkspacesListView/utils"; -import { V2WorkspaceDeviceBadge } from "./components/V2WorkspaceDeviceBadge"; +import { V2_WORKSPACES_ROW_GRID } from "../../constants"; interface V2WorkspaceRowProps { workspace: AccessibleV2Workspace; - showProjectName: boolean; isCurrentRoute: boolean; } +function hostIconFor(hostType: V2WorkspaceHostType) { + switch (hostType) { + case "cloud": + return LuCloud; + case "local-device": + return LuLaptop; + case "remote-device": + return LuMonitor; + } +} + export function V2WorkspaceRow({ workspace, - showProjectName, isCurrentRoute, }: V2WorkspaceRowProps) { const navigate = useNavigate(); const { ensureWorkspaceInSidebar, removeWorkspaceFromSidebar } = useDashboardSidebarState(); - const HostIcon = - workspace.hostType === "cloud" - ? LuCloud - : workspace.hostType === "local-device" - ? LuLaptop - : LuMonitor; + const HostIcon = hostIconFor(workspace.hostType); + + // The local device is always reachable from here โ€” ignore any stale + // isOnline flag on that row. + const treatAsOffline = + !workspace.hostIsOnline && workspace.hostType !== "local-device"; const handleOpen = useCallback(() => { navigateToV2Workspace(workspace.id, navigate); @@ -70,8 +75,16 @@ export function V2WorkspaceRow({ ? "you" : (workspace.createdByName ?? "unknown"); + const timeLabel = getRelativeTime(workspace.createdAt.getTime(), { + format: "compact", + }); + const handleRowKeyDown = useCallback( (event: React.KeyboardEvent) => { + // Ignore keystrokes bubbling from focused descendants (e.g. the + // Add/Remove icon buttons) โ€” `stopPropagation` on their click handlers + // doesn't catch keyboard events. + if (event.target !== event.currentTarget) return; if (event.key === "Enter" || event.key === " ") { event.preventDefault(); handleOpen(); @@ -80,72 +93,129 @@ export function V2WorkspaceRow({ [handleOpen], ); + const hostCell = ( + + + {workspace.hostName} + {treatAsOffline ? ( + + ) : null} + + ); + return ( - - - - - - - - {workspace.name} - - - {showProjectName ? ( - - {workspace.projectName} - + {/* biome-ignore lint/a11y/useSemanticElements: interactive row needs nested buttons, so the outer element is a div with role/tabIndex */} +
+ + {workspace.isInSidebar ? ( + ) : null} - - - {workspace.branch} - - - - {getRelativeTime(workspace.createdAt.getTime(), { - format: "compact", - })}{" "} - by {creatorLabel} - - - - - - {workspace.isInSidebar ? ( - + {workspace.name} + + + + {treatAsOffline ? ( + + {hostCell} + Host is offline + ) : ( - + hostCell )} - - + + + + + {workspace.branch} + + + + + {timeLabel} ยท {creatorLabel} + + +
+ {workspace.isInSidebar ? ( + + + + + + {isCurrentRoute + ? "Can't remove the current workspace" + : "Remove from sidebar"} + + + ) : ( + + + + + Add to sidebar + + )} +
+
+ ); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/V2WorkspaceDeviceBadge.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/V2WorkspaceDeviceBadge.tsx deleted file mode 100644 index 96872d2e490..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/V2WorkspaceDeviceBadge.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Badge } from "@superset/ui/badge"; -import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip"; -import { cn } from "@superset/ui/utils"; -import { LuCloud, LuLaptop, LuMonitor } from "react-icons/lu"; -import type { V2WorkspaceHostType } from "renderer/routes/_authenticated/_dashboard/v2-workspaces/hooks/useAccessibleV2Workspaces"; - -interface V2WorkspaceDeviceBadgeProps { - hostType: V2WorkspaceHostType; - hostName: string; - isOnline: boolean; -} - -export function V2WorkspaceDeviceBadge({ - hostType, - hostName, - isOnline, -}: V2WorkspaceDeviceBadgeProps) { - const Icon = - hostType === "cloud" - ? LuCloud - : hostType === "local-device" - ? LuLaptop - : LuMonitor; - - // The local device is always reachable from here โ€” ignore any stale - // isOnline flag on that row. - const treatAsOffline = !isOnline && hostType !== "local-device"; - - const badge = ( - - - {hostName} - {treatAsOffline ? ( - - ) : null} - - ); - - if (!treatAsOffline) { - return badge; - } - - return ( - - {badge} - Host is offline - - ); -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/index.ts deleted file mode 100644 index ca6ed56dfa0..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/components/V2WorkspaceRow/components/V2WorkspaceDeviceBadge/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { V2WorkspaceDeviceBadge } from "./V2WorkspaceDeviceBadge"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/constants.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/constants.ts new file mode 100644 index 00000000000..738705ecda4 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/constants.ts @@ -0,0 +1,5 @@ +// Shared grid template used by the column header row and every workspace row +// so the Sidebar / Name / Host / Branch / Created / Action columns align +// across the whole view. Columns hide progressively on narrower viewports. +export const V2_WORKSPACES_ROW_GRID = + "grid grid-cols-[1.25rem_minmax(0,1fr)_2.5rem] gap-4 md:grid-cols-[1.25rem_minmax(0,1fr)_12rem_2.5rem] lg:grid-cols-[1.25rem_minmax(0,1fr)_12rem_14rem_2.5rem] xl:grid-cols-[1.25rem_minmax(0,1fr)_12rem_14rem_11rem_2.5rem] items-center"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/types.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/types.ts new file mode 100644 index 00000000000..09ae323f499 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/components/V2WorkspacesList/types.ts @@ -0,0 +1,2 @@ +export type SortField = "sidebar" | "name" | "host" | "branch" | "created"; +export type SortDirection = "asc" | "desc"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/page.tsx index d8286acf22d..ebaa0ba0e7e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspaces/page.tsx @@ -22,17 +22,12 @@ function V2WorkspacesPage() { resetFilters(); }, [resetFilters]); - const { pinned, others, counts } = useAccessibleV2Workspaces({ searchQuery }); - const hasAnyAccessible = pinned.length > 0 || others.length > 0; + const { all, counts } = useAccessibleV2Workspaces({ searchQuery }); return (
- +
); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx index c5fb9900224..a3dbd8c0b1b 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx @@ -662,7 +662,8 @@ export function WorkspacePage({ return addBrowserShortcutListener(handleBrowserShortcut); }, [handleBrowserShortcut]); - const handleSearchInFiles = useCallback(() => { + // Open diff viewer (โŒ˜โ‡งL) + useHotkey("OPEN_DIFF_VIEWER", () => { if (!isSidebarOpen) { setSidebarOpen(true); } diff --git a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/PromptGroup.tsx b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/PromptGroup.tsx index cbaa45df94c..e157261b88b 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/PromptGroup.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/PromptGroup.tsx @@ -1,7 +1,12 @@ +import { + sanitizeUserBranchName, + slugifyForBranch, +} from "@superset/shared/workspace-launch"; import { PromptInput, PromptInputAttachment, PromptInputAttachments, + PromptInputButton, PromptInputFooter, PromptInputSubmit, PromptInputTextarea, @@ -14,17 +19,17 @@ import { cn } from "@superset/ui/utils"; import type { FileUIPart } from "ai"; import { AnimatePresence, motion } from "framer-motion"; import { ArrowUpIcon } from "lucide-react"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef } from "react"; +import { GoIssueOpened } from "react-icons/go"; import { LuGitPullRequest } from "react-icons/lu"; +import { SiLinear } from "react-icons/si"; import { AgentSelect } from "renderer/components/AgentSelect"; import { LinkedIssuePill } from "renderer/components/Chat/ChatInterface/components/ChatInputFooter/components/LinkedIssuePill"; import { IssueLinkCommand } from "renderer/components/Chat/ChatInterface/components/IssueLinkCommand"; import { useAgentLaunchPreferences } from "renderer/hooks/useAgentLaunchPreferences"; +import { useEnabledAgents } from "renderer/hooks/useEnabledAgents"; import { PLATFORM } from "renderer/hotkeys"; -import { electronTrpc } from "renderer/lib/electron-trpc"; import { useNewWorkspaceModalOpen } from "renderer/stores/new-workspace-modal"; -import { getEnabledAgentConfigs } from "shared/utils/agent-settings"; -import { sanitizeUserBranchName, slugifyForBranch } from "shared/utils/branch"; import { useDashboardNewWorkspaceDraft } from "../../../DashboardNewWorkspaceDraftContext"; import { DevicePicker } from "../components/DevicePicker"; import { AttachmentButtons } from "./components/AttachmentButtons"; @@ -73,11 +78,8 @@ export function PromptGroup({ } = draft; // โ”€โ”€ Agent presets โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - const agentPresetsQuery = electronTrpc.settings.getAgentPresets.useQuery(); - const enabledAgentPresets = useMemo( - () => getEnabledAgentConfigs(agentPresetsQuery.data ?? []), - [agentPresetsQuery.data], - ); + const { agents: enabledAgentPresets, isFetched: agentsFetched } = + useEnabledAgents(); const selectableAgentIds = useMemo( () => enabledAgentPresets.map((preset) => preset.id), [enabledAgentPresets], @@ -88,14 +90,9 @@ export function PromptGroup({ defaultAgent: "claude", fallbackAgent: "none", validAgents: ["none", ...selectableAgentIds], - agentsReady: agentPresetsQuery.isFetched, + agentsReady: agentsFetched, }); - // โ”€โ”€ Link commands โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - const [issueLinkOpen, setIssueLinkOpen] = useState(false); - const [gitHubIssueLinkOpen, setGitHubIssueLinkOpen] = useState(false); - const [prLinkOpen, setPRLinkOpen] = useState(false); - const plusMenuRef = useRef(null); const trimmedPrompt = prompt.trim(); const branchPreview = branchNameEdited ? sanitizeUserBranchName(branchName) @@ -299,46 +296,56 @@ export function PromptGroup({
- requestAnimationFrame(() => setIssueLinkOpen(true)) - } - onOpenGitHubIssue={() => - requestAnimationFrame(() => setGitHubIssueLinkOpen(true)) + linearIssueTrigger={ + + + + + } - onOpenPRLink={() => - requestAnimationFrame(() => setPRLinkOpen(true)) + githubIssueTrigger={ + + addLinkedGitHubIssue( + issue.issueNumber, + issue.title, + issue.url, + issue.state, + ) + } + projectId={projectId} + hostTarget={hostTarget} + tooltipLabel="Link GitHub issue" + > + + + + } - /> - - - addLinkedGitHubIssue( - issue.issueNumber, - issue.title, - issue.url, - issue.state, - ) + prTrigger={ + + + + + } - projectId={projectId} - hostTarget={hostTarget} - anchorRef={plusMenuRef} - /> -
+ updateDraft({ hostTarget: t })} + /> @@ -389,10 +400,11 @@ export function PromptGroup({
- updateDraft({ hostTarget: t })} - /> + {selectedProject?.needsSetup === true && ( + + Project needs to be set up + + )} {modKey}โ†ต diff --git a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/components/DevicePicker/DevicePicker.tsx b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/components/DevicePicker/DevicePicker.tsx index 025faea3eef..c9136bd7462 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/components/DevicePicker/DevicePicker.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/components/DevicePicker/DevicePicker.tsx @@ -1,4 +1,3 @@ -import { Button } from "@superset/ui/button"; import { DropdownMenu, DropdownMenuContent, @@ -9,6 +8,7 @@ import { DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@superset/ui/dropdown-menu"; +import { cn } from "@superset/ui/utils"; import { HiCheck, HiChevronUpDown, @@ -16,15 +16,30 @@ import { HiOutlineComputerDesktop, HiOutlineServer, } from "react-icons/hi2"; +import { FormPickerTrigger } from "../../PromptGroup/components/FormPickerTrigger"; import { useWorkspaceHostOptions, type WorkspaceHostOption, } from "./hooks/useWorkspaceHostOptions"; import type { WorkspaceHostTarget } from "./types"; +function OnlineDot({ online }: { online: boolean }) { + return ( + + ); +} + interface DevicePickerProps { hostTarget: WorkspaceHostTarget; onSelectHostTarget: (target: WorkspaceHostTarget) => void; + className?: string; } function getHostIcon(host: WorkspaceHostOption) { @@ -65,6 +80,7 @@ function getSelectedIcon( export function DevicePicker({ hostTarget, onSelectHostTarget, + className, }: DevicePickerProps) { const { currentDeviceName, otherHosts } = useWorkspaceHostOptions(); const selectedLabel = getSelectedLabel( @@ -72,19 +88,31 @@ export function DevicePicker({ currentDeviceName, otherHosts, ); + // Only remote hosts have a meaningful online indicator โ€” the app itself + // is the local host, so it's tautologically online. + const selectedRemoteOnline = + hostTarget.kind === "host" + ? (otherHosts.find((host) => host.id === hostTarget.hostId)?.isOnline ?? + false) + : null; return ( - + - + onSelectHostTarget({ kind: "local" })} > @@ -117,10 +145,11 @@ export function DevicePicker({ } > -
-
{host.name}
-
- {isSelected && } + {host.name} + + {isSelected && ( + + )}
); })} diff --git a/apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts b/apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts index 8cc31ea07b9..438d1b5be51 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts @@ -12,6 +12,15 @@ function getNextTabOrder(items: Array<{ tabOrder: number }>): number { return maxTabOrder + 1; } +function getPrependTabOrder(items: Array<{ tabOrder: number }>): number { + if (items.length === 0) return 1; + const minTabOrder = items.reduce( + (minValue, item) => Math.min(minValue, item.tabOrder), + Number.POSITIVE_INFINITY, + ); + return minTabOrder - 1; +} + function ensureSidebarProjectRecord( collections: Pick, projectId: string, @@ -60,7 +69,7 @@ function ensureSidebarWorkspaceRecord( createdAt: new Date(), sidebarState: { projectId, - tabOrder: getNextTabOrder(topLevelOrders), + tabOrder: getPrependTabOrder(topLevelOrders), sectionId: null, }, paneLayout: { diff --git a/apps/desktop/src/renderer/routes/_authenticated/layout.tsx b/apps/desktop/src/renderer/routes/_authenticated/layout.tsx index a7044fcefc3..5c91c31670c 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/layout.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/layout.tsx @@ -17,28 +17,26 @@ import { useUpdateListener } from "renderer/components/UpdateToast"; import { env } from "renderer/env.renderer"; import { useIsV2CloudEnabled } from "renderer/hooks/useIsV2CloudEnabled"; import { useOnlineStatus } from "renderer/hooks/useOnlineStatus"; -import { isTearoffWindow } from "renderer/hooks/useTearoffInit/useTearoffInit"; import { migrateHotkeyOverrides } from "renderer/hotkeys/migrate"; import { authClient, getAuthToken } from "renderer/lib/auth-client"; -import { dispatchBrowserShortcutEvent } from "renderer/lib/browser-shortcut-events"; import { dragDropManager } from "renderer/lib/dnd"; import { electronTrpc } from "renderer/lib/electron-trpc"; import { showWorkspaceAutoNameWarningToast } from "renderer/lib/workspaces/showWorkspaceAutoNameWarningToast"; -import { LanguageServicesProvider } from "renderer/providers/LanguageServicesProvider"; import { InitGitDialog } from "renderer/react-query/projects/InitGitDialog"; import { DashboardNewWorkspaceModal } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal"; -import { GitOperationDialog } from "renderer/screens/main/components/GitOperationDialog"; +import { WorkspaceInitEffects } from "renderer/screens/main/components/WorkspaceInitEffects"; import { useSettingsStore } from "renderer/stores/settings-state"; import { useTabsStore } from "renderer/stores/tabs/store"; import { useAgentHookListener } from "renderer/stores/tabs/useAgentHookListener"; import { setPaneWorkspaceRunState } from "renderer/stores/tabs/workspace-run"; import { useWorkspaceInitStore } from "renderer/stores/workspace-init"; import { MOCK_ORG_ID, NOTIFICATION_EVENTS } from "shared/constants"; +import { AgentHooks } from "./components/AgentHooks"; import { GlobalTerminalLifecycle } from "./components/GlobalTerminalLifecycle"; -import { MainWindowEffects } from "./components/MainWindowEffects"; import { TeardownLogsDialog } from "./components/TeardownLogsDialog"; import { createPierreWorker } from "./lib/pierreWorker"; import { CollectionsProvider } from "./providers/CollectionsProvider"; +import { DeletingWorkspacesProvider } from "./providers/DeletingWorkspacesProvider"; import { LocalHostServiceProvider } from "./providers/LocalHostServiceProvider"; export const Route = createFileRoute("/_authenticated")({ @@ -59,7 +57,6 @@ function AuthenticatedLayout() { const setOriginRoute = useSettingsStore((s) => s.setOriginRoute); const utils = electronTrpc.useUtils(); const shownWorkspaceInitWarningsRef = useRef(new Set()); - const redirectingToSignIn = useRef(false); const { isV2CloudEnabled } = useIsV2CloudEnabled(); const isSignedIn = env.SKIP_ENV_VALIDATION || !!session?.user; @@ -77,9 +74,7 @@ function AuthenticatedLayout() { }); }, []); - // Update workspace-run pane state on terminal exit. - // Each window has its own useTabsStore, so the paneId lookup below naturally - // scopes the update to the window that actually owns the pane. + // Update workspace-run pane state on terminal exit electronTrpc.notifications.subscribe.useSubscription(undefined, { onData: (event) => { if ( @@ -109,15 +104,6 @@ function AuthenticatedLayout() { const updateInitProgress = useWorkspaceInitStore((s) => s.updateProgress); electronTrpc.workspaces.onInitProgress.useSubscription(undefined, { onData: (progress) => { - // React Query cache invalidation runs in every window (including - // tearoff) since each BrowserWindow has its own QueryClient and may - // be displaying the affected workspace. - if (progress.step === "ready" || progress.step === "failed") { - utils.workspaces.getAllGrouped.invalidate(); - utils.workspaces.get.invalidate({ id: progress.workspaceId }); - } - // The rest (progress store, toast, navigate) is main-window only. - if (isTearoffWindow()) return; updateInitProgress(progress); if ( progress.warning && @@ -131,6 +117,11 @@ function AuthenticatedLayout() { }, }); } + if (progress.step === "ready" || progress.step === "failed") { + // Invalidate both the grouped list AND the specific workspace + utils.workspaces.getAllGrouped.invalidate(); + utils.workspaces.get.invalidate({ id: progress.workspaceId }); + } }, onError: (error) => { console.error("[workspace-init-subscription] Subscription error:", error); @@ -140,39 +131,17 @@ function AuthenticatedLayout() { // Menu navigation subscription electronTrpc.menu.subscribe.useSubscription(undefined, { onData: (event) => { - if (isTearoffWindow()) return; if (event.type === "open-settings") { const section = event.data.section || "account"; navigate({ to: `/settings/${section}` as "/settings/account" }); } else if (event.type === "open-workspace") { navigate({ to: `/workspace/${event.data.workspaceId}` }); - } else if (event.type === "browser-action") { - dispatchBrowserShortcutEvent(event.data.action); } }, }); - // Redirect to sign-in via useEffect to avoid React infinite update loops. - // can re-trigger during concurrent renders when already at the - // target URL, causing router.load() โ†’ setState โ†’ re-render cycles. - const shouldRedirectToSignIn = - (!env.SKIP_ENV_VALIDATION && isPending && !hasLocalToken) || - (!isSignedIn && - !(hasLocalToken && !isOnline) && - !(isPending || (isRefetching && !session?.user && hasLocalToken))); - - useEffect(() => { - if (shouldRedirectToSignIn && !redirectingToSignIn.current) { - redirectingToSignIn.current = true; - void navigate({ to: "/sign-in", replace: true }); - } - if (!shouldRedirectToSignIn) { - redirectingToSignIn.current = false; - } - }, [shouldRedirectToSignIn, navigate]); - if (isPending && !hasLocalToken && !env.SKIP_ENV_VALIDATION) { - return null; + return ; } if ( (isPending || (isRefetching && !session?.user && hasLocalToken)) && @@ -203,7 +172,7 @@ function AuthenticatedLayout() { } if (!isSignedIn) { - return null; + return ; } if (!activeOrganizationId) { @@ -215,24 +184,24 @@ function AuthenticatedLayout() { - - - - - {isV2CloudEnabled ? ( - - ) : ( - - )} - - {/* FORK NOTE: GitOperationDialog kept for PR/Changes sidebar prompts */} - - - - + + + + + + {isV2CloudEnabled ? ( + + ) : ( + + )} + + + + + diff --git a/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/DeletingWorkspacesProvider.tsx b/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/DeletingWorkspacesProvider.tsx new file mode 100644 index 00000000000..72f477304af --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/DeletingWorkspacesProvider.tsx @@ -0,0 +1,76 @@ +import { + createContext, + type ReactNode, + useCallback, + useContext, + useMemo, + useState, +} from "react"; + +interface DeletingWorkspacesContextValue { + isDeleting: (workspaceId: string) => boolean; + markDeleting: (workspaceId: string) => void; + clearDeleting: (workspaceId: string) => void; +} + +const DeletingWorkspacesContext = + createContext(null); + +/** + * Tracks workspaces whose `workspaceCleanup.destroy` call is in flight. + * The sidebar hides these rows optimistically so users get instant feedback + * instead of watching the row sit there during the 10โ€“20s destroy window. + * On error the caller calls `clearDeleting` and the row reappears; on + * success the row is naturally unmounted via `v2WorkspaceLocalState.delete`. + */ +export function DeletingWorkspacesProvider({ + children, +}: { + children: ReactNode; +}) { + const [ids, setIds] = useState>(() => new Set()); + + const isDeleting = useCallback( + (workspaceId: string) => ids.has(workspaceId), + [ids], + ); + + const markDeleting = useCallback((workspaceId: string) => { + setIds((prev) => { + if (prev.has(workspaceId)) return prev; + const next = new Set(prev); + next.add(workspaceId); + return next; + }); + }, []); + + const clearDeleting = useCallback((workspaceId: string) => { + setIds((prev) => { + if (!prev.has(workspaceId)) return prev; + const next = new Set(prev); + next.delete(workspaceId); + return next; + }); + }, []); + + const value = useMemo( + () => ({ isDeleting, markDeleting, clearDeleting }), + [isDeleting, markDeleting, clearDeleting], + ); + + return ( + + {children} + + ); +} + +export function useDeletingWorkspaces() { + const ctx = useContext(DeletingWorkspacesContext); + if (!ctx) { + throw new Error( + "useDeletingWorkspaces must be used within DeletingWorkspacesProvider", + ); + } + return ctx; +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/index.ts b/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/index.ts new file mode 100644 index 00000000000..be08e18fe85 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/providers/DeletingWorkspacesProvider/index.ts @@ -0,0 +1,4 @@ +export { + DeletingWorkspacesProvider, + useDeletingWorkspaces, +} from "./DeletingWorkspacesProvider"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/FontSettingSection/components/FontFamilyCombobox/FontFamilyCombobox.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/FontSettingSection/components/FontFamilyCombobox/FontFamilyCombobox.tsx index 2f88f8d9a75..12cb52659a1 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/FontSettingSection/components/FontFamilyCombobox/FontFamilyCombobox.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/appearance/components/AppearanceSettings/components/FontSettingSection/components/FontFamilyCombobox/FontFamilyCombobox.tsx @@ -56,6 +56,11 @@ export function FontFamilyCombobox({ return { nerdFonts: nerd, monoFonts: mono, otherFonts: other }; }, [fonts]); + // Terminal fonts must be monospace โ€” arbitrary free-form names would let + // users pick proportional fonts (see issue #3513), so the custom-entry + // escape hatches below are gated off for the terminal variant. + const allowCustomEntry = variant !== "terminal"; + const hasExactMatch = useMemo(() => { if (!search.trim()) return true; const lower = search.toLowerCase().trim(); @@ -120,7 +125,7 @@ export function FontFamilyCombobox({ /> - {search.trim() ? ( + {allowCustomEntry && search.trim() ? ( +
+
+
+ + {comment.body} + +
+
+
+ )} + + ); +} + +const mermaidPlugins = { mermaid }; + +const MERMAID_DARK_VARS = { + background: "#1e1e2e", + primaryColor: "#313244", + primaryTextColor: "#cdd6f4", + primaryBorderColor: "#45475a", + secondaryColor: "#313244", + secondaryTextColor: "#cdd6f4", + secondaryBorderColor: "#45475a", + tertiaryColor: "#313244", + tertiaryTextColor: "#cdd6f4", + tertiaryBorderColor: "#45475a", + nodeBorder: "#45475a", + nodeTextColor: "#cdd6f4", + mainBkg: "#313244", + clusterBkg: "#1e1e2e", + titleColor: "#cdd6f4", + edgeLabelBackground: "transparent", + lineColor: "#6c7086", + textColor: "#cdd6f4", +}; + +const MERMAID_LIGHT_VARS = { + background: "#ffffff", + primaryColor: "#f0f0f4", + primaryTextColor: "#1e1e2e", + primaryBorderColor: "#d0d0d8", + lineColor: "#888", + textColor: "#1e1e2e", +}; + +function CommentCodeBlock({ + className, + children, +}: { + className?: string; + children?: ReactNode; +}) { + const theme = useTheme(); + const isDark = theme?.type !== "light"; + + const match = /language-(\w+)/.exec(className || ""); + const language = match ? match[1] : undefined; + const codeString = String(children).replace(/\n$/, ""); + + if (language === "mermaid") { + return ( + + {`\`\`\`mermaid\n${codeString}\n\`\`\``} + + ); + } + + if (!language) { + return ( + + {children} + + ); + } + + return ( + + } + language={language} + PreTag="div" + className="rounded-md text-sm" + > + {codeString} + + ); +} + +const commentComponents = { + code: CommentCodeBlock, + table: ({ children }: { children?: ReactNode }) => ( + {children} + ), +}; + +function CopyableTable({ children }: { children?: ReactNode }) { + const tableRef = useRef(null); + const [copied, setCopied] = useState(false); + const timerRef = useRef | null>(null); + const isMountedRef = useRef(true); + + useEffect(() => { + return () => { + isMountedRef.current = false; + if (timerRef.current) clearTimeout(timerRef.current); + }; + }, []); + + const handleCopy = useCallback(() => { + const el = tableRef.current; + if (!el) return; + + const rows = el.querySelectorAll("tr"); + const lines: string[] = []; + for (const row of rows) { + const cells = row.querySelectorAll("th, td"); + const values: string[] = []; + for (const cell of cells) { + values.push((cell.textContent ?? "").trim()); + } + lines.push(values.join("\t")); + } + const text = lines.join("\n"); + void electronTrpcClient.external.copyText + .mutate(text) + .then(() => { + if (!isMountedRef.current) return; + if (timerRef.current) clearTimeout(timerRef.current); + setCopied(true); + timerRef.current = setTimeout(() => { + if (!isMountedRef.current) return; + setCopied(false); + timerRef.current = null; + }, 1500); + }) + .catch((err) => { + console.warn("Failed to copy table text", err); + }); + }, []); + + return ( +
+ +
+ + {children} +
+
+
+ ); +} diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/comment-pane.css b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/comment-pane.css new file mode 100644 index 00000000000..c0333e827ce --- /dev/null +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/comment-pane.css @@ -0,0 +1,263 @@ +.comment-pane-markdown { + color: var(--foreground); + background: var(--background); + font-size: 0.875rem; + line-height: 1.625; + -webkit-font-smoothing: antialiased; +} + +.comment-pane-markdown article { + width: 100%; +} + +/* Headings */ +.comment-pane-markdown h1 { + font-size: 1.75rem; + font-weight: 700; + line-height: 1.25; + margin-top: 0; + margin-bottom: 0.75rem; + letter-spacing: -0.02em; +} + +.comment-pane-markdown h2 { + font-size: 1.35rem; + font-weight: 600; + line-height: 1.3; + margin-top: 1.5rem; + margin-bottom: 0.625rem; +} + +.comment-pane-markdown h3 { + font-size: 1.1rem; + font-weight: 600; + line-height: 1.4; + margin-top: 1.25rem; + margin-bottom: 0.5rem; +} + +.comment-pane-markdown h4, +.comment-pane-markdown h5, +.comment-pane-markdown h6 { + font-size: 0.95rem; + font-weight: 600; + line-height: 1.5; + margin-top: 1rem; + margin-bottom: 0.375rem; +} + +/* First child no top margin */ +.comment-pane-markdown article > *:first-child { + margin-top: 0; +} + +/* Paragraphs */ +.comment-pane-markdown p { + margin-top: 0; + margin-bottom: 0.75rem; +} + +/* Links */ +.comment-pane-markdown a { + color: var(--primary); + text-decoration: underline; + text-underline-offset: 2px; +} + +.comment-pane-markdown a:hover { + opacity: 0.8; +} + +/* Strong & emphasis */ +.comment-pane-markdown strong { + font-weight: 600; +} + +.comment-pane-markdown em { + font-style: italic; +} + +/* Lists */ +.comment-pane-markdown ul, +.comment-pane-markdown ol { + margin-top: 0; + margin-bottom: 0.75rem; + padding-left: 1.5rem; +} + +.comment-pane-markdown ul { + list-style-type: disc; +} + +.comment-pane-markdown ol { + list-style-type: decimal; +} + +.comment-pane-markdown li { + margin-bottom: 0.25rem; +} + +.comment-pane-markdown li > ul, +.comment-pane-markdown li > ol { + margin-top: 0.25rem; + margin-bottom: 0; +} + +/* Tables โ€” full width with borders */ +.comment-pane-markdown table { + width: 100%; + border-collapse: collapse; + margin: 0.75rem 0; + font-size: 0.8125rem; +} + +.comment-pane-markdown th, +.comment-pane-markdown td { + border: 1px solid var(--border); + padding: 0.5rem 0.75rem; + vertical-align: middle; +} + +.comment-pane-markdown th { + font-weight: 500; + text-align: left; + background: color-mix(in srgb, var(--muted) 50%, transparent); +} + +.comment-pane-markdown td img { + display: inline-block; + vertical-align: middle; +} + +/* Blockquotes */ +.comment-pane-markdown blockquote { + border-left: 3px solid var(--border); + padding-left: 1rem; + margin: 0.75rem 0; + color: var(--muted-foreground); +} + +.comment-pane-markdown blockquote p:last-child { + margin-bottom: 0; +} + +/* Horizontal rules */ +.comment-pane-markdown hr { + border: none; + border-top: 1px solid var(--border); + margin: 1.5rem 0; +} + +/* Code โ€” inline */ +.comment-pane-markdown code { + font-family: var(--font-mono, ui-monospace, monospace); + font-size: 0.8125rem; + background: color-mix(in srgb, var(--muted) 60%, transparent); + padding: 0.125rem 0.375rem; + border-radius: 0.25rem; +} + +/* Code โ€” blocks */ +.comment-pane-markdown pre { + margin: 0.75rem 0; + padding: 0.75rem 1rem; + background: color-mix(in srgb, var(--muted) 40%, transparent); + border-radius: 0.375rem; + overflow-x: auto; +} + +.comment-pane-markdown pre code { + background: none; + padding: 0; + border-radius: 0; + font-size: 0.8125rem; + line-height: 1.5; +} + +/* Images */ +.comment-pane-markdown img { + max-width: 100%; + height: auto; + border-radius: 0.375rem; +} + +/* Details/summary (common in GitHub bot comments) */ +.comment-pane-markdown details { + margin: 0.75rem 0; + border: 1px solid var(--border); + border-radius: 0.375rem; + overflow: hidden; +} + +.comment-pane-markdown details > summary { + cursor: pointer; + padding: 0.5rem 0.75rem; + font-weight: 500; + background: color-mix(in srgb, var(--muted) 30%, transparent); + user-select: none; +} + +.comment-pane-markdown details > summary:hover { + background: color-mix(in srgb, var(--muted) 50%, transparent); +} + +.comment-pane-markdown details[open] > summary { + border-bottom: 1px solid var(--border); +} + +.comment-pane-markdown details > *:not(summary) { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.comment-pane-markdown details > p:first-of-type { + margin-top: 0.5rem; +} + +/* Task lists (checkboxes) */ +.comment-pane-markdown .task-list-item { + list-style: none; + display: flex; + align-items: flex-start; + gap: 0.5rem; +} + +.comment-pane-markdown .task-list-item input[type="checkbox"] { + margin-top: 0.25rem; +} + +/* Sub text */ +.comment-pane-markdown sub { + font-size: 0.75rem; + color: var(--muted-foreground); +} + +/* Strikethrough */ +.comment-pane-markdown del { + text-decoration: line-through; + opacity: 0.6; +} + +/* Mermaid diagrams */ +.comment-pane-markdown [data-streamdown="mermaid-block"] { + margin: 0.75rem 0; + border-radius: 0.375rem; + background: transparent; + border: none; + padding: 0; +} + +/* Hide "mermaid" label + action buttons */ +.comment-pane-markdown [data-streamdown="mermaid-block"] > .flex.h-8 { + display: none; +} + +.comment-pane-markdown [data-streamdown="mermaid-block-actions"] { + display: none; +} + +/* Remove the inner wrapper background */ +.comment-pane-markdown [data-streamdown="mermaid-block"] > div:last-child { + background: transparent; + border: none; +} diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/index.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/index.ts new file mode 100644 index 00000000000..ed0e956694b --- /dev/null +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/CommentPane/index.ts @@ -0,0 +1 @@ +export { CommentPane } from "./CommentPane"; diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx index dcd75e5bc4c..52d680bb4fb 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx @@ -23,6 +23,7 @@ import { useTheme } from "renderer/stores/theme"; import { ActionLogsPane } from "./ActionLogsPane"; import { BrowserPane } from "./BrowserPane"; import { ChatPane } from "./ChatPane"; +import { CommentPane } from "./CommentPane"; import { MosaicSplitOverlay } from "./components"; import { DatabaseExplorerPane } from "./DatabaseExplorerPane"; import { DevToolsPane } from "./DevToolsPane"; @@ -435,6 +436,20 @@ export function TabView({ tab, isWorkspaceActive }: TabViewProps) { ); } + // Route comment panes + if (paneInfo.type === "comment") { + return ( + + ); + } + // Default: terminal panes return ( { if (!fontSettings) return; - const family = - fontSettings.terminalFontFamily || DEFAULT_TERMINAL_FONT_FAMILY; + const family = sanitizeTerminalFontFamily(fontSettings.terminalFontFamily); const size = fontSettings.terminalFontSize ?? DEFAULT_TERMINAL_FONT_SIZE; const result = v1TerminalCache.updateAppearance(paneId, family, size); if (result?.changed) { diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts index 72a20cfe225..f4d9e5eee78 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts @@ -283,15 +283,6 @@ export interface KeyboardHandlerOptions { onOpenSuggestions?: () => void; } -export interface PasteHandlerOptions { - /** Callback when text is pasted, receives the pasted text */ - onPaste?: (text: string) => void; - /** Optional direct write callback to bypass xterm's paste burst */ - onWrite?: (data: string) => void; - /** Whether bracketed paste mode is enabled for the current terminal */ - isBracketedPasteEnabled?: () => boolean; -} - /** * Setup copy handler for xterm to trim trailing whitespace from copied text. * @@ -336,154 +327,6 @@ export function setupCopyHandler(xterm: XTerm): () => void { }; } -/** - * Setup paste handler for xterm to ensure bracketed paste mode works correctly. - * - * xterm.js's built-in paste handling via the textarea should work, but in some - * Electron environments the clipboard events may not propagate correctly. - * This handler explicitly intercepts paste events and uses xterm's paste() method, - * which properly handles bracketed paste mode (wrapping pasted content with - * \x1b[200~ and \x1b[201~ escape sequences when the shell has enabled it). - * - * This is required for TUI applications like opencode, vim, etc. that expect - * bracketed paste mode to distinguish between typed and pasted content. - * - * Returns a cleanup function to remove the handler. - */ -export function setupPasteHandler( - xterm: XTerm, - options: PasteHandlerOptions = {}, -): () => void { - const textarea = xterm.textarea; - if (!textarea) return () => {}; - - let cancelActivePaste: (() => void) | null = null; - - const shouldForwardCtrlVForNonTextPaste = ( - event: ClipboardEvent, - text: string, - ): boolean => { - if (text) return false; - const types = Array.from(event.clipboardData?.types ?? []); - if (types.length === 0) return false; - return types.some((type) => type !== "text/plain"); - }; - - const handlePaste = (event: ClipboardEvent) => { - const text = event.clipboardData?.getData("text/plain") ?? ""; - if (!text) { - // Match terminal behavior like iTerm's "Paste or send ^V": - // when clipboard has non-text payloads but no plain text, forward Ctrl+V. - if (options.onWrite && shouldForwardCtrlVForNonTextPaste(event, text)) { - event.preventDefault(); - event.stopImmediatePropagation(); - options.onWrite("\x16"); - } - return; - } - - event.preventDefault(); - event.stopImmediatePropagation(); - - options.onPaste?.(text); - - // Cancel any in-flight chunked paste to avoid overlapping writes. - cancelActivePaste?.(); - cancelActivePaste = null; - - // Chunk large pastes to avoid sending a single massive input burst that can - // overwhelm the PTY pipeline (especially when the app is repainting heavily). - const MAX_SYNC_PASTE_CHARS = 16_384; - - // If no direct write callback is provided, fall back to xterm's paste() - // (it handles newline normalization and bracketed paste mode internally). - if (!options.onWrite) { - const CHUNK_CHARS = 4096; - const CHUNK_DELAY_MS = 5; - - if (text.length <= MAX_SYNC_PASTE_CHARS) { - xterm.paste(text); - return; - } - - let cancelled = false; - let offset = 0; - - const pasteNext = () => { - if (cancelled) return; - - const chunk = text.slice(offset, offset + CHUNK_CHARS); - offset += CHUNK_CHARS; - xterm.paste(chunk); - - if (offset < text.length) { - setTimeout(pasteNext, CHUNK_DELAY_MS); - } - }; - - cancelActivePaste = () => { - cancelled = true; - }; - - pasteNext(); - return; - } - - // Direct write path: replicate xterm's paste normalization, but stream in - // controlled chunks while preserving bracketed-paste semantics. - const preparedText = text.replace(/\r?\n/g, "\r"); - const bracketedPasteEnabled = options.isBracketedPasteEnabled?.() ?? false; - const shouldBracket = bracketedPasteEnabled; - - // For small/medium pastes, preserve the fast path and avoid timers. - if (preparedText.length <= MAX_SYNC_PASTE_CHARS) { - options.onWrite( - shouldBracket ? `\x1b[200~${preparedText}\x1b[201~` : preparedText, - ); - return; - } - - let cancelled = false; - let offset = 0; - const CHUNK_CHARS = 16_384; - const CHUNK_DELAY_MS = 0; - - const pasteNext = () => { - if (cancelled) return; - - const chunk = preparedText.slice(offset, offset + CHUNK_CHARS); - offset += CHUNK_CHARS; - - if (shouldBracket) { - // Wrap each chunk to avoid long-running "open" bracketed paste blocks, - // which some TUIs may defer repainting until the closing sequence arrives. - options.onWrite?.(`\x1b[200~${chunk}\x1b[201~`); - } else { - options.onWrite?.(chunk); - } - - if (offset < preparedText.length) { - setTimeout(pasteNext, CHUNK_DELAY_MS); - return; - } - }; - - cancelActivePaste = () => { - cancelled = true; - }; - - pasteNext(); - }; - - textarea.addEventListener("paste", handlePaste, { capture: true }); - - return () => { - cancelActivePaste?.(); - cancelActivePaste = null; - textarea.removeEventListener("paste", handlePaste, { capture: true }); - }; -} - /** * Setup keyboard handling for xterm including: * - Shortcut forwarding: App hotkeys bubble to document where useAppHotkey listens diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts index 62ac4df05d9..fa3efc25bd2 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts @@ -23,7 +23,6 @@ import { setupCopyHandler, setupFocusListener, setupKeyboardHandler, - setupPasteHandler, } from "../helpers"; import { isPaneDestroyed } from "../pane-guards"; import { coldRestoreState, pendingDetaches } from "../state"; @@ -129,7 +128,6 @@ export interface UseTerminalLifecycleOptions { flushPendingEvents: () => void; resetModes: () => void; isAlternateScreenRef: MutableRefObject; - isBracketedPasteRef: MutableRefObject; setPaneNameRef: MutableRefObject<(paneId: string, name: string) => void>; renameUnnamedWorkspaceRef: MutableRefObject<(title: string) => void>; handleTerminalFocusRef: MutableRefObject<() => void>; @@ -194,7 +192,6 @@ export function useTerminalLifecycle({ flushPendingEvents, resetModes, isAlternateScreenRef, - isBracketedPasteRef, setPaneNameRef, renameUnnamedWorkspaceRef, handleTerminalFocusRef, @@ -891,15 +888,7 @@ export function useTerminalLifecycle({ const cleanupFocus = setupFocusListener(xterm, () => handleTerminalFocusRef.current(), ); - const cleanupPaste = setupPasteHandler(xterm, { - onPaste: (text) => { - if (!isAlternateScreenRef.current) { - commandBufferRef.current += text; - } - }, - onWrite: handleWrite, - isBracketedPasteEnabled: () => isBracketedPasteRef.current, - }); + const cleanupCopy = setupCopyHandler(xterm); const isPaneDestroyedInStore = () => @@ -936,7 +925,6 @@ export function useTerminalLifecycle({ cleanupKeyboard(); cleanupClickToMove(); cleanupFocus?.(); - cleanupPaste(); cleanupCopy(); unregisterClearCallbackRef.current(paneId); unregisterScrollToBottomCallbackRef.current(paneId); diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx index 8efd3389d78..c12401e68d1 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ReviewPanel/ReviewPanel.tsx @@ -1,47 +1,26 @@ import type { GitHubStatus, PullRequestComment } from "@superset/local-db"; -import { Avatar as UserAvatar } from "@superset/ui/atoms/Avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@superset/ui/avatar"; -import { Button } from "@superset/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@superset/ui/collapsible"; -import { - Command, - CommandEmpty, - CommandInput, - CommandItem, - CommandList, -} from "@superset/ui/command"; -import { Popover, PopoverContent, PopoverTrigger } from "@superset/ui/popover"; import { Skeleton } from "@superset/ui/skeleton"; import { toast } from "@superset/ui/sonner"; -import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip"; import { cn } from "@superset/ui/utils"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { LuArrowUpRight, LuCheck, - LuChevronDown, - LuCode, + LuCheckCheck, LuCopy, - LuExternalLink, LuLoaderCircle, - LuMessageSquarePlus, - LuRefreshCw, - LuReply, - LuX, + LuUndo2, } from "react-icons/lu"; import { VscChevronRight } from "react-icons/vsc"; import { electronTrpc } from "renderer/lib/electron-trpc"; -import { showGitConfirmDialog } from "renderer/lib/git/gitConfirmDialog"; import { PRIcon } from "renderer/screens/main/components/PRIcon"; -import { useWorkspaceId } from "renderer/screens/main/components/WorkspaceView/WorkspaceIdContext"; -import { useTabsStore } from "renderer/stores/tabs"; -import { CheckSteps } from "./components/CheckSteps"; -import { CommentBody } from "./components/CommentBody"; -import { ReplyDialog } from "./components/ReplyDialog"; +import { useTabsStore } from "renderer/stores/tabs/store"; import { ALL_COMMENTS_COPY_ACTION_KEY, buildAllCommentsClipboardText, @@ -58,151 +37,52 @@ import { splitPullRequestComments, } from "./utils"; -function buildIdentitySummary(items: string[]): string { - if (items.length === 0) { - return "None"; - } - - if (items.length <= 2) { - return items.join(", "); - } - - return `${items.slice(0, 2).join(", ")} +${items.length - 2}`; -} - -function getCheckKey( - check: NonNullable["checks"][number], - index: number, -): string { - return `${check.name}:${check.url ?? "no-url"}:${index}`; -} - interface ReviewPanelProps { pr: GitHubStatus["pr"] | null; comments?: PullRequestComment[]; isLoading?: boolean; isCommentsLoading?: boolean; - commentsQueryInput?: { - workspaceId: string; - prNumber?: number; - prUrl?: string; - repoUrl?: string; - upstreamUrl?: string; - isFork?: boolean; - }; - onOpenFile?: (path: string, line?: number) => void; - onRefreshReview?: (scope?: "full" | "status") => Promise; + workspaceId?: string; + onCommentsChange?: () => void; } -type GitHubStatusCacheValue = GitHubStatus | null | undefined; - export function ReviewPanel({ pr, comments = [], isLoading = false, isCommentsLoading = false, - commentsQueryInput, - onOpenFile, - onRefreshReview, + workspaceId, + onCommentsChange, }: ReviewPanelProps) { - const resolvedWorkspaceId = useWorkspaceId(); - const trpcUtils = electronTrpc.useUtils(); - const addBrowserTab = useTabsStore((s) => s.addBrowserTab); - const addActionLogsTab = useTabsStore((s) => s.addActionLogsTab); - const handleOpenUrl = useCallback( - (url: string, e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - if (resolvedWorkspaceId) { - addBrowserTab(resolvedWorkspaceId, url); - } - }, - [resolvedWorkspaceId, addBrowserTab], - ); - const [checksOpen, setChecksOpen] = useState(true); const [commentsOpen, setCommentsOpen] = useState(true); const [resolvedCommentsGroupOpen, setResolvedCommentsGroupOpen] = useState(false); const [copiedActionKey, setCopiedActionKey] = useState(null); - const [expandedChecks, setExpandedChecks] = useState>(new Set()); - const [expandedComments, setExpandedComments] = useState>( + const [resolvingThreadIds, setResolvingThreadIds] = useState>( new Set(), ); - const [reviewerSearch, setReviewerSearch] = useState(""); - const [assigneeSearch, setAssigneeSearch] = useState(""); - const [pendingThreadId, setPendingThreadId] = useState(null); - const [isDraftTogglePending, setIsDraftTogglePending] = useState(false); - const [replyTargetComment, setReplyTargetComment] = - useState(null); - const [isReplySubmitting, setIsReplySubmitting] = useState(false); - const [isNewCommentDialogOpen, setIsNewCommentDialogOpen] = useState(false); - const [isNewCommentSubmitting, setIsNewCommentSubmitting] = useState(false); - const [identityPopoverOpen, setIdentityPopoverOpen] = useState< - "reviewers" | "assignees" | null - >(null); - const [pendingIdentityGroup, setPendingIdentityGroup] = useState< - "reviewers" | "assignees" | null - >(null); + const [isResolvingAll, setIsResolvingAll] = useState(false); const copiedActionResetTimeoutRef = useRef | null>(null); const copyToClipboardMutation = electronTrpc.external.copyText.useMutation(); - const setPullRequestDraftStateMutation = - electronTrpc.workspaces.setPullRequestDraftState.useMutation(); - const setPullRequestThreadResolutionMutation = - electronTrpc.workspaces.setPullRequestThreadResolution.useMutation(); - const replyToPullRequestCommentMutation = - electronTrpc.workspaces.replyToPullRequestComment.useMutation(); - const updatePullRequestReviewersMutation = - electronTrpc.workspaces.updatePullRequestReviewers.useMutation(); - const updatePullRequestAssigneesMutation = - electronTrpc.workspaces.updatePullRequestAssignees.useMutation(); - const rerunPullRequestChecksMutation = - electronTrpc.workspaces.rerunPullRequestChecks.useMutation(); - const candidateKind = - identityPopoverOpen === "assignees" ? "assignee" : "reviewer"; - const canEditPullRequest = pr?.state === "open" || pr?.state === "draft"; - const [pendingRerunMode, setPendingRerunMode] = useState< - "all" | "failed" | null - >(null); - const setGitHubStatusCaches = useCallback( - ( - nextValue: - | GitHubStatusCacheValue - | ((current: GitHubStatusCacheValue) => GitHubStatusCacheValue), - ) => { - if (!resolvedWorkspaceId) { - return; - } - - trpcUtils.workspaces.getGitHubStatus.setData( - { workspaceId: resolvedWorkspaceId }, - nextValue, - ); - trpcUtils.workspaces.getGitHubStatus.setData( - { workspaceId: resolvedWorkspaceId, includePreview: true }, - nextValue, - ); - }, - [resolvedWorkspaceId, trpcUtils], - ); - const { - data: identityCandidates = [], - isLoading: isIdentityCandidatesLoading, - } = electronTrpc.workspaces.getPullRequestIdentityCandidates.useQuery( - { - workspaceId: resolvedWorkspaceId ?? "", - kind: candidateKind, - pullRequestUrl: pr?.url, - }, - { - enabled: - !!resolvedWorkspaceId && !!identityPopoverOpen && !!canEditPullRequest, - staleTime: 60_000, - refetchOnWindowFocus: false, - }, - ); + const resolveThreadMutation = + electronTrpc.workspaces.resolveReviewThread.useMutation(); + const openCommentPane = useTabsStore((s) => s.openCommentPane); + + const handleOpenComment = (comment: PullRequestComment) => { + if (!workspaceId) return; + openCommentPane(workspaceId, { + commentId: comment.id, + authorLogin: comment.authorLogin, + avatarUrl: comment.avatarUrl, + body: comment.body, + url: comment.url, + path: comment.path, + line: comment.line, + }); + }; useEffect(() => { return () => { @@ -250,297 +130,39 @@ export function ReviewPanel({ }); }; - const handleOpenReplyDialog = (comment: PullRequestComment) => { - setReplyTargetComment(comment); - }; - - const handleReplyDialogOpenChange = (open: boolean) => { - if (isReplySubmitting) { - return; - } - if (!open) { - setReplyTargetComment(null); - } - }; - - const handleSubmitReply = async (body: string) => { - if (!resolvedWorkspaceId || !replyTargetComment) { - return; - } - - setIsReplySubmitting(true); - try { - await replyToPullRequestCommentMutation.mutateAsync({ - workspaceId: resolvedWorkspaceId, - body, - threadId: replyTargetComment.threadId, - pullRequestNumber: pr?.number, - pullRequestUrl: pr?.url, - }); - toast.success("Reply posted"); - setReplyTargetComment(null); - void refreshReview("full"); - } catch (error) { - const message = error instanceof Error ? error.message : "Unknown error"; - toast.error(`Failed to post reply: ${message}`); - } finally { - setIsReplySubmitting(false); - } - }; + const handleToggleResolve = (comment: PullRequestComment) => { + const threadId = comment.threadId; + if (!workspaceId || !threadId) return; - const handleSubmitNewComment = async (body: string) => { - if (!resolvedWorkspaceId) { - return; - } - - setIsNewCommentSubmitting(true); - try { - await replyToPullRequestCommentMutation.mutateAsync({ - workspaceId: resolvedWorkspaceId, - body, - pullRequestNumber: pr?.number, - pullRequestUrl: pr?.url, - }); - toast.success("Comment posted"); - setIsNewCommentDialogOpen(false); - void refreshReview("full"); - } catch (error) { - const message = error instanceof Error ? error.message : "Unknown error"; - toast.error(`Failed to post comment: ${message}`); - } finally { - setIsNewCommentSubmitting(false); - } - }; - - const refreshReview = async (scope: "full" | "status" = "full") => { - if (!onRefreshReview) { - return; - } - - await onRefreshReview(scope); - }; - - const runToggleDraftState = () => { - if (!resolvedWorkspaceId || !pr) { - return; - } - - const nextIsDraft = pr.state !== "draft"; - const previousState = pr.state; - - setIsDraftTogglePending(true); - setGitHubStatusCaches((current) => { - if (!current?.pr) { - return current; - } - - return { - ...current, - pr: { - ...current.pr, - state: nextIsDraft ? "draft" : "open", + setResolvingThreadIds((prev) => new Set(prev).add(threadId)); + resolveThreadMutation.mutate( + { + workspaceId, + threadId, + resolve: !comment.isResolved, + }, + { + onSuccess: () => { + onCommentsChange?.(); }, - }; - }); - - void setPullRequestDraftStateMutation - .mutateAsync({ - workspaceId: resolvedWorkspaceId, - isDraft: nextIsDraft, - }) - .then(() => refreshReview("status")) - .catch((error) => { - const message = - error instanceof Error ? error.message : "Unknown error"; - setGitHubStatusCaches((current) => { - if (!current?.pr) { - return current; - } - - return { - ...current, - pr: { - ...current.pr, - state: previousState, - }, - }; - }); - toast.error(`Failed to update pull request: ${message}`); - void refreshReview("status"); - }) - .finally(() => { - setIsDraftTogglePending(false); - }); - }; - - const handleToggleDraftState = () => { - if (!pr) return; - const isConvertingToDraft = pr.state !== "draft"; - if (!isConvertingToDraft) { - runToggleDraftState(); - return; - } - showGitConfirmDialog({ - kind: "pr-draft-state-confirm", - tone: "warn", - title: "ใ“ใฎ PR ใ‚’ draft ใซๆˆปใ—ใพใ™ใ‹?", - description: - "ใƒฌใƒ“ใƒฅใ‚ขใƒผใฎใƒฌใƒ“ใƒฅใƒผ่ฆๆฑ‚ใŒ่งฃ้™คใ•ใ‚Œใ€reviewer workflow ใŒๅทปใๆˆปใ‚Šใพใ™ใ€‚", - confirmLabel: "draft ใซๆˆปใ™", - confirmVariant: "primary", - onConfirm: runToggleDraftState, - }); - }; - - const handleToggleThreadResolution = (comment: PullRequestComment) => { - if (!resolvedWorkspaceId || !comment.threadId) { - return; - } - - const nextResolved = comment.isResolved !== true; - const updateThreadResolutionInCache = (isResolved: boolean) => { - if (!commentsQueryInput) { - return; - } - - trpcUtils.workspaces.getGitHubPRComments.setData( - commentsQueryInput, - (current) => - (current ?? []).map((item) => - item.threadId === comment.threadId - ? { - ...item, - isResolved, - } - : item, - ), - ); - }; - - setPendingThreadId(comment.threadId); - updateThreadResolutionInCache(nextResolved); - void setPullRequestThreadResolutionMutation - .mutateAsync({ - workspaceId: resolvedWorkspaceId, - threadId: comment.threadId, - isResolved: nextResolved, - }) - .then(() => refreshReview("full")) - .catch((error) => { - const message = - error instanceof Error ? error.message : "Unknown error"; - updateThreadResolutionInCache(comment.isResolved === true); - toast.error(`Failed to update conversation: ${message}`); - void refreshReview("full"); - }) - .finally(() => { - setPendingThreadId((current) => - current === comment.threadId ? null : current, - ); - }); - }; - - const toggleCheckExpansion = (checkKey: string) => { - setExpandedChecks((prev) => { - const next = new Set(prev); - if (next.has(checkKey)) { - next.delete(checkKey); - } else { - next.add(checkKey); - } - return next; - }); - }; - - const toggleCommentExpansion = (commentId: string) => { - setExpandedComments((prev) => { - const next = new Set(prev); - if (next.has(commentId)) { - next.delete(commentId); - } else { - next.add(commentId); - } - return next; - }); + onError: (error) => { + const message = + error instanceof Error ? error.message : "Unknown error"; + toast.error( + `Failed to ${comment.isResolved ? "undo" : "mark as done"}: ${message}`, + ); + }, + onSettled: () => { + setResolvingThreadIds((prev) => { + const next = new Set(prev); + next.delete(threadId); + return next; + }); + }, + }, + ); }; - const applyOptimisticMemberUpdate = useCallback( - ({ - kind, - add = [], - remove = [], - }: { - kind: "reviewer" | "assignee"; - add?: string[]; - remove?: string[]; - }) => { - if (!resolvedWorkspaceId) { - return; - } - - const normalizedAdd = Array.from( - new Set(add.map((value) => value.trim()).filter(Boolean)), - ); - const normalizedRemove = new Set( - remove.map((value) => value.trim()).filter(Boolean), - ); - - setGitHubStatusCaches((current) => { - if (!current?.pr) { - return current; - } - - const existingValues = - kind === "reviewer" - ? (current.pr.requestedReviewers ?? []) - : (current.pr.assignees ?? []); - const nextValues = Array.from( - new Set( - existingValues - .filter((value) => !normalizedRemove.has(value)) - .concat(normalizedAdd), - ), - ); - - return { - ...current, - pr: { - ...current.pr, - ...(kind === "reviewer" - ? { requestedReviewers: nextValues } - : { assignees: nextValues }), - }, - }; - }); - }, - [resolvedWorkspaceId, setGitHubStatusCaches], - ); - - const restoreOptimisticMemberUpdate = useCallback( - ({ kind, values }: { kind: "reviewer" | "assignee"; values: string[] }) => { - if (!resolvedWorkspaceId) { - return; - } - - setGitHubStatusCaches((current) => { - if (!current?.pr) { - return current; - } - - return { - ...current, - pr: { - ...current.pr, - ...(kind === "reviewer" - ? { requestedReviewers: values } - : { assignees: values }), - }, - }; - }); - }, - [resolvedWorkspaceId, setGitHubStatusCaches], - ); - if (isLoading && !pr) { return (
@@ -558,7 +180,6 @@ export function ReviewPanel({ } const requestedReviewers = pr.requestedReviewers ?? []; - const assignees = pr.assignees ?? []; const relevantChecks = pr.checks.filter( (check) => check.status !== "skipped" && check.status !== "cancelled", @@ -573,12 +194,6 @@ export function ReviewPanel({ const checksStatus = relevantChecks.length > 0 ? pr.checksStatus : "none"; const checksStatusConfig = checkSummaryIconConfig[checksStatus]; const ChecksStatusIcon = checksStatusConfig.icon; - const actionChecks = relevantChecks.filter((check) => - isActionsRunUrl(check.url), - ); - const failedActionChecks = actionChecks.filter( - (check) => check.status === "failure", - ); const { active: activeComments, resolved: resolvedComments } = splitPullRequestComments(comments); const commentsCountLabel = isCommentsLoading ? "..." : comments.length; @@ -593,344 +208,47 @@ export function ReviewPanel({ }); }; - const runRerunChecks = async (mode: "all" | "failed") => { - if (!resolvedWorkspaceId || pendingRerunMode) { - return; - } + const uniqueResolvableThreadIds = [ + ...new Set( + activeComments.map((c) => c.threadId).filter((id): id is string => !!id), + ), + ]; + const handleResolveAll = async () => { + if (!workspaceId || uniqueResolvableThreadIds.length === 0) return; - setPendingRerunMode(mode); - try { - const result = await rerunPullRequestChecksMutation.mutateAsync({ - workspaceId: resolvedWorkspaceId, - mode, - }); - toast.success( - mode === "failed" - ? `Re-ran failed jobs for ${result.rerunCount} workflow run${result.rerunCount === 1 ? "" : "s"}` - : `Re-ran ${result.rerunCount} workflow run${result.rerunCount === 1 ? "" : "s"}`, - ); - await refreshReview("status"); - void trpcUtils.workspaces.getJobLogs.invalidate(); - } catch (error) { - const message = error instanceof Error ? error.message : "Unknown error"; - toast.error(`Failed to rerun jobs: ${message}`); - } finally { - setPendingRerunMode((current) => (current === mode ? null : current)); - } - }; - - const handleRerunChecks = async (mode: "all" | "failed") => { - if (mode === "failed") { - await runRerunChecks(mode); - return; - } - // Title is deliberately neutral so it cannot conflict with the primary - // button label. Primary runs the safer "failed only" path to avoid - // re-queuing every job on an errant Enter keypress; "ๅ…จใฆๅ†ๅฎŸ่กŒ" is - // available as the secondary action for users who explicitly want it. - showGitConfirmDialog({ - kind: "rerun-all-checks-confirm", - tone: "warn", - title: "CI jobs ใ‚’ๅ†ๅฎŸ่กŒใ—ใพใ™ใ‹?", - description: - "้€šๅธธใฏๅคฑๆ•—ใ—ใŸใ‚ธใƒงใƒ–ใฎใฟๅ†ๅฎŸ่กŒใ—ใพใ™ใ€‚ใ™ในใฆใฎใ‚ธใƒงใƒ–ใ‚’ๅ†ใ‚ญใƒฅใƒผใ™ใ‚‹ใจใ‚ณใ‚นใƒˆใจใƒŽใ‚คใ‚บใŒๅคงใใใชใ‚‹ใฎใงๆณจๆ„ใ—ใฆใใ ใ•ใ„ใ€‚", - confirmLabel: "ๅคฑๆ•—ๅˆ†ใ ใ‘ๅ†ๅฎŸ่กŒ", - confirmVariant: "primary", - onConfirm: () => { - void runRerunChecks("failed"); - }, - secondaryLabel: "ๅ…จใฆๅ†ๅฎŸ่กŒ", - onSecondary: () => { - void runRerunChecks("all"); - }, - }); - }; - - const updateReviewers = async ({ - add = [], - remove = [], - onSuccess, - }: { - add?: string[]; - remove?: string[]; - onSuccess?: () => void; - }) => { - if (!resolvedWorkspaceId || pendingIdentityGroup === "reviewers") { - return; - } + const batchIds = uniqueResolvableThreadIds; + setIsResolvingAll(true); + setResolvingThreadIds((prev) => new Set([...prev, ...batchIds])); - const previousReviewers = [...requestedReviewers]; - setPendingIdentityGroup("reviewers"); try { - applyOptimisticMemberUpdate({ - kind: "reviewer", - add, - remove, - }); - await updatePullRequestReviewersMutation.mutateAsync({ - workspaceId: resolvedWorkspaceId, - add, - remove, - pullRequestNumber: pr?.number, - pullRequestUrl: pr?.url, - }); - onSuccess?.(); - void refreshReview("status"); - } catch (error) { - restoreOptimisticMemberUpdate({ - kind: "reviewer", - values: previousReviewers, - }); - const message = error instanceof Error ? error.message : "Unknown error"; - toast.error(`Failed to update reviewers: ${message}`); - void refreshReview("status"); - } finally { - setPendingIdentityGroup((current) => - current === "reviewers" ? null : current, + const results = await Promise.allSettled( + batchIds.map((threadId) => + resolveThreadMutation.mutateAsync({ + workspaceId, + threadId, + resolve: true, + }), + ), ); - } - }; - - const updateAssignees = async ({ - add = [], - remove = [], - onSuccess, - }: { - add?: string[]; - remove?: string[]; - onSuccess?: () => void; - }) => { - if (!resolvedWorkspaceId || pendingIdentityGroup === "assignees") { - return; - } - - const previousAssignees = [...assignees]; - setPendingIdentityGroup("assignees"); - try { - applyOptimisticMemberUpdate({ - kind: "assignee", - add, - remove, - }); - await updatePullRequestAssigneesMutation.mutateAsync({ - workspaceId: resolvedWorkspaceId, - add, - remove, - pullRequestNumber: pr?.number, - pullRequestUrl: pr?.url, - }); - onSuccess?.(); - void refreshReview("status"); - } catch (error) { - restoreOptimisticMemberUpdate({ - kind: "assignee", - values: previousAssignees, - }); - const message = error instanceof Error ? error.message : "Unknown error"; - toast.error(`Failed to update assignees: ${message}`); - void refreshReview("status"); + const failed = results.filter((r) => r.status === "rejected"); + if (results.some((r) => r.status === "fulfilled")) { + onCommentsChange?.(); + } + if (failed.length > 0) { + toast.error( + `Failed to mark ${failed.length} thread${failed.length === 1 ? "" : "s"} as done`, + ); + } } finally { - setPendingIdentityGroup((current) => - current === "assignees" ? null : current, - ); - } - }; - - const handleRemoveReviewer = (reviewer: string) => { - setIdentityPopoverOpen(null); - setReviewerSearch(""); - void updateReviewers({ remove: [reviewer] }); - }; - - const handleRemoveAssignee = (assignee: string) => { - setIdentityPopoverOpen(null); - setAssigneeSearch(""); - void updateAssignees({ remove: [assignee] }); - }; - - const handleAddCandidate = ( - pendingGroup: "reviewers" | "assignees", - candidate: string, - ) => { - if (pendingIdentityGroup === pendingGroup) { - return; - } - setIdentityPopoverOpen(null); - if (pendingGroup === "assignees") { - setAssigneeSearch(""); - } else { - setReviewerSearch(""); - } - - if (pendingGroup === "reviewers") { - void updateReviewers({ add: [candidate] }); - return; + setIsResolvingAll(false); + setResolvingThreadIds((prev) => { + const next = new Set(prev); + for (const id of batchIds) { + next.delete(id); + } + return next; + }); } - - void updateAssignees({ add: [candidate] }); - }; - - function isActionsJobUrl(url?: string) { - return url ? /\/actions\/runs\/\d+\/job\/\d+/.test(url) : false; - } - - function isActionsRunUrl(url?: string) { - return url ? /\/actions\/runs\/\d+(?:\/|$)/.test(url) : false; - } - - const renderIdentitySection = ({ - label, - items, - onRemove, - pendingGroup, - }: { - label: string; - items: string[]; - onRemove: (value: string) => void; - pendingGroup: "reviewers" | "assignees"; - }) => { - const isPending = pendingIdentityGroup === pendingGroup; - const isOpen = identityPopoverOpen === pendingGroup; - const summary = buildIdentitySummary(items); - const searchValue = - pendingGroup === "assignees" ? assigneeSearch : reviewerSearch; - const existingItems = new Set(items.map((item) => item.toLowerCase())); - const identityCandidatesByLogin = new Map( - identityCandidates.map( - (candidate) => [candidate.login.toLowerCase(), candidate] as const, - ), - ); - const query = searchValue.trim().toLowerCase(); - const filteredCandidates = !isOpen - ? [] - : identityCandidates - .filter( - (candidate) => !existingItems.has(candidate.login.toLowerCase()), - ) - .filter((candidate) => - query ? candidate.login.toLowerCase().includes(query) : true, - ) - .slice(0, 8); - - return ( -
- { - setIdentityPopoverOpen(nextOpen ? pendingGroup : null); - if (!nextOpen) { - if (pendingGroup === "assignees") { - setAssigneeSearch(""); - } else { - setReviewerSearch(""); - } - } - }} - > - - - - event.stopPropagation()} - > - - - - - {isIdentityCandidatesLoading - ? "Loading..." - : "No candidates found"} - - {items.length > 0 - ? items.map((item) => ( - onRemove(item)} - className="flex items-center justify-between gap-2 text-xs" - > -
- - - {item} -
- -
- )) - : null} - {filteredCandidates.map((candidate) => ( - - handleAddCandidate(pendingGroup, candidate.login) - } - className="flex items-center justify-between gap-2 text-xs" - > -
- - {candidate.login} -
- -
- ))} -
-
-
-
-
- ); }; const renderCommentList = (list: PullRequestComment[]) => @@ -938,170 +256,100 @@ export function ReviewPanel({ const age = formatShortAge(comment.createdAt); const commentCopyActionKey = getCommentCopyActionKey(comment.id); const isCopied = copiedActionKey === commentCopyActionKey; - const isExpanded = expandedComments.has(comment.id); - const hasFileLocation = !!comment.path; + const content = ( + <> + + {comment.avatarUrl ? ( + + ) : null} + + {getCommentAvatarFallback(comment.authorLogin)} + + +
+
+ + {comment.authorLogin} + + + {getCommentKindText(comment)} + + + {age ? ( + + {age} + + ) : null} +
+

+ {getCommentPreviewText(comment.body)} +

+
+ + ); return (
- - {isExpanded && ( -
- {hasFileLocation || comment.threadId ? ( -
- {hasFileLocation ? ( - - ) : null} - {comment.threadId ? ( - - ) : null} -
- ) : null} -
- -
-
- )} - -
- {comment.url ? ( - - - - - - Open comment on GitHub - - - ) : null} -
- - - - - - Reply - - +
+ {comment.threadId && workspaceId ? ( -
+ ) : null} + + {comment.url ? ( + + + + ) : null}
); @@ -1110,10 +358,11 @@ export function ReviewPanel({ return (
- -
-
- - {reviewDecisionConfig[pr.reviewDecision].label} - - {requestedReviewers.length > 0 && ( - - Awaiting {requestedReviewers.join(", ")} - + +
+ - {pr.state === "open" || pr.state === "draft" ? ( - - ) : null} -
-
- {renderIdentitySection({ - label: "Assignees", - items: assignees, - onRemove: handleRemoveAssignee, - pendingGroup: "assignees", - })} - {renderIdentitySection({ - label: "Reviewers", - items: requestedReviewers, - onRemove: handleRemoveReviewer, - pendingGroup: "reviewers", - })} + > + {reviewDecisionConfig[pr.reviewDecision].label} + + {requestedReviewers.length > 0 && ( + + Awaiting {requestedReviewers.join(", ")} + + )}
@@ -1211,144 +429,60 @@ export function ReviewPanel({
- {actionChecks.length > 0 ? ( -
- {resolvedWorkspaceId && ( - - )} - - -
- ) : null} {relevantChecks.length === 0 ? (
No checks reported.
) : ( - relevantChecks.map((check, index) => { + relevantChecks.map((check) => { const { icon: CheckIcon, className } = checkIconConfig[check.status]; const checkUrl = resolveCheckDestinationUrl(check, pr.url); - const checkKey = getCheckKey(check, index); - const isCheckExpanded = expandedChecks.has(checkKey); - const canExpand = isActionsJobUrl(check.url); - return ( -
+ return checkUrl ? ( + - {isCheckExpanded && check.url && ( - + + ) : ( +
+ + {check.name} + {check.durationText && ( + + {check.durationText} + )}
); @@ -1382,34 +516,36 @@ export function ReviewPanel({ {commentsCountLabel} - {pr && canEditPullRequest && ( - - + {activeComments.length > 0 && ( +
+ {uniqueResolvableThreadIds.length > 0 && workspaceId && ( - - New comment - - )} - {activeComments.length > 0 && ( - + +
)}
@@ -1457,27 +593,6 @@ export function ReviewPanel({ )} - - - { - if (!isNewCommentSubmitting) { - setIsNewCommentDialogOpen(open); - } - }} - onSubmit={handleSubmitNewComment} - isSubmitting={isNewCommentSubmitting} - isNewComment - />
); } diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/index.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/index.tsx index 6f99fd4f667..8e9bb153673 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/index.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/index.tsx @@ -692,7 +692,7 @@ export function RightSidebar({ isActive = true }: { isActive?: boolean }) { diff --git a/apps/desktop/src/renderer/stores/tabs/store.ts b/apps/desktop/src/renderer/stores/tabs/store.ts index 9b740e1c426..cb00b6090e1 100644 --- a/apps/desktop/src/renderer/stores/tabs/store.ts +++ b/apps/desktop/src/renderer/stores/tabs/store.ts @@ -1,11 +1,8 @@ import type { MosaicNode } from "react-mosaic-component"; import { updateTree } from "react-mosaic-component"; import { getFileOpenMode } from "renderer/hooks/useFileOpenMode"; -import { getRightSidebarOpenViewWidth } from "renderer/hooks/useRightSidebarOpenViewWidth"; import { posthog } from "renderer/lib/posthog"; import { trpcTabsStorage } from "renderer/lib/trpc-storage"; -import { navigatePersistentWebview } from "renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/runtime"; -import { tearoffPaneIds } from "renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/pane-guards"; import { deleteDocumentBuffer } from "renderer/stores/editor-state/editorBufferRegistry"; import { useEditorDocumentsStore } from "renderer/stores/editor-state/useEditorDocumentsStore"; import { useEditorSessionsStore } from "renderer/stores/editor-state/useEditorSessionsStore"; @@ -25,7 +22,7 @@ import { import type { AddFileViewerPaneOptions, AddTabWithMultiplePanesOptions, - ClosedTabEntry, + CommentPaneData, TabsState, TabsStore, } from "./types"; @@ -34,22 +31,17 @@ import { applyFileViewerOpenOptionsToPane, buildMultiPaneLayout, type CreatePaneOptions, - createActionLogsTabWithPane, createBrowserPane, createBrowserTabWithPane, createChatPane, createChatTabWithPane, - createDatabaseExplorerTabWithPane, + createCommentTabWithPane, createDevToolsPane, createFileViewerPane, - createGitGraphTabWithPane, createPane, - createReferenceGraphTabWithPane, createTabWithPane, - createVscodeExtensionTabWithPane, equalizeSplitPercentages, extractPaneIdsFromLayout, - findPanePathInLayout, findReusableFileViewerPane, generateId, generateTabName, @@ -61,28 +53,7 @@ import { resolveActiveTabIdForWorkspace, resolveFileViewerMode, } from "./utils"; -import { - killTerminalForPane, - releaseTerminalCache, -} from "./utils/terminal-cleanup"; - -const DEFAULT_FILE_VIEWER_SPLIT_PERCENTAGE = 50; - -const getRelativeFileViewerSplitPercentage = ( - position: "top" | "bottom" | "left" | "right", - useRightSidebarOpenViewWidth?: boolean, -): number => { - if ( - !useRightSidebarOpenViewWidth || - position === "top" || - position === "bottom" - ) { - return DEFAULT_FILE_VIEWER_SPLIT_PERCENTAGE; - } - - const sidebarWidth = getRightSidebarOpenViewWidth(); - return position === "left" ? sidebarWidth : 100 - sidebarWidth; -}; +import { killTerminalForPane } from "./utils/terminal-cleanup"; /** * Finds the next best tab to activate when closing a tab. @@ -157,62 +128,6 @@ const normalizePersistedChatPane = (pane: TabsState["panes"][string]): void => { delete legacyPane.chatMastra; }; -const sanitizePersistedVscodeExtensionPane = ( - pane: TabsState["panes"][string], -): TabsState["panes"][string] => { - if ( - pane.type !== "vscode-extension" || - pane.vscodeExtension?.source !== "panel" || - !pane.vscodeExtension.sessionId - ) { - return pane; - } - - return { - ...pane, - vscodeExtension: { - ...pane.vscodeExtension, - sessionId: undefined, - }, - }; -}; - -const sanitizePersistedPanes = ( - panes: TabsState["panes"], -): TabsState["panes"] => { - let hasChanges = false; - const sanitizedEntries = Object.entries(panes).map(([paneId, pane]) => { - const nextPane = sanitizePersistedVscodeExtensionPane(pane); - if (nextPane !== pane) { - hasChanges = true; - } - return [paneId, nextPane] as const; - }); - - return hasChanges ? Object.fromEntries(sanitizedEntries) : panes; -}; - -const sanitizeClosedTabsStack = ( - closedTabsStack: ClosedTabEntry[], -): ClosedTabEntry[] => { - let hasChanges = false; - const nextEntries = closedTabsStack.map((entry) => { - let entryChanged = false; - const nextPanes = entry.panes.map((pane) => { - const nextPane = sanitizePersistedVscodeExtensionPane(pane); - if (nextPane !== pane) { - hasChanges = true; - entryChanged = true; - } - return nextPane; - }); - - return entryChanged ? { ...entry, panes: nextPanes } : entry; - }); - - return hasChanges ? nextEntries : closedTabsStack; -}; - const deriveTabName = ( panes: Record, tabId: string, @@ -274,31 +189,16 @@ const cleanupEditorPaneState = (paneId: string): void => { deleteDocumentBuffer(session.documentKey); }; -// biome-ignore lint/suspicious/noExplicitAny: preload injects untyped data -const _tearoffData: any = - typeof window !== "undefined" ? window.App?.tearoffData : null; - export const useTabsStore = create()( devtools( persist( (set, get) => ({ - tabs: _tearoffData ? [_tearoffData.tab] : [], - panes: _tearoffData?.panes ?? {}, - activeTabIds: _tearoffData - ? { [_tearoffData.tab.workspaceId]: _tearoffData.tab.id } - : {}, - focusedPaneIds: _tearoffData - ? { - [_tearoffData.tab.id]: getFirstPaneId(_tearoffData.tab.layout), - } - : {}, - tabHistoryStacks: _tearoffData - ? { [_tearoffData.tab.workspaceId]: [] } - : {}, + tabs: [], + panes: {}, + activeTabIds: {}, + focusedPaneIds: {}, + tabHistoryStacks: {}, closedTabsStack: [], - hasHydrated: Boolean(_tearoffData), - - setHasHydrated: (hasHydrated) => set({ hasHydrated }), // Tab operations addTab: (workspaceId, options?: CreatePaneOptions) => { @@ -467,14 +367,7 @@ export const useTabsStore = create()( .filter(Boolean); const closedEntry = { tab: tabToRemove, - panes: - sanitizeClosedTabsStack([ - { - tab: tabToRemove, - panes: closedPanes, - closedAt: Date.now(), - }, - ])[0]?.panes ?? closedPanes, + panes: closedPanes, closedAt: Date.now(), }; const closedTabsStack = [closedEntry, ...state.closedTabsStack].slice( @@ -495,7 +388,6 @@ export const useTabsStore = create()( const newPanes = { ...state.panes }; for (const paneId of paneIds) { delete newPanes[paneId]; - releaseTerminalCache(paneId); } const newTabs = state.tabs.filter((t) => t.id !== tabId); @@ -534,12 +426,6 @@ export const useTabsStore = create()( })); }, - setTabColor: (tabId, color) => { - set((state) => ({ - tabs: state.tabs.map((t) => (t.id === tabId ? { ...t, color } : t)), - })); - }, - setTabAutoTitle: (tabId, title) => { set((state) => { const tab = state.tabs.find((t) => t.id === tabId); @@ -674,7 +560,6 @@ export const useTabsStore = create()( killTerminalForPane(paneId); } delete newPanes[paneId]; - releaseTerminalCache(paneId); } } @@ -988,13 +873,8 @@ export const useTabsStore = create()( // If clicking the same file that's already in preview, just focus it if (isSameFile) { - // Conflicted files must default to the conflict viewer even - // when callers do not pass an explicit viewMode. - const conflictFallbackViewMode = - options.diffCategory === "conflicted" - ? "conflict" - : existingFileViewer.viewMode; - const nextViewMode = options.viewMode ?? conflictFallbackViewMode; + const nextViewMode = + options.viewMode ?? existingFileViewer.viewMode; const shouldUpdateViewerState = nextViewMode !== existingFileViewer.viewMode || options.line !== undefined || @@ -1124,90 +1004,38 @@ export const useTabsStore = create()( return newPane.id; } - const relativeSplitPosition = - options.relativeSplitPosition ?? "right"; - const splitPercentage = getRelativeFileViewerSplitPercentage( - relativeSplitPosition, - options.useRightSidebarOpenViewWidth, - ); - const splitTargetTab = - options.relativeToTabId && options.relativeToPaneId - ? (state.tabs.find((tab) => tab.id === options.relativeToTabId) ?? - null) - : null; - const splitTargetPane = - splitTargetTab && options.relativeToPaneId - ? state.panes[options.relativeToPaneId] - : null; - const splitTargetPath = - splitTargetTab && - splitTargetPane && - splitTargetPane.tabId === splitTargetTab.id - ? findPanePathInLayout(splitTargetTab.layout, splitTargetPane.id) - : null; - const resolvedRelativeTarget = - splitTargetTab && splitTargetPane && splitTargetPath !== null - ? { - tab: splitTargetTab, - pane: splitTargetPane, - path: splitTargetPath, - } - : null; + const newPane = createFileViewerPane(activeTab.id, options); - const targetTab = resolvedRelativeTarget?.tab ?? activeTab; - const newPaneForTarget = createFileViewerPane(targetTab.id, options); - const targetLayoutNode = - resolvedRelativeTarget?.pane.id ?? targetTab.layout; - const splitDirection = - relativeSplitPosition === "top" || - relativeSplitPosition === "bottom" - ? "column" - : "row"; - const insertBeforeTarget = - relativeSplitPosition === "left" || relativeSplitPosition === "top"; - const splitNode: MosaicNode = { - direction: splitDirection, - first: insertBeforeTarget ? newPaneForTarget.id : targetLayoutNode, - second: insertBeforeTarget ? targetLayoutNode : newPaneForTarget.id, - splitPercentage, + const newLayout: MosaicNode = { + direction: "row", + first: activeTab.layout, + second: newPane.id, + splitPercentage: 50, }; - const newLayout: MosaicNode = resolvedRelativeTarget - ? resolvedRelativeTarget.path.length > 0 - ? updateTree(targetTab.layout, [ - { - path: resolvedRelativeTarget.path, - spec: { $set: splitNode }, - }, - ]) - : splitNode - : splitNode; - const newPanes = { - ...state.panes, - [newPaneForTarget.id]: newPaneForTarget, - }; - const tabName = deriveTabName(newPanes, targetTab.id); + const newPanes = { ...state.panes, [newPane.id]: newPane }; + const tabName = deriveTabName(newPanes, activeTab.id); set({ tabs: state.tabs.map((t) => - t.id === targetTab.id + t.id === activeTab.id ? { ...t, layout: newLayout, name: tabName } : t, ), panes: newPanes, focusedPaneIds: { ...state.focusedPaneIds, - [targetTab.id]: newPaneForTarget.id, + [activeTab.id]: newPane.id, }, }); posthog.capture("panel_opened", { panel_type: "file_viewer", - workspace_id: targetTab.workspaceId, - pane_id: newPaneForTarget.id, + workspace_id: activeTab.workspaceId, + pane_id: newPane.id, }); - return newPaneForTarget.id; + return newPane.id; }, removePane: (paneId) => { @@ -1261,7 +1089,6 @@ export const useTabsStore = create()( const newPanes = { ...state.panes }; for (const id of paneIdsToRemove) { delete newPanes[id]; - releaseTerminalCache(id); } let newFocusedPaneIds = state.focusedPaneIds; @@ -1351,40 +1178,6 @@ export const useTabsStore = create()( ), }); }, - setFileViewerDisplayName: (paneId, displayName) => { - set((state) => { - const pane = state.panes[paneId]; - if ( - !pane?.fileViewer || - pane.userTitle?.trim() || - (pane.name === displayName && - pane.fileViewer.displayName === displayName) - ) { - return state; - } - - const nextPanes = { - ...state.panes, - [paneId]: { - ...pane, - name: displayName, - fileViewer: { - ...pane.fileViewer, - displayName, - }, - }, - }; - - return { - panes: nextPanes, - tabs: state.tabs.map((tab) => - tab.id === pane.tabId - ? { ...tab, name: deriveTabName(nextPanes, tab.id) } - : tab, - ), - }; - }); - }, setPaneWorkspaceRun: (paneId, workspaceRun) => { set((state) => { const pane = state.panes[paneId]; @@ -1626,10 +1419,7 @@ export const useTabsStore = create()( paneType === "chat" ? createChatPane(tabId) : paneType === "webview" - ? createBrowserPane( - tabId, - options?.url ? { url: options.url } : undefined, - ) + ? createBrowserPane(tabId) : createPane(tabId, "terminal", options); const panelType = paneType === "chat" @@ -1698,10 +1488,7 @@ export const useTabsStore = create()( paneType === "chat" ? createChatPane(tabId) : paneType === "webview" - ? createBrowserPane( - tabId, - options?.url ? { url: options.url } : undefined, - ) + ? createBrowserPane(tabId) : createPane(tabId, "terminal", options); const panelType = paneType === "chat" @@ -1816,115 +1603,53 @@ export const useTabsStore = create()( set(withDerivedTabNames(result, [targetTabId])); }, - // Browser operations - addBrowserTab: (workspaceId: string, url?: string) => { + // Comment operations + openCommentPane: (workspaceId: string, comment: CommentPaneData) => { const state = get(); - const { tab, pane } = createBrowserTabWithPane( - workspaceId, - state.tabs, - url, + // Reuse an existing comment pane in this workspace if one exists + const workspaceTabIds = new Set( + state.tabs + .filter((t) => t.workspaceId === workspaceId) + .map((t) => t.id), ); - - const currentActiveId = state.activeTabIds[workspaceId]; - const historyStack = state.tabHistoryStacks[workspaceId] || []; - const newHistoryStack = currentActiveId - ? [ - currentActiveId, - ...historyStack.filter((id) => id !== currentActiveId), - ] - : historyStack; - - set({ - tabs: [...state.tabs, tab], - panes: { ...state.panes, [pane.id]: pane }, - activeTabIds: { - ...state.activeTabIds, - [workspaceId]: tab.id, - }, - focusedPaneIds: { - ...state.focusedPaneIds, - [tab.id]: pane.id, - }, - tabHistoryStacks: { - ...state.tabHistoryStacks, - [workspaceId]: newHistoryStack, - }, - }); - - posthog.capture("panel_opened", { - panel_type: "browser", - workspace_id: workspaceId, - pane_id: pane.id, - }); - - return { tabId: tab.id, paneId: pane.id }; - }, - - addDatabaseExplorerTab: ( - workspaceId: string, - connectionId?: string | null, - ) => { - const state = get(); - - const { tab, pane } = createDatabaseExplorerTabWithPane( - workspaceId, - connectionId, + const existingPane = Object.values(state.panes).find( + (p) => p.type === "comment" && workspaceTabIds.has(p.tabId), ); - const currentActiveId = state.activeTabIds[workspaceId]; - const historyStack = state.tabHistoryStacks[workspaceId] || []; - const newHistoryStack = currentActiveId - ? [ - currentActiveId, - ...historyStack.filter((id) => id !== currentActiveId), - ] - : historyStack; - - set({ - tabs: [...state.tabs, tab], - panes: { ...state.panes, [pane.id]: pane }, - activeTabIds: { - ...state.activeTabIds, - [workspaceId]: tab.id, - }, - focusedPaneIds: { - ...state.focusedPaneIds, - [tab.id]: pane.id, - }, - tabHistoryStacks: { - ...state.tabHistoryStacks, - [workspaceId]: newHistoryStack, - }, - }); - - posthog.capture("panel_opened", { - panel_type: "database-explorer", - workspace_id: workspaceId, - pane_id: pane.id, - }); + if (existingPane) { + const newPanes = { + ...state.panes, + [existingPane.id]: { + ...existingPane, + name: `@${comment.authorLogin}`, + comment, + }, + }; + const tabName = deriveTabName(newPanes, existingPane.tabId); + const nextTabs = state.tabs.map((t) => + t.id === existingPane.tabId ? { ...t, name: tabName } : t, + ); + const activationState = activatePaneInWorkspace({ + workspaceId, + paneId: existingPane.id, + tabs: nextTabs, + panes: newPanes, + activeTabIds: state.activeTabIds, + focusedPaneIds: state.focusedPaneIds, + tabHistoryStacks: state.tabHistoryStacks, + }); - return { tabId: tab.id, paneId: pane.id }; - }, + if (!activationState) { + set({ panes: newPanes, tabs: nextTabs }); + return { tabId: existingPane.tabId, paneId: existingPane.id }; + } - addVscodeExtensionTab: ( - workspaceId: string, - extensionId: string, - viewType: string, - name: string, - source: "view" | "panel" = "view", - sessionId?: string, - ) => { - const state = get(); + set({ ...activationState, tabs: nextTabs }); + return { tabId: existingPane.tabId, paneId: existingPane.id }; + } - const { tab, pane } = createVscodeExtensionTabWithPane( - workspaceId, - extensionId, - viewType, - name, - source, - sessionId, - ); + const { tab, pane } = createCommentTabWithPane(workspaceId, comment); const currentActiveId = state.activeTabIds[workspaceId]; const historyStack = state.tabHistoryStacks[workspaceId] || []; @@ -1953,7 +1678,7 @@ export const useTabsStore = create()( }); posthog.capture("panel_opened", { - panel_type: "vscode-extension", + panel_type: "comment", workspace_id: workspaceId, pane_id: pane.id, }); @@ -1961,106 +1686,14 @@ export const useTabsStore = create()( return { tabId: tab.id, paneId: pane.id }; }, - addGitGraphTab: (workspaceId: string, worktreePath: string) => { - const state = get(); - - const { tab, pane } = createGitGraphTabWithPane( - workspaceId, - worktreePath, - ); - - const currentActiveId = state.activeTabIds[workspaceId]; - const historyStack = state.tabHistoryStacks[workspaceId] || []; - const newHistoryStack = currentActiveId - ? [ - currentActiveId, - ...historyStack.filter((id) => id !== currentActiveId), - ] - : historyStack; - - set({ - tabs: [...state.tabs, tab], - panes: { ...state.panes, [pane.id]: pane }, - activeTabIds: { - ...state.activeTabIds, - [workspaceId]: tab.id, - }, - focusedPaneIds: { - ...state.focusedPaneIds, - [tab.id]: pane.id, - }, - tabHistoryStacks: { - ...state.tabHistoryStacks, - [workspaceId]: newHistoryStack, - }, - }); - - return { tabId: tab.id, paneId: pane.id }; - }, - - addReferenceGraphTab: ( - workspaceId: string, - absolutePath: string, - languageId: string, - line: number, - column: number, - ) => { - const state = get(); - - const { tab, pane } = createReferenceGraphTabWithPane( - workspaceId, - absolutePath, - languageId, - line, - column, - ); - - const currentActiveId = state.activeTabIds[workspaceId]; - const historyStack = state.tabHistoryStacks[workspaceId] || []; - const newHistoryStack = currentActiveId - ? [ - currentActiveId, - ...historyStack.filter((id) => id !== currentActiveId), - ] - : historyStack; - - set({ - tabs: [...state.tabs, tab], - panes: { ...state.panes, [pane.id]: pane }, - activeTabIds: { - ...state.activeTabIds, - [workspaceId]: tab.id, - }, - focusedPaneIds: { - ...state.focusedPaneIds, - [tab.id]: pane.id, - }, - tabHistoryStacks: { - ...state.tabHistoryStacks, - [workspaceId]: newHistoryStack, - }, - }); - - return { tabId: tab.id, paneId: pane.id }; - }, - - addActionLogsTab: ( - workspaceId: string, - jobs: Array<{ - detailsUrl: string; - name: string; - status: "success" | "failure" | "pending" | "skipped" | "cancelled"; - }>, - initialJobIndex?: number, - runId?: number, - ) => { + // Browser operations + addBrowserTab: (workspaceId: string, url?: string) => { const state = get(); - const { tab, pane } = createActionLogsTabWithPane( + const { tab, pane } = createBrowserTabWithPane( workspaceId, - jobs, - initialJobIndex, - runId, + state.tabs, + url, ); const currentActiveId = state.activeTabIds[workspaceId]; @@ -2090,7 +1723,7 @@ export const useTabsStore = create()( }); posthog.capture("panel_opened", { - panel_type: "action-logs", + panel_type: "browser", workspace_id: workspaceId, pane_id: pane.id, }); @@ -2159,7 +1792,6 @@ export const useTabsStore = create()( t.id === existingPane.tabId ? { ...t, name: tabName } : t, ), }); - navigatePersistentWebview(existingPane.id, url); } else { // No existing browser pane โ€” add one to the active tab const resolvedActiveTabId = resolveActiveTabIdForWorkspace({ @@ -2217,37 +1849,11 @@ export const useTabsStore = create()( } }, - setDatabaseExplorerConnection: (paneId, connectionId) => { - set((state) => { - const pane = state.panes[paneId]; - if (!pane || pane.type !== "database-explorer") { - return state; - } - - if (pane.databaseExplorer?.connectionId === connectionId) { - return state; - } - - return { - panes: { - ...state.panes, - [paneId]: { - ...pane, - databaseExplorer: { - connectionId, - }, - }, - }, - }; - }); - }, - updateBrowserUrl: ( paneId: string, url: string, title: string, faviconUrl?: string, - historyNavDirection?: "back" | "forward", ) => { const state = get(); const pane = state.panes[paneId]; @@ -2287,46 +1893,6 @@ export const useTabsStore = create()( return; } - // Only reuse adjacent history entries when the caller explicitly - // signals that a native back/forward gesture triggered this update. - // URL-bar navigation or loadURL() calls must never match an adjacent - // entry โ€” they should always truncate forward history and push a new - // entry, even if the URL happens to coincide with a neighbour. - if (historyNavDirection) { - const offset = historyNavDirection === "back" ? -1 : 1; - const adjacentIndex = historyIndex + offset; - const adjacentEntry = prevHistory[adjacentIndex]; - if (adjacentEntry && adjacentEntry.url === url) { - const history = [...prevHistory]; - history[adjacentIndex] = { - ...adjacentEntry, - title, - ...(faviconUrl !== undefined ? { faviconUrl } : {}), - }; - const newPanes = { - ...state.panes, - [paneId]: { - ...pane, - name: title || "Browser", - browser: { - ...pane.browser, - currentUrl: url, - history, - historyIndex: adjacentIndex, - }, - }, - }; - const tabName = deriveTabName(newPanes, pane.tabId); - set({ - panes: newPanes, - tabs: state.tabs.map((t) => - t.id === pane.tabId ? { ...t, name: tabName } : t, - ), - }); - return; - } - } - // Truncate forward entries when navigating from a non-end position const history = prevHistory.slice(0, historyIndex + 1); history.push({ @@ -2634,78 +2200,6 @@ export const useTabsStore = create()( }); }, - // Tearoff operations - /** Remove a tab from the store WITHOUT killing terminal sessions. */ - detachTabForTearoff: (tabId) => { - const state = get(); - const tabToRemove = state.tabs.find((t) => t.id === tabId); - if (!tabToRemove) return; - - const paneIds = getPaneIdsForTab(state.panes, tabId); - - // Mark panes as "tearing off" so terminal cleanup skips killing them - for (const paneId of paneIds) { - tearoffPaneIds.add(paneId); - } - // Clean up flags after a delay (tearoff window should be ready by then) - setTimeout(() => { - for (const paneId of paneIds) { - tearoffPaneIds.delete(paneId); - } - }, 5000); - - const newPanes = { ...state.panes }; - for (const paneId of paneIds) { - delete newPanes[paneId]; - } - - const workspaceId = tabToRemove.workspaceId; - const newActiveTabIds = { ...state.activeTabIds }; - if (state.activeTabIds[workspaceId] === tabId) { - newActiveTabIds[workspaceId] = findNextTab(state, tabId); - } - - const newFocusedPaneIds = { ...state.focusedPaneIds }; - delete newFocusedPaneIds[tabId]; - - set({ - tabs: state.tabs.filter((t) => t.id !== tabId), - panes: newPanes, - activeTabIds: newActiveTabIds, - focusedPaneIds: newFocusedPaneIds, - tabHistoryStacks: { - ...state.tabHistoryStacks, - [workspaceId]: (state.tabHistoryStacks[workspaceId] || []).filter( - (id) => id !== tabId, - ), - }, - }); - }, - - hydrateFromTearoff: (tab, panes) => { - set({ - tabs: [tab], - panes, - activeTabIds: { [tab.workspaceId]: tab.id }, - focusedPaneIds: { [tab.id]: getFirstPaneId(tab.layout) }, - tabHistoryStacks: { [tab.workspaceId]: [] }, - closedTabsStack: [], - }); - }, - - hydrateReturnedTab: (tab, panes) => { - const state = get(); - set({ - tabs: [...state.tabs, tab], - panes: { ...state.panes, ...panes }, - activeTabIds: { ...state.activeTabIds, [tab.workspaceId]: tab.id }, - focusedPaneIds: { - ...state.focusedPaneIds, - [tab.id]: getFirstPaneId(tab.layout), - }, - }); - }, - // Query helpers getTabsByWorkspace: (workspaceId) => { return get().tabs.filter((t) => t.workspaceId === workspaceId); @@ -2739,20 +2233,6 @@ export const useTabsStore = create()( name: "tabs-storage", version: 9, storage: trpcTabsStorage, - partialize: (state) => { - const panes = sanitizePersistedPanes(state.panes); - const closedTabsStack = sanitizeClosedTabsStack( - state.closedTabsStack, - ); - return { - tabs: state.tabs, - panes, - activeTabIds: state.activeTabIds, - focusedPaneIds: state.focusedPaneIds, - tabHistoryStacks: state.tabHistoryStacks, - closedTabsStack, - }; - }, migrate: (persistedState, version) => { const state = persistedState as TabsState; if (version < 2 && state.panes) { @@ -2804,7 +2284,6 @@ export const useTabsStore = create()( // - "permission": Permission dialog is gone after restart // Note: "review" is intentionally preserved so users see missed completions if (persisted.panes) { - persisted.panes = sanitizePersistedPanes(persisted.panes); for (const pane of Object.values(persisted.panes)) { if (pane.status === "working" || pane.status === "permission") { pane.status = "idle"; @@ -2820,11 +2299,6 @@ export const useTabsStore = create()( } } } - if (persisted.closedTabsStack) { - persisted.closedTabsStack = sanitizeClosedTabsStack( - persisted.closedTabsStack, - ); - } const mergedState = { ...currentState, ...persisted }; @@ -2888,9 +2362,6 @@ export const useTabsStore = create()( focusedPaneIds: nextFocusedPaneIds, }; }, - onRehydrateStorage: () => (state) => { - state?.setHasHydrated(true); - }, }, ), { name: "TabsStore" }, diff --git a/apps/desktop/src/renderer/stores/tabs/types.ts b/apps/desktop/src/renderer/stores/tabs/types.ts index 16c836f0902..e5f64a4aec5 100644 --- a/apps/desktop/src/renderer/stores/tabs/types.ts +++ b/apps/desktop/src/renderer/stores/tabs/types.ts @@ -5,6 +5,7 @@ import type { BaseTabsState, BrowserLoadError, ChatLaunchConfig, + CommentPaneState, FileViewerMode, Pane, PaneStatus, @@ -15,6 +16,11 @@ import type { // Re-export shared types export type { Pane, PaneStatus, PaneType }; +/** + * Data required to open a comment pane + */ +export type CommentPaneData = CommentPaneState; + /** * Snapshot of a closed tab + its panes, used for "reopen closed tab". */ @@ -211,6 +217,17 @@ export interface TabsStore extends TabsState { position: MosaicDropPosition, ) => void; + // Comment operations + /** + * Open a PR/review comment in a pane. Reuses an existing comment pane in + * the workspace if one is found; otherwise creates a new tab with a + * comment pane. + */ + openCommentPane: ( + workspaceId: string, + comment: CommentPaneData, + ) => { tabId: string; paneId: string }; + // Browser operations addBrowserTab: ( workspaceId: string, diff --git a/apps/desktop/src/renderer/stores/tabs/utils.ts b/apps/desktop/src/renderer/stores/tabs/utils.ts index 7265db91813..ab26f7c5b8d 100644 --- a/apps/desktop/src/renderer/stores/tabs/utils.ts +++ b/apps/desktop/src/renderer/stores/tabs/utils.ts @@ -9,19 +9,15 @@ import { type FileStatus, isNewFile, } from "shared/changes-types"; -import { hasRenderedPreview, isHtmlFile, isImageFile } from "shared/file-types"; +import { hasRenderedPreview, isImageFile } from "shared/file-types"; import { - type ActionLogsJob, - type ActionLogsPaneState, acknowledgedStatus, type BrowserPaneState, - type DatabaseExplorerPaneState, + type CommentPaneState, type DevToolsPaneState, type DiffLayout, type FileViewerMode, type FileViewerState, - type GitGraphPaneState, - type ReferenceGraphPaneState, } from "shared/tabs-types"; import type { AddChatTabOptions, @@ -47,10 +43,6 @@ export const resolveFileViewerMode = ({ if (viewMode) return viewMode; // Images always default to rendered (no meaningful diff for binary files) if (isImageFile(filePath)) return "rendered"; - // Conflicted files show the inline conflict resolver - if (diffCategory === "conflicted") return "conflict"; - // HTML files always default to raw (preview available via toggle) - if (isHtmlFile(filePath)) return "raw"; // New files have no previous version โ€” show raw/rendered instead of an all-green diff if (diffCategory && fileStatus && isNewFile(fileStatus)) { if (hasRenderedPreview(filePath)) return "rendered"; @@ -349,73 +341,16 @@ export const createBrowserTabWithPane = ( return { tab, pane }; }; -/** - * Creates a new git graph pane - */ -export const createGitGraphPane = ( - tabId: string, - worktreePath: string, -): Pane => { - const id = generateId("pane"); - const gitGraph: GitGraphPaneState = { worktreePath }; - return { - id, - tabId, - type: "git-graph", - name: "Git Graph", - gitGraph, - }; -}; - -/** - * Creates a new tab with a git graph pane atomically - */ -export const createGitGraphTabWithPane = ( - workspaceId: string, - worktreePath: string, -): { tab: Tab; pane: Pane } => { - const tabId = generateId("tab"); - const pane = createGitGraphPane(tabId, worktreePath); - - const tab: Tab = { - id: tabId, - name: "Git Graph", - workspaceId, - layout: pane.id, - createdAt: Date.now(), - }; - - return { tab, pane }; -}; - -export const createDatabaseExplorerPane = ( - tabId: string, - connectionId?: string | null, -): Pane => { - const id = generateId("pane"); - const databaseExplorer: DatabaseExplorerPaneState = { - connectionId: connectionId ?? null, - }; - - return { - id, - tabId, - type: "database-explorer", - name: "Database Explorer", - databaseExplorer, - }; -}; - -export const createDatabaseExplorerTabWithPane = ( +export const createChatTabWithPane = ( workspaceId: string, - connectionId?: string | null, + options?: AddChatTabOptions, ): { tab: Tab; pane: Pane } => { const tabId = generateId("tab"); - const pane = createDatabaseExplorerPane(tabId, connectionId); + const pane = createChatPane(tabId, options); const tab: Tab = { id: tabId, - name: "Database Explorer", + name: "New Chat", workspaceId, layout: pane.id, createdAt: Date.now(), @@ -424,58 +359,39 @@ export const createDatabaseExplorerTabWithPane = ( return { tab, pane }; }; -export const createActionLogsPane = ( +/** + * Creates a new comment pane (PR review / conversation comment viewer) + */ +export const createCommentPane = ( tabId: string, - jobs: ActionLogsJob[], - initialJobIndex?: number, - runId?: number, + comment: CommentPaneState, ): Pane => { const id = generateId("pane"); - const actionLogs: ActionLogsPaneState = { jobs, initialJobIndex, runId }; return { id, tabId, - type: "action-logs", - name: "Action Logs", - actionLogs, + type: "comment", + name: `@${comment.authorLogin}`, + comment, }; }; -export const createActionLogsTabWithPane = ( - workspaceId: string, - jobs: ActionLogsJob[], - initialJobIndex?: number, - runId?: number, -): { tab: Tab; pane: Pane } => { - const tabId = generateId("tab"); - const pane = createActionLogsPane(tabId, jobs, initialJobIndex, runId); - - const tab: Tab = { - id: tabId, - name: "Action Logs", - workspaceId, - layout: pane.id, - createdAt: Date.now(), - }; - - return { tab, pane }; -}; - -export const createChatTabWithPane = ( +/** + * Creates a new tab with a comment pane atomically + */ +export const createCommentTabWithPane = ( workspaceId: string, - options?: AddChatTabOptions, + comment: CommentPaneState, ): { tab: Tab; pane: Pane } => { const tabId = generateId("tab"); - const pane = createChatPane(tabId, options); - + const pane = createCommentPane(tabId, comment); const tab: Tab = { id: tabId, - name: "New Chat", + name: `@${comment.authorLogin}`, workspaceId, layout: pane.id, createdAt: Date.now(), }; - return { tab, pane }; }; @@ -676,8 +592,6 @@ export const findPanePath = ( return null; }; -export const findPanePathInLayout = findPanePath; - export type FocusDirection = "left" | "right" | "up" | "down"; const findEdgeMosaicPaneId = ( @@ -982,17 +896,9 @@ export const applyFileViewerOpenOptionsToPane = ( return pane; } - // Conflicted files must render in the conflict viewer. If the reused pane - // has a stale non-conflict viewMode (e.g. was opened as raw before the - // merge marked the file as conflicted), force it back to "conflict" when - // no explicit override is provided. - const fallbackViewMode = - options.diffCategory === "conflicted" - ? "conflict" - : pane.fileViewer.viewMode; const nextFileViewer: FileViewerState = { ...pane.fileViewer, - viewMode: options.viewMode ?? fallbackViewMode, + viewMode: options.viewMode ?? pane.fileViewer.viewMode, isPinned: pane.fileViewer.isPinned || (options.isPinned ?? false), oldPath: options.oldPath ?? pane.fileViewer.oldPath, initialLine: options.line ?? pane.fileViewer.initialLine, @@ -1088,102 +994,3 @@ export const activatePaneInWorkspace = ({ }, }; }; - -export const createVscodeExtensionPane = ( - tabId: string, - extensionId: string, - viewType: string, - name: string, - source: "view" | "panel" = "view", - sessionId?: string, -): Pane => { - const id = generateId("pane"); - return { - id, - tabId, - type: "vscode-extension", - name, - vscodeExtension: { viewType, extensionId, source, sessionId }, - }; -}; - -export const createVscodeExtensionTabWithPane = ( - workspaceId: string, - extensionId: string, - viewType: string, - name: string, - source: "view" | "panel" = "view", - sessionId?: string, -): { tab: Tab; pane: Pane } => { - const tabId = generateId("tab"); - const pane = createVscodeExtensionPane( - tabId, - extensionId, - viewType, - name, - source, - sessionId, - ); - - const tab: Tab = { - id: tabId, - name, - workspaceId, - layout: pane.id, - createdAt: Date.now(), - }; - - return { tab, pane }; -}; - -export const createReferenceGraphPane = ( - tabId: string, - absolutePath: string, - languageId: string, - line: number, - column: number, -): Pane => { - const id = generateId("pane"); - const fileName = getPathBaseName(absolutePath); - const referenceGraph: ReferenceGraphPaneState = { - absolutePath, - languageId, - line, - column, - }; - return { - id, - tabId, - type: "reference-graph", - name: `References: ${fileName}:${line}`, - referenceGraph, - }; -}; - -export const createReferenceGraphTabWithPane = ( - workspaceId: string, - absolutePath: string, - languageId: string, - line: number, - column: number, -): { tab: Tab; pane: Pane } => { - const tabId = generateId("tab"); - const pane = createReferenceGraphPane( - tabId, - absolutePath, - languageId, - line, - column, - ); - const fileName = getPathBaseName(absolutePath); - - const tab: Tab = { - id: tabId, - name: `References: ${fileName}:${line}`, - workspaceId, - layout: pane.id, - createdAt: Date.now(), - }; - - return { tab, pane }; -}; diff --git a/apps/desktop/src/shared/tabs-types.ts b/apps/desktop/src/shared/tabs-types.ts index c6e11690383..2098afbd98e 100644 --- a/apps/desktop/src/shared/tabs-types.ts +++ b/apps/desktop/src/shared/tabs-types.ts @@ -14,11 +14,7 @@ export type PaneType = | "file-viewer" | "chat" | "devtools" - | "git-graph" - | "database-explorer" - | "action-logs" - | "vscode-extension" - | "reference-graph"; + | "comment"; /** * Pane status for agent lifecycle indicators @@ -95,7 +91,7 @@ export function acknowledgedStatus(status: PaneStatus | undefined): PaneStatus { /** * File viewer display modes */ -export type FileViewerMode = "rendered" | "raw" | "diff" | "conflict"; +export type FileViewerMode = "rendered" | "raw" | "diff"; /** * Diff layout options for file viewer @@ -147,16 +143,7 @@ export interface Pane { chat?: ChatPaneState; // For chat panes browser?: BrowserPaneState; // For browser (webview) panes devtools?: DevToolsPaneState; // For devtools panes - gitGraph?: GitGraphPaneState; // For git-graph panes - databaseExplorer?: DatabaseExplorerPaneState; // For database explorer panes - actionLogs?: ActionLogsPaneState; // For GitHub Actions log panes - vscodeExtension?: { - viewType: string; - extensionId: string; - source?: "view" | "panel"; - sessionId?: string; - }; - referenceGraph?: ReferenceGraphPaneState; + comment?: CommentPaneState; // For comment panes workspaceRun?: { workspaceId: string; state: "running" | "stopped-by-user" | "stopped-by-exit"; @@ -236,53 +223,16 @@ export interface DevToolsPaneState { } /** - * Git Graph pane-specific properties - */ -export interface GitGraphPaneState { - /** Worktree path for the git repository */ - worktreePath: string; -} - -/** - * Database Explorer pane-specific properties - */ -export interface DatabaseExplorerPaneState { - connectionId: string | null; -} - -/** - * Action Logs pane-specific properties - */ -export interface ActionLogsJob { - /** The GitHub Actions job details URL */ - detailsUrl: string; - /** Display name for the job */ - name: string; - /** Check status */ - status: "success" | "failure" | "pending" | "skipped" | "cancelled"; -} - -export interface ActionLogsPaneState { - /** All action jobs to display */ - jobs: ActionLogsJob[]; - /** Initially selected job index */ - initialJobIndex?: number; - /** Workflow run ID โ€” when set, jobs are polled from the GitHub API */ - runId?: number; -} - -/** - * Reference graph pane-specific properties + * Comment pane-specific properties (PR review / conversation comment viewer) */ -export interface ReferenceGraphPaneState { - /** Absolute path of the file containing the symbol */ - absolutePath: string; - /** Language ID for the file */ - languageId: string; - /** Line of the symbol */ - line: number; - /** Column of the symbol */ - column: number; +export interface CommentPaneState { + commentId: string; + authorLogin: string; + avatarUrl?: string; + body: string; + url?: string; + path?: string; + line?: number; } /** @@ -294,7 +244,6 @@ export interface BaseTab { userTitle?: string; workspaceId: string; createdAt: number; - color?: string | null; } /** diff --git a/apps/electric-proxy/package.json b/apps/electric-proxy/package.json index 9fa85989d94..0b797be11bd 100644 --- a/apps/electric-proxy/package.json +++ b/apps/electric-proxy/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@superset/db": "workspace:*", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "jose": "^6.1.3" }, "devDependencies": { diff --git a/apps/electric-proxy/wrangler.jsonc b/apps/electric-proxy/wrangler.jsonc index 514b498c2f3..75066000e0e 100644 --- a/apps/electric-proxy/wrangler.jsonc +++ b/apps/electric-proxy/wrangler.jsonc @@ -2,5 +2,12 @@ "name": "electric-proxy", "main": "src/index.ts", "compatibility_date": "2025-01-01", - "compatibility_flags": ["request_cf_overrides_cache_rules"] + "compatibility_flags": ["request_cf_overrides_cache_rules"], + "observability": { + "enabled": true, + "head_sampling_rate": 1, + "logs": { + "invocation_logs": true + } + } } diff --git a/apps/marketing/content/changelog/2026-04-20-v2-workspace-brand-cli.mdx b/apps/marketing/content/changelog/2026-04-20-v2-workspace-brand-cli.mdx new file mode 100644 index 00000000000..1df0c6a894b --- /dev/null +++ b/apps/marketing/content/changelog/2026-04-20-v2-workspace-brand-cli.mdx @@ -0,0 +1,177 @@ +--- +title: Chat UX overhaul, v2 early access, brand refresh, and standalone CLI +date: 2026-04-20 +image: /changelog/chat-ux.png +--- + +A big update covering the last three weeks. The chat interface got a top-to-bottom UX overhaul with a new rich-text prompt editor, slash-command and file-mention chips, and a redesigned tool-call system. The v2 workspace is now in early access, with panes, a diff viewer, a file editor, a review tab, and a browser pane. The Superset CLI shipped and then grew a self-contained tarball that can run the host-service anywhere. The desktop app got a full brand refresh, and GitHub integration is now free on every plan. + +## Chat UX overhaul + +### Tiptap prompt input + +The prompt is now a ProseMirror-based rich text editor with inline chips for commands and file references. + +- **Slash command chips** โ€” type `/` to open a command menu; the command becomes an inline chip anywhere in the message instead of submitting immediately. Chips with an `argumentHint` expose an inline editable input with auto-sizing and keyboard nav; `/model` shows a dropdown of available models. +- **File mention chips** โ€” type `@` to open a file-search popover anchored to the cursor. Picking a file inserts a chip that serializes to `@path` on send. +- **Skill preload** โ€” `/command` chips are extracted before the LLM turn so the harness loads the right skill first. A `SkillToolCall` row shows in the message while the skill loads. +- **Preview on hover** โ€” hovering a chip shows a popover with its description (hidden while an arg input is focused). +- IME composition guard prevents submit while CJK input is pending; Tab no longer auto-selects commands (Enter or click only). + +### Redesigned tool calls + +- Compact, monospaced `ToolInput` / `ToolOutput` / `ToolHeader` layout with a braille spinner and left-side icons +- Subagent activity rendered inline as a collapsible tool wrapper, with full markdown for task prompt and response +- Clickable file names on every file-related tool call row (read, write, LSP inspect) โ€” clicking opens the file in the editor pane +- Syntax-highlighted read-file output with filename header and line-range label; expand/collapse and copy on every code block + +### ask_user flow + +- Footer overlay with pinned header/footer and scrollable option buttons โ€” no more inline question UI +- Status chips (Awaiting Response / Answered / Cancelled) with a collapsible answer bubble; cancelled shows immediately when aborted +- Optimistic dismiss on submit; prompt textarea auto-focuses after answering +- `ask_user` is now required for all Superset questions โ€” no plain-text fallbacks + +### Workspace status and notifications + +- A pending question puts an orange dot on the workspace nav and fires a native OS toast, driven server-side through the lifecycle event pipeline so it works when the tab is unfocused +- Orange dot clears immediately on answer submit +- Auto-scroll to bottom on message send, new question arrival, and answer submit + +## The v2 workspace is in early access + +![v2 workspace early access](/changelog/v2-early-access.png) + +v2 is a ground-up rebuild of the workspace aimed at cloud. We tore out v1's accumulated cruft, rewrote the terminal from scratch to fix the rendering glitches, and re-architected the app like a real IDE โ€” Tab โ†’ Split โ†’ Pane, a proper file tree with git decorations, a full editor, and a diff viewer that handles large changesets. Opt-in for now; here's what's in the box: + +### Pane layout system + +A new flexible Tab โ†’ Split โ†’ Pane structure built on the `@superset/panes` package, with weighted resizable splits. + +- Drag and drop panes to rearrange them +- Drag to reorder tabs within a tab group +- Right-click pane headers for split / close / close others +- Double-click a split separator to equalize pane sizes +- Cmd+Alt+Arrow moves focus between panes +- Closing the active pane focuses the nearest sibling + +### Diff viewer + +![v2 diff viewer](/changelog/v2-diff.png) + +A GitHub-style multi-file diff pane with lazy loading, a persistent "Viewed" state synced to the sidebar Changes list, unified/split view toggles, and header actions for collapse, expand unchanged, copy, and revert. Open it in its own tab with โŒ˜โ‡งL . + +### File editor + +![v2 file tree and editor](/changelog/v2-file-tree.png) + +A full editor pane โ€” foundation, views, and a large stability pass. The file tree shows git decorations inline . + +### Review tab + +PR info, checks, and comments rendered inline in the v2 workspace, matching the v1 review experience. + +### PR checkout and launch context + +Check out a PR directly from v2 via a widened checkout procedure, and compose a full launch context (selected files, instructions, branch state) before starting work. + +### Browser pane + +Pages stay loaded across tab switches and workspace navigations โ€” no reloads, no lost scroll or form state. URL bar, back/forward/reload, history autocomplete, DevTools, screenshots, and hard reload from the overflow menu. + +### Git Changes sidebar + +A Changes tab in the right sidebar showing ahead/behind status, commit count, and a filterable file list. Filter by all changes, uncommitted only, a single commit, or a commit range. Searchable base-branch picker and inline rename for unpushed branches. + +## Superset CLI + +{/* TODO: Screenshot of the CLI in action */} + +The `superset` CLI lets you manage Superset from your terminal, and ships as a self-contained tarball so you can run the host-service on a remote server, CI box, or cloud VM without the desktop app. + +```bash +tar -xzf superset-darwin-arm64.tar.gz -C ~/superset +export PATH="$HOME/superset/bin:$PATH" + +superset auth login # OAuth PKCE + loopback +superset host start --daemon # connects to relay.superset.sh +superset tasks list # full task CRUD +superset org switch # manage organizations +``` + +Binaries for macOS (arm64, x64) and Linux x64. `--json` output mode for scripting and agent use. + +## Brand refresh + +![Brand refresh โ€” new logo and icon treatment](/changelog/brand-refresh.png) + +New logo and icon treatment across the desktop app, DMG installer background, tray icon, and wordmark. In dev builds, each workspace gets a color-coded corner fold on the dock icon so open workspaces are distinguishable at a glance. + +## GitHub integration is free + +PR review, issue linking, and push-from-desktop are available on every plan โ€” no Pro subscription required. + +## Improvements + +- **V2 file editor foundation** โ€” editor views plus a large stability pass +- **V2 review tab** โ€” PR info, checks, and comments inline +- **V2 PR checkout** โ€” checkout a PR directly in a v2 workspace +- **V2 launch context composition** โ€” prep files, instructions, and branch state before launching +- **Recently Viewed in Quick Open** โ€” surfaces files you were just looking at +- **Paginated branch picker** โ€” scales to thousands of branches with inline checkout + open actions +- **Modifier-keyed terminal file links** โ€” โŒ˜/Ctrl+click opens in external editor or new tab +- **Drag-and-drop into v2 terminal panes** โ€” drop files to insert their paths +- **Tasks link restored in v2 dashboard sidebar** +- **Escape closes settings** +- **Hotkey defaults** โ€” unbound defaults plus restored prev/next tab and workspace shortcuts +- **Allow hotkeys in editable content** +- **Terminal search** โ€” โŒ˜F / Ctrl+Shift+F in the v2 terminal +- **Kitty keyboard protocol** โ€” better modifier support in neovim, fish 4+, and others +- **Terminal theme and font settings** in v2 (parity with v1) +- **Fast file search** โ€” VS Code's path-aware fuzzy scorer with pre-warmed index +- **V2 top bar** โ€” right sidebar toggle, org dropdown, unified "Open In" button +- **Git decorations in v2 file tree** +- **V2 preset parity + setup scripts** +- **V1/v2 toggle from the top bar**, preference persists +- **Host service durability** โ€” survives app quits, re-adopted on next launch +- **Relay security setting** โ€” Settings โ†’ Security controls whether this machine is exposed; defaults to off +- **Unified workspace delete** โ€” v2 delete goes through the host-service +- **Focus neighbor on workspace delete** โ€” drops you on an adjacent workspace, not `/` +- **Create Section Below** promoted to top-level on the workspace menu +- **Event-driven tray menu** showing the real org name +- **Notification sound volume** dropdown in settings +- **Resolve review comments** directly in the review tab +- **Public roadmap** at superset.sh/roadmap + +--- + +**Bug fixes** + +- Security โ€” bumped drizzle-orm and better-auth to patch CVEs ; pinned axios against a known supply-chain vector +- Chat โ€” cut display polling to 4fps and restored query cache defaults +- Chat โ€” prevent keyboard shortcuts from leaking characters into the chat input +- Terminal โ€” recover from non-monospace font crash +- Terminal โ€” unblock v1 input during shell init +- Terminal โ€” sync v1 dimensions to backend on connect +- Terminal โ€” match VS Code clipboard handling +- Terminal โ€” restore โŒ˜+click for v1 file links; refresh v2 link tooltip editor +- Terminal โ€” correct dimensions sent after attach (fixes TUI apps) +- Terminal โ€” garbling fix via tRPC-first sessions +- Auto-updater โ€” restored on macOS; recover from corrupt update cache; spinner while pending; guard repeat clicks +- macOS quit โ€” โŒ˜Q and Dock Quit now fully exit instead of backgrounding to tray +- macOS โ€” trigger Local Network permission on startup +- Port scanner โ€” stop excessive `lsof` spawning +- V2 workspace โ€” prevent "workspace not found" flash after create; gate children on collection readiness; derive base branch from git config +- V2 file tree โ€” no longer blocks on `git.getStatus` in shared tRPC batch; file icons resolve on nested routes +- V2 sidebar โ€” LOC badge hidden when no changes; section count matches visual grouping; native clipboard for copy path +- V2 diff sidebar โ€” removed viewed checkboxes; right sidebar toggle is reactive +- V2 โ€” Open In editor is project-scoped, not workspace-scoped; duplicate panes on new-tab file opens; modal focus trap on workspace dialogs +- V1 โ€” fix Cmd+O firing open-in twice; fix split pane startup sizing; `--no-track` in createWorktree +- Keyboard โ€” Ctrl bindings, `event.code` unification, terminal override respect +- IME composition in new-workspace Enter handlers +- File attachments pass through the prompt input +- Close-workspace shortcut no longer conflicts with tab close โ€” now โŒ˜โ‡งโŒซ +- Pending failure error messages are selectable +- Font-settings query no longer silently routed through host-service +- MCP โ€” accept resource URL as valid OAuth audience; fix devices incorrectly classified as offline +- CLI auth switched to OAuth PKCE + loopback diff --git a/apps/marketing/public/changelog/brand-refresh.png b/apps/marketing/public/changelog/brand-refresh.png new file mode 100644 index 00000000000..fef8e5ee83c Binary files /dev/null and b/apps/marketing/public/changelog/brand-refresh.png differ diff --git a/apps/marketing/public/changelog/chat-ux.png b/apps/marketing/public/changelog/chat-ux.png new file mode 100644 index 00000000000..adea7a86ebf Binary files /dev/null and b/apps/marketing/public/changelog/chat-ux.png differ diff --git a/apps/marketing/public/changelog/v2-diff.png b/apps/marketing/public/changelog/v2-diff.png new file mode 100644 index 00000000000..adf42e58a80 Binary files /dev/null and b/apps/marketing/public/changelog/v2-diff.png differ diff --git a/apps/marketing/public/changelog/v2-early-access.png b/apps/marketing/public/changelog/v2-early-access.png new file mode 100644 index 00000000000..8536fde75d7 Binary files /dev/null and b/apps/marketing/public/changelog/v2-early-access.png differ diff --git a/apps/marketing/public/changelog/v2-file-tree.png b/apps/marketing/public/changelog/v2-file-tree.png new file mode 100644 index 00000000000..83c3e4852c7 Binary files /dev/null and b/apps/marketing/public/changelog/v2-file-tree.png differ diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 3d6444a08c4..ad5cdeafe28 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -12,7 +12,7 @@ "lint:fix": "biome check --write ." }, "dependencies": { - "@better-auth/expo": "1.5.6", + "@better-auth/expo": "1.6.5", "@electric-sql/client": "1.5.15", "@expo/ui": "~55.0.0-preview.4", "@expo/vector-icons": "^15.0.3", @@ -50,7 +50,7 @@ "@tanstack/react-query": "^5.90.19", "@trpc/client": "^11.7.1", "@trpc/react-query": "^11.7.1", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.3.1", diff --git a/apps/relay/fly.toml b/apps/relay/fly.toml index ae06f29dfcd..a7bb85dab68 100644 --- a/apps/relay/fly.toml +++ b/apps/relay/fly.toml @@ -13,6 +13,7 @@ primary_region = "sjc" auto_stop_machines = "off" auto_start_machines = true min_machines_running = 1 + max_machines_running = 1 [http_service.concurrency] type = "connections" diff --git a/apps/relay/plans/20260420-relay-hardening.md b/apps/relay/plans/20260420-relay-hardening.md new file mode 100644 index 00000000000..c6331d6585c --- /dev/null +++ b/apps/relay/plans/20260420-relay-hardening.md @@ -0,0 +1,170 @@ +# Relay Hardening & Horizontal Scale-Out + +**Author:** Satya ยท **Date:** 2026-04-20 ยท **Linear:** SUPER-427 + +## Context + +The relay is how remote desktop hosts proxy HTTP + WebSocket traffic to clients on the web. It's a Hono + `@hono/node-ws` server on fly (`superset-relay`, `sjc`) that accepts two kinds of connections: + +1. **Host-side** โ€” desktops open `wss://relay.superset.sh/tunnel?hostId=&token=`. Relay calls this a "tunnel" and keeps an in-memory `Map` (`apps/relay/src/tunnel.ts:30`). +2. **Client-side** โ€” web/desktop clients call `/hosts/:hostId/trpc/*` (HTTP) or upgrade `/hosts/:hostId/*` (WS). Relay looks up the tunnel and forwards the frame via the host-side WS. + +The service has been working for internal users but is about to take a large traffic step-up. The 2026-04-20 debugging session exposed a set of issues that will get much worse at scale. Two were patched live (multi-machine sharding โ†’ pinned to 1 machine; terminal WS URL bug); everything else is open (SUPER-427). + +This plan proposes (a) a scale-out architecture that survives multiple fly machines and (b) a prioritized hardening backlog so we can ship in known-small increments. + +## Goals + +- Horizontally scalable relay โ€” adding machines increases capacity, not 503 rate. +- No stuck `is_online` state in the DB; what the UI shows matches reality within seconds of a drop. +- Streaming proxies (SSE, tRPC subscriptions, WS) work end-to-end. +- Graceful shutdown: deploys / scale-down don't drop live tunnels abruptly. +- Single pane of glass for "who's connected, on which machine, since when". + +## Non-goals + +- Geographic distribution (multi-region). We stay in `sjc` for now; lat is dominated by host<->relay and client<->relay legs individually. +- Replacing JWT auth. Current token flow is fine. +- Migrating off fly. + +## Decision: scale-out architecture + +**Pick: fly-replay sticky routing + Redis directory.** Each relay machine continues to hold tunnels in-process. When a proxy request lands on a machine that does not own the target tunnel, the machine replies with `fly-replay: instance=` โ€” fly's proxy re-routes the request to the owning machine, which handles it locally. Tunnel ownership is published to Redis on register, removed on unregister. + +### Rejected alternatives + +- **Pub/sub message bus (every request piped through Redis/NATS).** Adds a latency hop per request *and* per response frame; correlation-id bookkeeping duplicates fly's routing layer; Redis pub/sub has no delivery guarantees so we'd need acks on top. No gain over sticky routing. +- **Dedicated subdomain per tunnel** (e.g. `.relayโ€ฆ`). Requires wildcard DNS + per-tunnel fly machines, order-of-magnitude more infra. +- **Vertical scaling only.** One big box is a single point of failure during deploys and hardware faults. Fine as a fallback but not a plan. +- **Consistent-hash routing at the fly edge.** Fly's proxy doesn't natively hash by header/query; would need a custom edge. Not worth it. + +### Why fly-replay works here + +- One-hop re-routing: the first machine hit does a ~200ยตs Redis `HGET` and returns the replay header; fly re-issues the request to the correct instance. For tunnels that stay on the same machine for their whole lifetime (vast majority), most requests hit the right machine on the first try after fly's LB learns affinity. +- WS upgrades are in scope for `fly-replay` as of 2024. +- Ownership directory is tiny (one row per live tunnel); Redis HSET is the right shape. +- No request payload ever transits Redis โ€” Redis just stores ownership and heartbeat timestamps. + +### What Redis stores + +``` +HSET tunnel-owner # set on register, DEL on unregister +HSET tunnel-meta # registeredAt, lastPongAt +ZADD tunnel-ttl # for stale-owner cleanup +``` + +TTLs are enforced by a periodic sweeper on each machine (SCAN the ZSET, drop rows older than 2ร— ping interval without a refresh). + +### Redis itself + +**Reuse the existing Upstash instance** (`KV_REST_API_URL` / `KV_REST_API_TOKEN`, already used by `packages/auth/src/lib/rate-limit.ts` and a dozen api routes). No new infra, no new secrets, no new failure mode to monitor. Write through the `@upstash/redis` REST client we already depend on. + +Rejected alternatives: +- **Fly's "Managed Redis" add-on.** It is just Upstash under the hood (reseller relationship; product has since been de-emphasized). Zero latency or feature win over using Upstash directly. +- **Self-hosted Redis on a fly machine behind flycast.** Sub-ms latency via the wireguard network, but we own replication, backups, HA, and deploy sequencing. Not worth it for ~few-hundred ops/sec. +- **Putting Upstash behind fly's private network.** Upstash's REST endpoint is public-internet HTTPS; they don't expose a flycast-routable endpoint. Can't keep it inside the VPN. + +Latency budget: Upstash REST from fly `sjc` is ~5โ€“15ms round-trip. That is only paid on *cross-machine* proxy requests โ€” once fly's LB learns affinity, the owning machine handles requests in-process with no Redis hop. Register/unregister are one-shot so the hop doesn't matter there either. + +## Proposed phases + +Each phase is independently shippable and individually provides value. Ordered by ROI; phase 1 blocks phase 2. + +### Phase 0 โ€” freeze known-good (done, this session) + +- [x] `max_machines_running = 1` in `apps/relay/fly.toml` (PR #3599). +- [x] Terminal WS URL bug (PR #3599). + +These keep prod stable while we execute the rest. + +### Phase 1 โ€” shared-state scale-out (the big one) + +**Blocks being able to run >1 machine. Everything in later phases benefits from this.** + +Workstreams: + +1. **Tunnel directory in Redis.** New module `apps/relay/src/directory.ts`: `register(hostId, machineId)`, `unregister(hostId)`, `lookup(hostId) โ†’ machineId | null`, `heartbeat(hostId)`, `sweepStale()`. Fly machine id from `FLY_MACHINE_ID` env. Uses `@upstash/redis` pointed at the existing `KV_REST_API_URL` / `KV_REST_API_TOKEN` โ€” same instance the api's rate-limiter already uses. Key prefix `relay:` so it can't collide with other users of the instance. +2. **Fly-replay routing.** In `authMiddleware` (after access check, before tunnel lookup): if `tunnelManager.hasTunnel(hostId)` is false, call `directory.lookup(hostId)`. If another machine owns it, respond with `fly-replay: instance=` + 200. If no owner, keep returning 503. +3. **WS upgrade replay.** `@hono/node-ws` upgrade path needs to set `fly-replay` before the upgrade response. Needs a small detour โ€” we can't replay after `Sec-WebSocket-Accept`. Verify fly honors the header on 101 upgrade. If not, we do an HTTP pre-flight `/hosts/:hostId/_whoowns` first that returns the replay header. Clients already hit `/tunnel` once, so adding a single pre-flight per WS open is fine. +4. **Clean register/unregister lifecycle.** Current `register()` at `tunnel.ts:38` closes the NEW socket if the old one is still present. Flip to last-write-wins: close the OLD tunnel, take the new one. Prevents flaky clients from getting permanently stuck behind a dead-but-not-yet-detected WS. +5. **Flip cap back up.** Remove `max_machines_running = 1`, scale to 2, verify via `fly logs` that tunnels are served from both machines and proxy requests get routed correctly. + +**Exit criteria:** `fly scale count 3 -a superset-relay`, then have three of us connect our desktops, and every client request succeeds regardless of which machine the client's HTTP lands on. + +### Phase 2 โ€” truthful `is_online` + +**Independently valuable; unblocks the "is X online?" UI question.** + +- Boot-time cleanup: on relay start, `UPDATE v2_hosts SET is_online = false WHERE is_online = true` filtered to rows not present in the local in-memory map (once phase 1 lands, filter to rows not in the Redis directory). ~5 lines. +- Periodic reconciliation: every 30s, reconcile DB state against the Redis directory. Drift โ†’ DB loses, directory wins. +- Move the is-online write off the hot path: today we fire `device.setHostOnline.mutate(...)` against the API on every register. With thrash (flaky clients reconnecting) this is a lot of writes. Batch or debounce. + +**Exit criteria:** Kill a relay machine with `fly machine stop`; within 60s, every host that was on it is flipped to `is_online=false` in the DB and the UI reflects it. + +### Phase 3 โ€” streaming support + +**Probably the biggest latent correctness bug.** Currently `tunnel-client.ts:144` does `await response.text()` โ€” the entire HTTP response body is buffered on the host before being sent to the relay. That kills SSE, tRPC subscriptions, and any chunked response. Chat streams work today only because they use `httpBatchStreamLink` to the tRPC endpoint which the host then terminates; the relay tunnel itself isn't streaming. + +- Change the tunnel protocol from `{type: "http:response"}` one-shot to `{type: "http:response:start", headers, status} + {type: "http:response:chunk", data} + {type: "http:response:end"}`. +- Relay side: pipe chunks directly to the `Response` body stream. +- Same treatment for large request bodies (today `await c.req.text()` in `index.ts:118`). + +**Exit criteria:** a 10MB file download through the tunnel starts arriving client-side before the last byte leaves the host. + +### Phase 4 โ€” reliability & graceful shutdown + +- **SIGTERM handling on relay.** Intercept SIGTERM (fly sends this on scale-down/deploy), stop accepting new tunnels, send a close frame `{code: 4001, reason: "server-drain"}` to every tunneled host, wait up to 10s for graceful close, then exit. Hosts treat code 4001 as "reconnect immediately, no backoff." +- **Client-side missed-pong detection.** Today the client only reconnects on `onclose`. Add a dead-socket detector: if no `onmessage` (including pings) for 45s, forcibly close and reconnect. Server pings every 30s (`tunnel.ts:55`); three missed pings = 90s to detect, too slow. Also have the client send an app-level ping every 15s so the server can detect dead clients sooner (currently the server only knows about client liveness via TCP). +- **Tighter ping cadence.** 10s ping interval, 3 missed = 30s to detect. Tradeoff: ~10 ping frames/minute/host ร— 1k hosts = 166 msg/s, trivial. +- **Request timeout policy.** `REQUEST_TIMEOUT_MS = 30_000` at `tunnel.ts:33` is too short for some tRPC calls (chat.sendMessage saw 11s already). Raise to 120s, and mark streaming requests (phase 3) as never-timing-out at this layer. +- **Backoff cap lowered.** `RECONNECT_MAX_MS = 30_000` is fine but combined with TCP FIN timing a dead server isn't noticed for up to ~90s. Not a backoff issue; the missed-pong detector above fixes it. + +### Phase 5 โ€” observability + +- **Admin endpoint.** `GET /admin/tunnels` (auth-gated by a shared secret env var, not user JWT), returns `[{ hostId, machineId, connectedAt, pendingRequests, activeChannels, lastPongAt }]` read from Redis. Replaces the "grep fly logs" workflow. +- **Metrics.** Ship Prometheus-format metrics at `/metrics` or push to fly's built-in metrics: + - `relay_tunnels_current` (gauge, per machine) + - `relay_tunnel_register_total`, `relay_tunnel_unregister_total` + - `relay_request_total{status,route}` + - `relay_request_duration_seconds{route}` histogram + - `relay_proxy_errors_total{reason}` (timeout, tunnel_missing, remote_error, ...) + - `relay_replay_hits_total{cross_machine=true}` โ€” fraction of cross-machine replays (too high = need sticky LB tuning) +- **Structured logs.** Today logs are `[relay] ...` strings. Move to JSON via `pino` or similar with `{ level, msg, hostId, userId, machineId }` on every line; grep-friendly + pipable to any log provider later. +- **Alerts.** Starting set, alertmanager/sentry routing: + - 503 rate > 2% sustained 1m + - tunnel register โ†’ unregister in < 5s (flapping) + - replay hit rate > 40% (routing fighting us) + - p95 proxy latency > 2s + +### Phase 6 โ€” data-model fixes + +- **Decouple `name` from `v2_hosts`.** Today every `(org, machine_id)` row carries its own `name`. Two registrations of the same physical machine can have different names. Lift `name` (and probably `os`, `cpu_count`, `total_memory`, `agent_version`) to a `v2_machines` table keyed by `machine_id`; `v2_hosts.machine_id` FKs in. Migration: backfill `v2_machines` from existing distinct `(machine_id, most_recent name)`, drop `name` from `v2_hosts`. +- **Fix UUID-as-name leak.** Find the register codepath that sometimes passes a UUID where the hostname should go (`v2_hosts.id = 7cd349d5-โ€ฆ` has `name = '2b5fb23d-โ€ฆ'`). Likely in `device.setHostOnline` or a register-adjacent mutation in `packages/trpc/src/router/device/device.ts`. Once in `v2_machines`, this bug becomes impossible because `name` is no longer written on register. +- **Add telemetry columns to `v2_hosts`:** `last_connected_at`, `last_disconnected_at`, `connected_machine_id`. Useful for debugging "when did it last talk to us?" without tailing fly logs. + +### Phase 7 โ€” load testing + +- Script: spin up N synthetic hosts (just `tunnel-client.ts` pointed at a mock local port) + M clients hammering `/hosts//...`. Measure p95 latency, CPU, memory, FD count per machine. +- Target capacity plan (guess, to validate): 5k concurrent tunnels per `performance-2x` machine with < 50ms p95 pass-through. +- Fault injection: kill a machine mid-run, verify clients reconnect within 30s. + +## Open questions + +- **Authorization on the admin endpoint.** Shared secret vs user JWT with role check? Shared secret is simpler and keeps `/admin/*` out of the normal auth path. Probably the right call. +- **Do we want a `v2_machines` table, or fold `name` etc. onto `devices`?** There's already a `device_presence` table that the MCP server reads. Might be simpler to converge those rather than add a third. Worth discussing with Avi/Kiet before phase 6. +- **Fly region.** Staying in `sjc` means ~80ms RTT from EU hosts. Could shard to `fra` later, but scale-out-within-region first. +- **TLS inside the tunnel?** Relay terminates TLS from the client and opens a plaintext WS to localhost on the host. Fine since the host-service WS is on loopback. Worth documenting so nobody bolts TLS on unnecessarily. + +## Milestones / ETA + +Rough; assumes one person (me) full-time, review async. + +- Phase 1: 4โ€“5 days. The real work. +- Phase 2: 1 day. +- Phase 3: 2โ€“3 days. +- Phase 4: 2 days. +- Phase 5: 2 days. +- Phase 6: 1 day + DB migration review. +- Phase 7: 1 day. + +Total ~2.5 weeks if done serially, less with parallel review. diff --git a/apps/web/package.json b/apps/web/package.json index f0199c0a333..fa2e32fd46d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -24,7 +24,7 @@ "@trpc/server": "^11.7.1", "@trpc/tanstack-react-query": "^11.7.1", "@uiw/react-md-editor": "^4.0.11", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "framer-motion": "^12.23.26", "geist": "^1.7.0", "import-in-the-middle": "2.0.1", diff --git a/bun.lock b/bun.lock index 4c2e32b1daa..f81d6dcf926 100644 --- a/bun.lock +++ b/bun.lock @@ -27,9 +27,9 @@ "@trpc/client": "^11.7.1", "@trpc/server": "^11.7.1", "@trpc/tanstack-react-query": "^11.7.1", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "date-fns": "^4.1.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "import-in-the-middle": "2.0.1", "next": "^16.0.10", "next-themes": "^0.4.6", @@ -60,7 +60,7 @@ "version": "0.1.0", "dependencies": { "@anthropic-ai/sdk": "^0.78.0", - "@better-auth/oauth-provider": "1.5.6", + "@better-auth/oauth-provider": "1.6.5", "@durable-streams/client": "^0.2.3", "@electric-sql/client": "1.5.15", "@linear/sdk": "^68.1.0", @@ -83,9 +83,9 @@ "@upstash/ratelimit": "^2.0.4", "@upstash/redis": "^1.34.3", "@vercel/blob": "^2.0.0", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "date-fns": "^4.1.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "import-in-the-middle": "2.0.1", "jose": "^6.1.3", "lodash.chunk": "^4.2.0", @@ -116,8 +116,8 @@ "@ai-sdk/openai": "3.0.36", "@ai-sdk/react": "^3.0.0", "@ast-grep/napi": "^0.41.0", - "@better-auth/api-key": "1.5.6", - "@better-auth/stripe": "1.5.6", + "@better-auth/api-key": "1.6.5", + "@better-auth/stripe": "1.6.5", "@codemirror/commands": "^6.10.2", "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-css": "^6.3.1", @@ -135,7 +135,6 @@ "@codemirror/lang-yaml": "^6.1.2", "@codemirror/language": "^6.12.2", "@codemirror/legacy-modes": "^6.5.2", - "@codemirror/merge": "^6.12.1", "@codemirror/search": "^6.6.0", "@codemirror/state": "^6.5.4", "@codemirror/theme-one-dark": "^6.1.3", @@ -165,7 +164,6 @@ "@superset/host-service": "workspace:*", "@superset/local-db": "workspace:*", "@superset/macos-process-metrics": "workspace:*", - "@superset/macos-window-blur": "workspace:*", "@superset/panes": "workspace:*", "@superset/shared": "workspace:*", "@superset/trpc": "workspace:*", @@ -180,7 +178,6 @@ "@tanstack/react-router": "^1.147.3", "@tanstack/react-table": "^8.21.3", "@tanstack/react-virtual": "^3.13.18", - "@taplo/lib": "^0.5.0", "@tiptap/core": "^3.17.1", "@tiptap/extension-blockquote": "^3.17.1", "@tiptap/extension-bold": "^3.17.1", @@ -219,44 +216,32 @@ "@types/express": "^5.0.5", "@types/pidusage": "^2.0.5", "@vercel/blob": "^2.0.0", - "@vscode/ripgrep": "^1.15.9", - "@xterm/addon-clipboard": "0.3.0-beta.195", - "@xterm/addon-fit": "0.12.0-beta.195", - "@xterm/addon-image": "0.10.0-beta.195", - "@xterm/addon-ligatures": "0.11.0-beta.195", - "@xterm/addon-progress": "0.3.0-beta.195", - "@xterm/addon-search": "0.17.0-beta.195", - "@xterm/addon-serialize": "0.15.0-beta.195", - "@xterm/addon-unicode11": "0.10.0-beta.195", - "@xterm/addon-webgl": "0.20.0-beta.194", - "@xterm/headless": "6.1.0-beta.195", - "@xterm/xterm": "6.1.0-beta.195", - "@xyflow/react": "^12.10.0", + "@xterm/addon-clipboard": "0.3.0-beta.197", + "@xterm/addon-fit": "0.12.0-beta.197", + "@xterm/addon-image": "0.10.0-beta.197", + "@xterm/addon-ligatures": "0.11.0-beta.197", + "@xterm/addon-progress": "0.3.0-beta.197", + "@xterm/addon-search": "0.17.0-beta.197", + "@xterm/addon-serialize": "0.15.0-beta.197", + "@xterm/addon-unicode11": "0.10.0-beta.197", + "@xterm/addon-webgl": "0.20.0-beta.196", + "@xterm/headless": "6.1.0-beta.197", + "@xterm/xterm": "6.1.0-beta.197", "ai": "^6.0.0", - "ansi_up": "^6.0.6", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "better-sqlite3": "12.6.2", "bindings": "^1.5.0", "bufferutil": "^4.1.0", "clsx": "^2.1.1", - "cron-parser": "^5.5.0", - "cronstrue": "^3.14.0", "culori": "^4.0.2", "date-fns": "^4.1.0", "default-shell": "^2.2.0", "detect-libc": "2.0.4", "dexie": "^4.4.2", - "diff": "^7.0.0", "dnd-core": "^16.0.1", - "dockerfile-ast": "0.7.1", - "dockerfile-language-server-nodejs": "^0.15.0", - "dockerfile-language-service": "0.16.1", - "dockerfile-utils": "0.16.3", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "electron-updater": "^6.8.3", - "elkjs": "^0.11.1", - "exceljs": "^4.4.0", "execa": "^9.6.0", "express": "^5.1.0", "fast-glob": "^3.3.3", @@ -264,16 +249,10 @@ "framer-motion": "^12.23.26", "friendly-words": "^1.3.1", "fuse.js": "^7.1.0", - "graphql": "^16.13.2", - "graphql-language-service-cli": "^3.5.0", "highlight.js": "^11.11.1", - "html-to-image": "^1.11.13", "http-proxy": "^1.18.1", - "https-proxy-agent": "^7.0.2", "idb-keyval": "^6.2.2", "jose": "^6.1.3", - "js-yaml": "^4.1.1", - "jszip": "^3.10.1", "libsql": "0.5.22", "line-column-path": "^3.0.0", "lodash": "^4.17.21", @@ -285,20 +264,17 @@ "node-addon-api": "^7.1.0", "node-pty": "1.1.0", "os-locale": "^6.0.2", - "pg": "8.20.0", "pidtree": "^0.6.0", "pidusage": "^4.0.1", "posthog-js": "1.310.1", "posthog-node": "^5.24.7", "prebuild-install": "^7.1.1", - "proxy-from-env": "^1.1.0", - "pyright": "^1.1.408", "react": "19.2.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "19.2.0", "react-hook-form": "^7.71.1", - "react-hotkeys-hook": "5.2.4", + "react-hotkeys-hook": "^5.2.4", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-mosaic-component": "^6.1.1", @@ -307,11 +283,9 @@ "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", "remark-gfm": "^4.0.1", - "remark-github-blockquote-alert": "^2.1.0", "semver": "^7.7.3", "shell-env": "^4.0.3", "shell-quote": "^1.8.3", - "shiki": "^3.21.0", "simple-git": "^3.30.0", "streamdown": "2.5.0", "strip-ansi": "^7.1.2", @@ -325,15 +299,6 @@ "use-resize-observer": "^9.1.0", "utf-8-validate": "^6.0.6", "uuid": "^13.0.0", - "vscode-css-languageservice": "^6.3.10", - "vscode-html-languageservice": "^5.6.2", - "vscode-json-languageservice": "^5.7.2", - "vscode-langservers-extracted": "^4.10.0", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "3.17.3", - "ws": "^8.18.0", - "yaml-language-server": "^1.21.0", - "yauzl": "^2.9.2", "zod": "^4.3.5", "zustand": "^5.0.8", }, @@ -346,18 +311,14 @@ "@types/better-sqlite3": "^7.6.13", "@types/bun": "^1.2.17", "@types/culori": "^4.0.1", - "@types/diff": "^6.0.0", "@types/http-proxy": "^1.17.17", - "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.20", "@types/node": "^24.9.1", - "@types/pg": "8.15.6", "@types/react": "~19.2.2", "@types/react-dom": "^19.2.3", "@types/react-syntax-highlighter": "^15.5.13", "@types/semver": "^7.7.1", "@types/shell-quote": "^1.7.5", - "@types/ws": "^8.18.1", "@vitejs/plugin-react": "^5.0.1", "code-inspector-plugin": "^1.2.2", "cross-env": "^10.0.0", @@ -415,7 +376,7 @@ "version": "0.0.0", "dependencies": { "@superset/db": "workspace:*", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "jose": "^6.1.3", }, "devDependencies": { @@ -480,7 +441,7 @@ "name": "@superset/mobile", "version": "1.0.0", "dependencies": { - "@better-auth/expo": "1.5.6", + "@better-auth/expo": "1.6.5", "@electric-sql/client": "1.5.15", "@expo/ui": "~55.0.0-preview.4", "@expo/vector-icons": "^15.0.3", @@ -518,7 +479,7 @@ "@tanstack/react-query": "^5.90.19", "@trpc/client": "^11.7.1", "@trpc/react-query": "^11.7.1", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.3.1", @@ -565,14 +526,6 @@ "typescript": "^5.9.3", }, }, - "apps/open-link": { - "name": "@superset/open-link", - "version": "0.0.0", - "devDependencies": { - "typescript": "^5.9.3", - "wrangler": "^4.14.4", - }, - }, "apps/relay": { "name": "@superset/relay", "version": "0.1.0", @@ -617,7 +570,7 @@ "@trpc/server": "^11.7.1", "@trpc/tanstack-react-query": "^11.7.1", "@uiw/react-md-editor": "^4.0.11", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "framer-motion": "^12.23.26", "geist": "^1.7.0", "import-in-the-middle": "2.0.1", @@ -651,10 +604,10 @@ "name": "@superset/auth", "version": "0.1.0", "dependencies": { - "@better-auth/api-key": "1.5.6", - "@better-auth/expo": "1.5.6", - "@better-auth/oauth-provider": "1.5.6", - "@better-auth/stripe": "1.5.6", + "@better-auth/api-key": "1.6.5", + "@better-auth/expo": "1.6.5", + "@better-auth/oauth-provider": "1.6.5", + "@better-auth/stripe": "1.6.5", "@superset/db": "workspace:*", "@superset/email": "workspace:*", "@superset/shared": "workspace:*", @@ -663,9 +616,9 @@ "@upstash/qstash": "^2.8.4", "@upstash/ratelimit": "^2.0.4", "@upstash/redis": "^1.34.3", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "resend": "^4.0.1", "stripe": "^20.2.0", "zod": "^4.3.5", @@ -743,7 +696,7 @@ "@neondatabase/serverless": "1.0.2", "@t3-oss/env-core": "^0.13.8", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "zod": "^4.3.5", }, "devDependencies": { @@ -811,7 +764,7 @@ "@trpc/client": "^11.7.1", "@trpc/server": "^11.7.1", "better-sqlite3": "12.6.2", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "hono": "^4.8.5", "mastracode": "0.14.0", "node-pty": "1.1.0", @@ -832,7 +785,7 @@ "name": "@superset/local-db", "version": "0.1.0", "dependencies": { - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "uuid": "^13.0.0", "zod": "^4.3.5", }, @@ -851,13 +804,6 @@ "node-addon-api": "^7.1.0", }, }, - "packages/macos-window-blur": { - "name": "@superset/macos-window-blur", - "version": "0.0.1", - "dependencies": { - "node-addon-api": "^7.1.0", - }, - }, "packages/mcp": { "name": "@superset/mcp", "version": "0.1.0", @@ -865,7 +811,7 @@ "@modelcontextprotocol/sdk": "^1.26.0", "@superset/db": "workspace:*", "@superset/shared": "workspace:*", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "zod": "^4.3.5", }, "devDependencies": { @@ -907,22 +853,6 @@ "typescript": "^5.9.3", }, }, - "packages/superset-browser-mcp": { - "name": "@superset/superset-browser-mcp", - "version": "0.1.0", - "bin": { - "superset-browser-mcp": "./src/bin.ts", - }, - "dependencies": { - "@modelcontextprotocol/sdk": "^1.26.0", - "zod": "^4.3.5", - }, - "devDependencies": { - "@superset/typescript": "workspace:*", - "@types/node": "^24.9.1", - "typescript": "^5.9.3", - }, - }, "packages/trpc": { "name": "@superset/trpc", "version": "0.1.0", @@ -936,7 +866,7 @@ "@upstash/qstash": "^2.8.4", "@vercel/blob": "^2.0.0", "@vercel/kv": "^3.0.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "superjson": "^2.2.5", "zod": "^4.3.5", }, @@ -977,7 +907,6 @@ "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-use-controllable-state": "^1.2.2", - "@streamdown/code": "1.0.2", "@streamdown/mermaid": "1.0.2", "@superset/shared": "workspace:*", "@xyflow/react": "^12.10.0", @@ -1054,7 +983,6 @@ "devDependencies": { "@superset/typescript": "workspace:*", "@types/node": "^24.9.1", - "@vscode/ripgrep": "^1.15.9", "typescript": "^5.9.3", }, }, @@ -1065,57 +993,52 @@ }, "trustedDependencies": [ "koffi", - "@vscode/ripgrep", + "sharp", "node-pty", "utf-8-validate", - "sharp", "esbuild", "electron", "better-sqlite3", "bufferutil", "workerd", ], - "patchedDependencies": { - "fstream@1.0.12": "patches/fstream@1.0.12.patch", - }, "overrides": { "axios": "1.14.0", - "fstream>mkdirp": "^0.5.6", }, "packages": { "7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="], "@a2a-js/sdk": ["@a2a-js/sdk@0.2.5", "", { "dependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.23", "body-parser": "^2.2.0", "cors": "^2.8.5", "express": "^4.21.2", "uuid": "^11.1.0" } }, "sha512-VTDuRS5V0ATbJ/LkaQlisMnTAeYKXAK6scMguVBstf+KIBQ7HIuKhiXLv+G/hvejkV+THoXzoNifInAkU81P1g=="], - "@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@3.0.97", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.77", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EUkR9ovQQY9dHVo67bchi9Qa+05FlSee6hTNZ6X1Rz1SJQKIIR2jt9rN7glRTvrYd+70zU7Xl993RKE3JtqT9w=="], + "@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@3.0.93", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.74", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-57cP3Ume6DdQP05xPYl2g554EqPrQgKRW/eE3BGm1ktK1k71e35HGzNl1GZHIYKct82QrY/iQuheanSonI88Dg=="], - "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.71", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bUWOzrzR0gJKJO/PLGMR4uH2dqEgqGhrsCV+sSpk4KtOEnUQlfjZI/F7BFlqSvVpFbjdgYRRLysAeEZpJ6S1lg=="], + "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.64", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-rwLi/Rsuj2pYniQXIrvClHvXDzgM4UQHHnvHTWEF14efnlKclG/1ghpNC+adsRujAbCTr6gRsSbDE2vEqriV7g=="], - "@ai-sdk/azure": ["@ai-sdk/azure@2.0.105", "", { "dependencies": { "@ai-sdk/openai": "2.0.103", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-pdYOtsFNJvNARbNxHORBIS6gwvU6yHdmgB3ZAzGdt89TiVtWiO1/quJeJ7Y3KUVLbjdpbVsTAWlL/J70XQxV5A=="], + "@ai-sdk/azure": ["@ai-sdk/azure@2.0.104", "", { "dependencies": { "@ai-sdk/openai": "2.0.102", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-g0ZDc/IgNCnIQuMj+bCBPionZwH4YBkfj5/CYeEPNqWrGBJm3aYfuWCjdT6Yayg+zlimunHZIjpjdDwan3i8Qg=="], - "@ai-sdk/cerebras": ["@ai-sdk/cerebras@1.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-UeBaOMXOcfkzHZE8TfbWRe9OMDkwB1NpHe837A+mRGWFabgdpJFTDnNrqCQVc3kGdDVhYBiDFh0lOEd8QRwJHQ=="], + "@ai-sdk/cerebras": ["@ai-sdk/cerebras@1.0.40", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.35", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KPtzWXMvRUI7nc/tpwQiP4LfEDwwSTSAkQLY++FKHHPr3Fnnt6Kjhq7sorF1qW5EROxmXNScQngnoU0z9lvcBg=="], - "@ai-sdk/deepseek": ["@ai-sdk/deepseek@1.0.37", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-GXSsA1wz0r9LdtEa7uxSB3ynaLHzKP7WmExrl5v5QgNVCmjmv/P4RhEMa1T6JFVdqG2sK1Nud/VWJ38LlnxkGg=="], + "@ai-sdk/deepseek": ["@ai-sdk/deepseek@1.0.36", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4PZ76VHbU2j8CsvbldrDzbao5VB5v2UhAbMgR6N6Fo1s7g4YE86+uBtP2god41qRIXtZXKurYuCEFjJGJEMR/w=="], - "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.83", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LvlWujbSdEkTBXBLFtF7GS6riXdHhH0O+DpDrCaNQvXeHmSF2jKsOg7JWXiCgygAHM5cWFAO3JYmZp83DjiuBQ=="], - "@ai-sdk/google": ["@ai-sdk/google@2.0.70", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-NDMTvMo6vnPHDTA94FBOh3YMv0lxWDohYmFSGYhg0IimHMcOcC1ZV7E2KMLjzHOz5S7uasTITW7V3X5T+ozInQ=="], + "@ai-sdk/google": ["@ai-sdk/google@2.0.67", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-A7iZeJf3RbNIrFBKsskd2s4c52tK0S0nX4rGlehjVHSYBvIZzrX+RW3Oxe7WnpeI0aON+5dVsqfGLFNYNGWEXw=="], - "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.132", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.77", "@ai-sdk/google": "2.0.70", "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-IZfAutGNrHPk7VsziwtBVsNBnXTS2y5qZpI1tT9MdN+O6z0UFv6LVBDIpAFAZcQOec9M22j+5uc4ukB6BfC/0A=="], + "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.127", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.74", "@ai-sdk/google": "2.0.67", "@ai-sdk/openai-compatible": "1.0.35", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kD2xC1HFbhNe5/yCJqkIP2rV40mlyK3IJiCoI6bwkjC5aPvWdBVoMIYvYcmM/eYlDYkPwC3pkUWd1HqRdLyzZw=="], - "@ai-sdk/groq": ["@ai-sdk/groq@2.0.38", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qw6OB9RTYy1JO1//FK/bE4o12sl6s6uff7+C2L0AlskRbqOw0oWNh1FjeQU9bqHdObL5P6/UU1Cnq0FcQ7OT3g=="], + "@ai-sdk/groq": ["@ai-sdk/groq@2.0.37", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-I3nceoFuNwJx8gEWx/mPl1rjbe2pes5UDor+7OtNYOBUcPzmkb1E3yyTMDKYW4JAlmBWLk0xwT9WwX9R/mpqzA=="], - "@ai-sdk/mistral": ["@ai-sdk/mistral@2.0.31", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ii+06f4Vzt3OH7/FNCj/QVms65VaZxqfat9GvMZ03ZdxlhO8yWzw83j3OqgdQ8pRL5qkABNepf06YUwfeNz6XQ=="], + "@ai-sdk/mistral": ["@ai-sdk/mistral@2.0.30", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-PhdfT0yFPRUsGxWQ8Gc0w/yog9UeYGo8US/4dQp608yhqV12ljxbot2VrqMUAeS6aZc0GDBVb+jGbLLb9SpDbw=="], "@ai-sdk/openai": ["@ai-sdk/openai@3.0.36", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.15" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-foY3onGY8l3q9niMw0Cwe9xrYnm46keIWL57NRw6F3DKzSW9TYTfx0cQJs/j8lXJ8lPzqNxpMO/zXOkqCUt3IQ=="], - "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.36", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ePJ1nj1Wv2QcG9m8zA3zT20WBInFqEfwV17KT0JBeRyQucmiJBwIhzLkOq95O0sBwUutJJJrQNG8pEYxGf6w3w=="], + "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.35", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wDN0NfYNfe/i+12YR3n6g7zETHNQrw8WJhL9IjgNG1shXdoFDCqzitSz2rYqfqbuKirUIcChrMvjIpcr5nX14w=="], - "@ai-sdk/perplexity": ["@ai-sdk/perplexity@2.0.28", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6KUdU+ccJEX+Y9xx8wKjEXIrELZINZg6NiZf2w9ZCcd96hC+8hkcq9TC4g3PDbtoA51ITfYXqwOer7UOx1nrZg=="], + "@ai-sdk/perplexity": ["@ai-sdk/perplexity@2.0.27", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-uyq8BEucqIm2Byp/JQ7iWKgV+s6B+mLFDBn4p4Dty8iyD/roQQMc5QXgQxJCLCR0duElEYYVh5hRCKIIzFy8LA=="], "@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], - "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.23", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg=="], + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], "@ai-sdk/provider-utils-v5": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], @@ -1125,18 +1048,16 @@ "@ai-sdk/provider-v6": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], - "@ai-sdk/react": ["@ai-sdk/react@3.0.170", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.23", "ai": "6.0.168", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-YUDn+mK0c8iUz14rCBf1A0zg6SV5b5aSVUz+azF1bdBd1SFXVI19dKYR+PQSpZY+0+z+zs252AAsacUqiO98Kw=="], + "@ai-sdk/react": ["@ai-sdk/react@3.0.143", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.21", "ai": "6.0.141", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-yYXrrscpF3MiCycGizgw1rukbhXBnoYpisC9vt12UU4i0tkyBMBCtBrsqLTJFrItax6ZR9TjTcGdNTqKqJhyow=="], - "@ai-sdk/togetherai": ["@ai-sdk/togetherai@1.0.39", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-RUKl8FD8WVnEHV//HnsNcV9r6lQGdfjYF2ypMON3eZZja2cGKdk/qrJnX9KBApkPjVmm2AiB1YBgkuVDWv8WTg=="], + "@ai-sdk/togetherai": ["@ai-sdk/togetherai@1.0.38", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.35", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-3sdh58EZ2rz9fBL8flVIY70Qosmc2QBPO/pzFjXdtumfBL73KAWjweBs9HkQxrfM3jy5CuRaC8q5qBkktWGHeQ=="], "@ai-sdk/ui-utils-v5": ["@ai-sdk/ui-utils@1.2.11", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w=="], - "@ai-sdk/xai": ["@ai-sdk/xai@2.0.68", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.36", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LqjizlypsbFcjVS/0BqGCPgvz4V5MaWCk+H7Tj7bZFQ1Ca8hby2Q0wGJ6u1ypR4Z8rRLHmfyrZ0mAEm/vd/d/A=="], + "@ai-sdk/xai": ["@ai-sdk/xai@2.0.67", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.35", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8ykkoxZbgAQAvngRBmkja00yUdE8Op+LQXzBFQ12Jn3TZ/gkN7gp+BTcuZ8dYVSYpGbKv+yGe56sKkiYAbH6Kw=="], "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], - "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], - "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.78.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-PzQhR715td/m1UaaN5hHXjYB8Gl2lF9UVhrrGrZeysiF6Rb74Wc9GCB8hzLdzmQtBd1qe89F9OptgB9Za1Ib5w=="], @@ -1173,13 +1094,11 @@ "@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.41.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xFp68OCUEmWYcqoreZFaf2xwMhm/22Qf6bR2Qyn8WNVY9RF4m4+k5K+7Wn+n9xy0vHUPhtFd1So/SvuaqLHEoA=="], - "@astrojs/compiler": ["@astrojs/compiler@2.13.1", "", {}, "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg=="], - "@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="], "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], - "@aws-sdk/types": ["@aws-sdk/types@3.973.8", "", { "dependencies": { "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw=="], + "@aws-sdk/types": ["@aws-sdk/types@3.973.7", "", { "dependencies": { "@smithy/types": "^4.14.0", "tslib": "^2.6.2" } }, "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg=="], "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], @@ -1249,8 +1168,6 @@ "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew=="], - "@babel/plugin-syntax-import-assertions": ["@babel/plugin-syntax-import-assertions@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw=="], - "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="], "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], @@ -1355,8 +1272,6 @@ "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="], - "@babel/polyfill": ["@babel/polyfill@7.12.1", "", { "dependencies": { "core-js": "^2.6.5", "regenerator-runtime": "^0.13.4" } }, "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g=="], - "@babel/preset-react": ["@babel/preset-react@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ=="], "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="], @@ -1367,31 +1282,33 @@ "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + "@babel/traverse--for-generate-function-map": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], - "@better-auth/api-key": ["@better-auth/api-key@1.5.6", "", { "dependencies": { "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "0.3.1", "better-auth": "1.5.6" } }, "sha512-jr3m4/caFxn9BuY9pGDJ4B1HP1Qoqmyd7heBHm4KUFel+a9Whe/euROgZ/L+o7mbmUdZtreneaU15dpn0tJZ5g=="], + "@better-auth/api-key": ["@better-auth/api-key@1.6.5", "", { "dependencies": { "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "better-auth": "^1.6.5" } }, "sha512-OaWrtidL56J2tYi+hkzqr52pN3LCQrYMDL90fyElHwewxcHzl/su13szp6FFjeF2BrclUQTdTkICHbShamb8og=="], - "@better-auth/core": ["@better-auth/core@1.5.6", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.2", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-Ez9DZdIMFyxHremmoLz1emFPGNQomDC1jqqBPnZ6Ci+6TiGN3R9w/Y03cJn6I8r1ycKgOzeVMZtJ/erOZ27Gsw=="], + "@better-auth/core": ["@better-auth/core@1.6.5", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.5", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-T3u4rVsJcMWShG2qfQUlU1HdkQGLYX0+lcR48QV2Cp2kpBOLOTYdt+p6zZtGm2Omx/ReEouRQyKy7pYtahRQuA=="], - "@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "drizzle-orm": ">=0.41.0" }, "optionalPeers": ["drizzle-orm"] }, "sha512-VfFFmaoFw3ug12SiSuIwzrMoHyIVmkMGWm9gZ4sXdYYVX4HboCL4m3fjzOhppcmK5OGatRuU+N1UX6wxCITcXw=="], + "@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "drizzle-orm": "^0.45.2" }, "optionalPeers": ["drizzle-orm"] }, "sha512-9YjPW35+h66D+QA+YqEJ9pFP97ClLFR+QrTPZojkeP0PTYqpW0ErBK3p1pwRTJG88yK+o3Y4yOwoacMTBxz0jQ=="], - "@better-auth/expo": ["@better-auth/expo@1.5.6", "", { "dependencies": { "@better-fetch/fetch": "1.1.21", "better-call": "1.3.2", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "1.5.6", "better-auth": "1.5.6", "expo-constants": ">=17.0.0", "expo-linking": ">=7.0.0", "expo-network": ">=8.0.7", "expo-web-browser": ">=14.0.0" }, "optionalPeers": ["expo-constants", "expo-linking", "expo-network", "expo-web-browser"] }, "sha512-LZsX8c1hbo+W3EEx3bpuO+MCl8BKhuiboGs8+Kaq6TaB3Ca684oGgvWAhHVPaH4yd6TA+jdX5QC+RXb9xX2Gmw=="], + "@better-auth/expo": ["@better-auth/expo@1.6.5", "", { "dependencies": { "@better-fetch/fetch": "1.1.21", "better-call": "1.3.5", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.5", "better-auth": "^1.6.5", "expo-constants": ">=17.0.0", "expo-linking": ">=7.0.0", "expo-network": ">=8.0.7", "expo-web-browser": ">=14.0.0" }, "optionalPeers": ["expo-constants", "expo-linking", "expo-network", "expo-web-browser"] }, "sha512-xLPx1d4eL24HYb9Jh9Eqeia09OiGH/2QZy41x6skKIwxEFyRW/CtntjlRKn2FI5+O8bE2AO+efGLHFefCw6IJQ=="], - "@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "kysely": "^0.27.0 || ^0.28.0" }, "optionalPeers": ["kysely"] }, "sha512-Fnf+h8WVKtw6lEOmVmiVVzDf3shJtM60AYf9XTnbdCeUd6MxN/KnaJZpkgtYnRs7a+nwtkVB+fg4lGETebGFXQ=="], + "@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "kysely": "^0.28.14" }, "optionalPeers": ["kysely"] }, "sha512-kbevd70qzKNR3ZHF7q6/e0XXYRCXanLB2rvmTd3T8WbNEd9kYMqKjgTGNxL1ri5N+PEDUK6zfHx/HrvaEOfoHw=="], - "@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0" } }, "sha512-rS7ZsrIl5uvloUgNN0u9LOZJMMXnsZXVdUZ3MrTBKWM2KpoJjzPr9yN3Szyma5+0V7SltnzSGHPkYj2bEzzmlA=="], + "@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0" } }, "sha512-5qFUpSdQi+RwHSmNyHMSsJIrFjed8d/ASS61L2xyW7sjBLTIuR7JcgS6hif5cQbtPeq+Qz+Wct5q8oKw33qyqQ=="], - "@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-6+M3MS2mor8fTUV3EI1FBLP0cs6QfbN+Ovx9+XxR/GdfKIBoNFzmPEPRbdGt+ft6PvrITsUm+T70+kkHgVSP6w=="], + "@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-HvOUFTiSEFSGTzL/vE3FntTwQiZ79O/V+QcsCimR+65Bj3tOqdFaC1G2Yd1dQ9l2YHNXA9SNBrGekbk66RzJMw=="], - "@better-auth/oauth-provider": ["@better-auth/oauth-provider@1.5.6", "", { "dependencies": { "jose": "^6.1.3", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", "better-auth": "1.5.6", "better-call": "1.3.2" } }, "sha512-DSkdC4GLwUiDwwd4hxQZa+aqzFoMXQV0Im3k4igzGIW6VB2S0p0CIR+YCOxJP7lAP+1eepxvjTfG07sTXzu2Bw=="], + "@better-auth/oauth-provider": ["@better-auth/oauth-provider@1.6.5", "", { "dependencies": { "jose": "^6.1.3", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "better-auth": "^1.6.5", "better-call": "1.3.5" } }, "sha512-j/LzpR1tkzY+MIDebXbmGYQfxu81PPEGXwO8rbNXufwmR5wLFD0B0negwygiaC4q8lX+crnIFmG2R1JedLez/g=="], - "@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-UxY9vQJs1Tt+O+T2YQnseDMlWmUSQvFZSBb5YiFRg7zcm+TEzujh4iX2/csA0YiZptLheovIuVWTP9nriewEBA=="], + "@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-d7PUO5XoimYYDEG/DoYVbOSbyVYJBDuZgvY9pjf8INccBTCD1BzcyEJ9NQil4huXWj4fcNaGOt2FG0OI8NtWOA=="], - "@better-auth/stripe": ["@better-auth/stripe@1.5.6", "", { "dependencies": { "defu": "^6.1.4", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "1.5.6", "better-auth": "1.5.6", "better-call": "1.3.2", "stripe": "^18 || ^19 || ^20" } }, "sha512-MVs9TKnFF0MV+bB+olMVBd5hwq4AhA6HYIdmZmUDzIv08dj968myhWr955R3dBMFsuS7+Bz7v4xQ3dlgU+ctCQ=="], + "@better-auth/stripe": ["@better-auth/stripe@1.6.5", "", { "dependencies": { "defu": "^6.1.5", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.5", "better-auth": "^1.6.5", "better-call": "1.3.5", "stripe": "^18 || ^19 || ^20 || ^21 || ^22" } }, "sha512-FnY3EptDjgpn5g6F04jrkz4R0qoygXUtftRWzINDOVU5FXfymKbFYKa5euVO3pQFilR0sEhCzB7aoRuSa6lr6w=="], - "@better-auth/telemetry": ["@better-auth/telemetry@1.5.6", "", { "dependencies": { "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.5.6" } }, "sha512-yXC7NSxnIFlxDkGdpD7KA+J9nqIQAPCJKe77GoaC5bWoe/DALo1MYorZfTgOafS7wrslNtsPT4feV/LJi1ubqQ=="], + "@better-auth/telemetry": ["@better-auth/telemetry@1.6.5", "", { "peerDependencies": { "@better-auth/core": "^1.6.5", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21" } }, "sha512-Ag3CjAP+tLretKPq+pYdU/gU4pFIcey/AoNQzw671wV5JQZXrMitS65INi8j8QuYfol2xgQrht5KVlcxGrkhHQ=="], - "@better-auth/utils": ["@better-auth/utils@0.3.1", "", {}, "sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg=="], + "@better-auth/utils": ["@better-auth/utils@0.4.0", "", { "dependencies": { "@noble/hashes": "^2.0.1" } }, "sha512-RpMtLUIQAEWMgdPLNVbIF5ON2mm+CH0U3rCdUCU1VyeAUui4m38DyK7/aXMLZov2YDjG684pS1D0MBllrmgjQA=="], "@better-fetch/fetch": ["@better-fetch/fetch@1.1.21", "", {}, "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A=="], @@ -1421,15 +1338,15 @@ "@cfworker/json-schema": ["@cfworker/json-schema@4.1.1", "", {}, "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og=="], - "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@12.0.0", "", { "dependencies": { "@chevrotain/gast": "12.0.0", "@chevrotain/types": "12.0.0" } }, "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg=="], + "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@11.1.2", "", { "dependencies": { "@chevrotain/gast": "11.1.2", "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q=="], - "@chevrotain/gast": ["@chevrotain/gast@12.0.0", "", { "dependencies": { "@chevrotain/types": "12.0.0" } }, "sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ=="], + "@chevrotain/gast": ["@chevrotain/gast@11.1.2", "", { "dependencies": { "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g=="], - "@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@12.0.0", "", {}, "sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA=="], + "@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.1.2", "", {}, "sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw=="], - "@chevrotain/types": ["@chevrotain/types@12.0.0", "", {}, "sha512-S+04vjFQKeuYw0/eW3U52LkAHQsB1ASxsPGsLPUyQgrZ2iNNibQrsidruDzjEX2JYfespXMG0eZmXlhA6z7nWA=="], + "@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="], - "@chevrotain/utils": ["@chevrotain/utils@12.0.0", "", {}, "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA=="], + "@chevrotain/utils": ["@chevrotain/utils@11.1.2", "", {}, "sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA=="], "@clack/core": ["@clack/core@0.4.2", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-NYQfcEy8MWIxrT5Fj8nIVchfRFA26yYKJcvBS7WlUIlw2OmQOY9DhGGXMovyI5J5PpxrCPGkgUi207EBrjpBvg=="], @@ -1439,29 +1356,29 @@ "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.0", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "1.20260301.1 || ~1.20260302.1 || ~1.20260303.1 || ~1.20260304.1 || >1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-8ovsRpwzPoEqPUzoErAYVv8l3FMZNeBVQfJTvtzP4AgLSRGZISRfuChFxHWUQd3n6cnrwkuTGxT+2cGo8EsyYg=="], - "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260415.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-dsxaKsQm3LnPGNPEdsRv09QN3Y4DqCw7kX5j6noKqbAtro2jTr95sVlYM1jUxZ5FkOl1f7SXgaKKB9t5H5Nkbg=="], + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260317.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-8hjh3sPMwY8M/zedq3/sXoA2Q4BedlGufn3KOOleIG+5a4ReQKLlUah140D7J6zlKmYZAFMJ4tWC7hCuI/s79g=="], - "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260415.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+JgSgVA49KyKteHRA1SnonE4Zn5Ei5zdAp5FQMxFmXI8qulZw4Hl7safXxRyK4i9sTO8gl7TFOKO5Q64VPvSDQ=="], + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260317.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M/MnNyvO5HMgoIdr3QHjdCj2T1ki9gt0vIUnxYxBu9ISXS/jgtMl6chUVPJ7zHYBn9MyYr8ByeN6frjYxj0MGg=="], - "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260415.1", "", { "os": "linux", "cpu": "x64" }, "sha512-tU+9pwsqCy8afOVlGtiWrWQc/fedQK4SRm4KPIAt+zOiQWDxWASm6YGBUJis5c648WN80yz47qnmdDi8DQNOcA=="], + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260317.1", "", { "os": "linux", "cpu": "x64" }, "sha512-1ltuEjkRcS3fsVF7CxsKlWiRmzq2ZqMfqDN0qUOgbUwkpXsLVJsXmoblaLf5OP00ELlcgF0QsN0p2xPEua4Uug=="], - "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260415.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-bR9uITnV19r5NQ14xnypi2xHXu2iQvfYV8cVgx0JouFUmWwTEEAwFVojDdssGq93VHX9hr/pi2IRUZeegbYBog=="], + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260317.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-3QrNnPF1xlaNwkHpasvRvAMidOvQs2NhXQmALJrEfpIJ/IDL2la8g499yXp3eqhG3hVMCB07XVY149GTs42Xtw=="], - "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260415.1", "", { "os": "win32", "cpu": "x64" }, "sha512-4NuMLlerI0Ijua3Ir8HXQ+qyNvCUDEG5gDco5Om+sAiK6rnWiz+aGoSlbB8W16yW9QAgzCstbmXLiVknUBflfQ=="], + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260317.1", "", { "os": "win32", "cpu": "x64" }, "sha512-MfZTz+7LfuIpMGTa3RLXHX8Z/pnycZLItn94WRdHr8LPVet+C5/1Nzei399w/jr3+kzT4pDKk26JF/tlI5elpQ=="], - "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260418.1", "", {}, "sha512-bywXb2XmeSqrLCQYipcupLneqx015YhhNWz2v9b9iatpe8Cg551vP7ZuD5S2a6GfBka0dDnO70kIBiBvFglcrg=="], + "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260329.1", "", {}, "sha512-LxBHrYYI/AZ6OCbUzRqRgg6Rt1qev2KxN2NNd3saye41AO2g52cYvHV+ohts5oPnrIUD7YRjbgN/J3NU7e7m5A=="], - "@code-inspector/core": ["@code-inspector/core@1.5.1", "", { "dependencies": { "@vue/compiler-dom": "^3.5.13", "chalk": "^4.1.1", "dotenv": "^16.1.4", "launch-ide": "1.4.3", "portfinder": "^1.0.28" } }, "sha512-Y9JdgoxVh93xRMupTa1lT/v+UlcBEpM7Y1BTxQy924wSe6VVEXsJ1nPJ/Ob2HPMUAA6F568aHALi2KDUhA2kzg=="], + "@code-inspector/core": ["@code-inspector/core@1.4.5", "", { "dependencies": { "@vue/compiler-dom": "^3.5.13", "chalk": "^4.1.1", "dotenv": "^16.1.4", "launch-ide": "1.4.3", "portfinder": "^1.0.28" } }, "sha512-wskkSRX13TAqJG65d5sq0bRZ4kYktas/iE70xqXMOeqW/A6n2Zqhw5QRHANmEmlBvB9bP/bse+9iBkNN3Q2Skw=="], - "@code-inspector/esbuild": ["@code-inspector/esbuild@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1" } }, "sha512-Z/WZVCG6WaB9HTcDC8l15RpgEsfFj/WKLLr6cKNX/JzAYBroadLPw1N0sbUJUIQnow5cCo7KYpHrC1T27WVMnw=="], + "@code-inspector/esbuild": ["@code-inspector/esbuild@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5" } }, "sha512-KBwq7waqZ3L1CW7N9ff7aS0HxzamrslR08i5ovkLQe1p6tH9Axe9zzCrBnvgmB0UZsT2r/5wKLOWyEpq5+VYKw=="], - "@code-inspector/mako": ["@code-inspector/mako@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1" } }, "sha512-EQmqQnnyW8tf3EBRlYyRYv1n3W1PUcfaYuuXXAfBdfJIGMwJjj0PcrDsdiI5MNyFmIx3QdMREhWmPMx1LoAANg=="], + "@code-inspector/mako": ["@code-inspector/mako@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5" } }, "sha512-yrHgE5+b4ZL29Xt+y0H/9xrXSbRskq7dFhmE9GYFWCcgdWNCMD25hZd7xZVije94++H65Vw6Bu/abfqEx0peog=="], - "@code-inspector/turbopack": ["@code-inspector/turbopack@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1", "@code-inspector/webpack": "1.5.1" } }, "sha512-PeLbcDtKDoSrKPsWnwQc+Yj9KgCa3xbHxEwXa/aGVykilvfvYP9AH1z5BRyZLDgB21diSV75BPNpF+o/FQRYug=="], + "@code-inspector/turbopack": ["@code-inspector/turbopack@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5", "@code-inspector/webpack": "1.4.5" } }, "sha512-IG39ikmQthdx/oAxhpV7zsIQZ3Jpycl88JzH+UXHq0ZpfHwa1KdNc/9erP3kFMY4+ANmkmerqBk57knmRTGMRQ=="], - "@code-inspector/vite": ["@code-inspector/vite@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1", "chalk": "4.1.1" } }, "sha512-gkfmSmawYb1yDDuCft4DESXCAD3JxPt59dGiRoD78GhQzSYHk3tnLPZMH/GLBpdeFNbKHi1FtEMbAAECIJG9xg=="], + "@code-inspector/vite": ["@code-inspector/vite@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5", "chalk": "4.1.1" } }, "sha512-vBtH91afwYL7JV4zWcJJTFd65LJ4SZz5E9AwGgCF30/L1mdDx7U29D+M+JpaxSgsMB6monKSZh+ubbqYe0ixpQ=="], - "@code-inspector/webpack": ["@code-inspector/webpack@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1" } }, "sha512-8i3QI/bSirORDF/0P16T6NhNy1RxO7soip8sWeV/2btLbYCwyiaDnqT4Bw3JaM8MNz0N8NaA2qItUrrKE7TtCg=="], + "@code-inspector/webpack": ["@code-inspector/webpack@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5" } }, "sha512-lwUv+X1FNSUWz+FKcUsE2dT2pg6VFRRXKt16hg/m+Lwtdet2adfi6BFLZmNz3OPIEGbRB5Kjx6bfaghZhbDCCg=="], "@codemirror/autocomplete": ["@codemirror/autocomplete@6.20.1", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A=="], @@ -1501,15 +1418,13 @@ "@codemirror/lint": ["@codemirror/lint@6.9.5", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA=="], - "@codemirror/merge": ["@codemirror/merge@6.12.1", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/highlight": "^1.0.0", "style-mod": "^4.1.0" } }, "sha512-GA8hBq2T+IFM0sb5fk8CunTrqOulA3zurJmHtzcU15EMnL8aYpVINfJ5bkfd53M4ikwoew4Y1ydtSaAlk6+B1w=="], - "@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="], "@codemirror/state": ["@codemirror/state@6.6.0", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ=="], "@codemirror/theme-one-dark": ["@codemirror/theme-one-dark@6.1.3", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/highlight": "^1.0.0" } }, "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA=="], - "@codemirror/view": ["@codemirror/view@6.41.0", "", { "dependencies": { "@codemirror/state": "^6.6.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-6H/qadXsVuDY219Yljhohglve8xf4B8xJkVOEWfA5uiYKiTFppjqsvsfR5iPA0RbvRBoOyTZpbLIxe9+0UR8xA=="], + "@codemirror/view": ["@codemirror/view@6.40.0", "", { "dependencies": { "@codemirror/state": "^6.6.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg=="], "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], @@ -1549,13 +1464,7 @@ "@electron/windows-sign": ["@electron/windows-sign@1.2.2", "", { "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", "fs-extra": "^11.1.1", "minimist": "^1.2.8", "postject": "^1.0.0-alpha.6" }, "bin": { "electron-windows-sign": "bin/electron-windows-sign.js" } }, "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ=="], - "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], - - "@envelop/core": ["@envelop/core@5.5.1", "", { "dependencies": { "@envelop/instrumentation": "^1.0.0", "@envelop/types": "^5.2.1", "@whatwg-node/promise-helpers": "^1.2.4", "tslib": "^2.5.0" } }, "sha512-3DQg8sFskDo386TkL5j12jyRAdip/8yzK3x7YGbZBgobZ4aKXrvDU0GppU0SnmrpQnNaiTUsxBs9LKkwQ/eyvw=="], - - "@envelop/instrumentation": ["@envelop/instrumentation@1.0.0", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.2.1", "tslib": "^2.5.0" } }, "sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw=="], - - "@envelop/types": ["@envelop/types@5.2.1", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.5.0" } }, "sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg=="], + "@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], "@epic-web/invariant": ["@epic-web/invariant@1.0.0", "", {}, "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA=="], @@ -1615,15 +1524,15 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.32", "", {}, "sha512-+RtX6GNteOQEycWKcliKtHYQ3NvFamuD4ZCb7MLwzImkZwxRXjUO1kSVV5FFB2koK5WNYwUCye2KkDp8LFD1SQ=="], + "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.27", "", {}, "sha512-cnb3DZnWUWpezGFkJ8y4MT5f/lw6FcgDzeJzic+T+vpQHLHG1cg3SC3i1w1i8Bk4xKR4HPY3t9iIRNvtr5ml8A=="], - "@expo/cli": ["@expo/cli@55.0.24", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.15", "@expo/config-plugins": "~55.0.8", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.1", "@expo/image-utils": "^0.8.13", "@expo/json-file": "^10.0.13", "@expo/log-box": "55.0.10", "@expo/metro": "~55.0.0", "@expo/metro-config": "~55.0.16", "@expo/osascript": "^2.4.2", "@expo/package-manager": "^1.10.4", "@expo/plist": "^0.5.2", "@expo/prebuild-config": "^55.0.15", "@expo/require-utils": "^55.0.4", "@expo/router-server": "^55.0.14", "@expo/schema-utils": "^55.0.3", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.4", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^55.0.7", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-Z6Xh0WNTg1LvoZQ77zO3snF2cFiv1xf0VguDlwTL1Ql87oMOp30f7mjl9jeaSHqoWkgiAbmxgCKKIGjVX/keiA=="], + "@expo/cli": ["@expo/cli@55.0.19", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~55.0.11", "@expo/config-plugins": "~55.0.7", "@expo/devcert": "^1.2.1", "@expo/env": "~2.1.1", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@expo/log-box": "55.0.8", "@expo/metro": "~54.2.0", "@expo/metro-config": "~55.0.11", "@expo/osascript": "^2.4.2", "@expo/package-manager": "^1.10.3", "@expo/plist": "^0.5.2", "@expo/prebuild-config": "^55.0.11", "@expo/require-utils": "^55.0.3", "@expo/router-server": "^55.0.11", "@expo/schema-utils": "^55.0.2", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.4", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.3", "expo-server": "^55.0.6", "fetch-nodeshim": "^0.4.6", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.0", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-PPNWwPXHcLDFgNNmkLmlLm3fLiNTxr7sbhNx4mXdjo0U/2Wg3rWaCeg1yMx49llOpDLZEWJpyAwPvTBqWc8glw=="], "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="], - "@expo/config": ["@expo/config@55.0.15", "", { "dependencies": { "@expo/config-plugins": "~55.0.8", "@expo/config-types": "^55.0.5", "@expo/json-file": "^10.0.13", "@expo/require-utils": "^55.0.4", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-lHc0ELIQ8126jYOMZpLv3WIuvordW98jFg5aT/J1/12n2ycuXu01XLZkJsdw0avO34cusUYb1It+MvY8JiMduA=="], + "@expo/config": ["@expo/config@55.0.11", "", { "dependencies": { "@expo/config-plugins": "~55.0.7", "@expo/config-types": "^55.0.5", "@expo/json-file": "^10.0.12", "@expo/require-utils": "^55.0.3", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-14AkSmR1gOIUhCsPJ0cAo5ZduMNsPQsmFV9jBNZn1xC5Zb3D8x5eqvUie5QzWaUwdcyrq79uYJ2bTCiC6+nD0Q=="], - "@expo/config-plugins": ["@expo/config-plugins@55.0.8", "", { "dependencies": { "@expo/config-types": "^55.0.5", "@expo/json-file": "~10.0.13", "@expo/plist": "^0.5.2", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-8WfWTRntTCcowfOS+tHdB0z98gKetTwktg4G5TWkCkXVa8Jt1NUnvzaaU4UHk2vbR2U4N84RyZJFizSwfF6C9g=="], + "@expo/config-plugins": ["@expo/config-plugins@55.0.7", "", { "dependencies": { "@expo/config-types": "^55.0.5", "@expo/json-file": "~10.0.12", "@expo/plist": "^0.5.2", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA=="], "@expo/config-types": ["@expo/config-types@55.0.5", "", {}, "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg=="], @@ -1631,41 +1540,41 @@ "@expo/devtools": ["@expo/devtools@55.0.2", "", { "dependencies": { "chalk": "^4.1.2" }, "peerDependencies": { "react": "*", "react-native": "*" }, "optionalPeers": ["react", "react-native"] }, "sha512-4VsFn9MUriocyuhyA+ycJP3TJhUsOFHDc270l9h3LhNpXMf6wvIdGcA0QzXkZtORXmlDybWXRP2KT1k36HcQkA=="], - "@expo/dom-webview": ["@expo/dom-webview@55.0.5", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-lt3uxYOCk3wmWvtOOvsC35CKGbDAOx5C2EaY8SH1JVSfBzqmF8Cs0Xp1MPxncDPMyxpMiWx5SvvV/iLF1rJU4A=="], + "@expo/dom-webview": ["@expo/dom-webview@55.0.3", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-bY4/rfcZ0f43DvOtMn8/kmPlmo01tex5hRoc5hKbwBwQjqWQuQt0ACwu7akR9IHI4j0WNG48eL6cZB6dZUFrzg=="], "@expo/env": ["@expo/env@2.1.1", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-rVvHC4I6xlPcg+mAO09ydUi2Wjv1ZytpLmHOSzvXzBAz9mMrJggqCe4s4dubjJvi/Ino/xQCLhbaLCnTtLpikg=="], "@expo/fingerprint": ["@expo/fingerprint@0.16.6", "", { "dependencies": { "@expo/env": "^2.0.11", "@expo/spawn-async": "^1.7.2", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-nRITNbnu3RKSHPvKVehrSU4KG2VY9V8nvULOHBw98ukHCAU4bGrU5APvcblOkX3JAap+xEHsg/mZvqlvkLInmQ=="], - "@expo/image-utils": ["@expo/image-utils@0.8.13", "", { "dependencies": { "@expo/require-utils": "^55.0.4", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "semver": "^7.6.0" } }, "sha512-1I//yBQeTY6p0u1ihqGNDAr35EbSG8uFEupFrIF0jd++h9EWH33521yZJU1yE+mwGlzCb61g3ehu78siMhXBlA=="], + "@expo/image-utils": ["@expo/image-utils@0.8.12", "", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-3KguH7kyKqq7pNwLb9j6BBdD/bjmNwXZG/HPWT6GWIXbwrvAJt2JNyYTP5agWJ8jbbuys1yuCzmkX+TU6rmI7A=="], - "@expo/json-file": ["@expo/json-file@10.0.13", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-pX/XjQn7tgNw6zuuV2ikmegmwe/S7uiwhrs2wXrANMkq7ozrA+JcZwgW9Q/8WZgciBzfAhNp5hnackHcrmapQA=="], + "@expo/json-file": ["@expo/json-file@10.0.12", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-inbDycp1rMAelAofg7h/mMzIe+Owx6F7pur3XdQ3EPTy00tme+4P6FWgHKUcjN8dBSrnbRNpSyh5/shzHyVCyQ=="], - "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@55.0.11", "", { "dependencies": { "@expo/config": "~55.0.15", "chalk": "^4.1.2" } }, "sha512-rJ4RTCrkeKaXaido/bVyhl90ZRtVTOEbj59F1PWVjIEIVgjdlfc1J3VD9v7hEsbf/+8Tbr/PgvWhT6Visi5sLQ=="], + "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@55.0.7", "", { "dependencies": { "@expo/config": "~55.0.10", "chalk": "^4.1.2" } }, "sha512-Qg9uNZn1buv4zJUA4ZQaz+ZnKDCipRgjoEg2Gcp8Qfy+2Gq5yZKX4YN1TThCJ01LJk/pvJsCRxXlXZSwdZppgg=="], - "@expo/log-box": ["@expo/log-box@55.0.10", "", { "dependencies": { "@expo/dom-webview": "^55.0.5", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-7jdikExgIrCIF5e3P1qMwcUZ2tcxrNdVqE9Y8kNMUHqZ+ipMlin+SiZwJKHM1+am4CYGjhdyrzbnIpvEcLDYcg=="], + "@expo/log-box": ["@expo/log-box@55.0.8", "", { "dependencies": { "@expo/dom-webview": "^55.0.3", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-WVEuW1XcntUdOpQk8k9cUymM5FHKmEcPr6QO9SVIin3WYk5FbbwHRYr1T6GfwWF0UA2s9w9heeYolesq99vFIw=="], "@expo/mcp-tunnel": ["@expo/mcp-tunnel@0.2.4", "", { "dependencies": { "ws": "^8.18.3", "zod": "^3.25.76", "zod-to-json-schema": "^3.24.6" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.26.0" } }, "sha512-hxFzqdUNKCt+8pbGV3oGcd/aBNA1mmhwh3DSeXoHReypxzsiLYLITJs1OctglaPecfMA9qFb+6z/RIkRSf5S4g=="], - "@expo/metro": ["@expo/metro@55.0.0", "", { "dependencies": { "metro": "0.83.5", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-config": "0.83.5", "metro-core": "0.83.5", "metro-file-map": "0.83.5", "metro-minify-terser": "0.83.5", "metro-resolver": "0.83.5", "metro-runtime": "0.83.5", "metro-source-map": "0.83.5", "metro-symbolicate": "0.83.5", "metro-transform-plugins": "0.83.5", "metro-transform-worker": "0.83.5" } }, "sha512-wohGl+4y17rGHU+lq8UqC5neOXL/HOThorDYXTMbOcBL1jYwcK11MBc151gDMpjpgdVUzgHne0H5RfCIhIN4hA=="], + "@expo/metro": ["@expo/metro@54.2.0", "", { "dependencies": { "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-minify-terser": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3" } }, "sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w=="], - "@expo/metro-config": ["@expo/metro-config@55.0.16", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~55.0.15", "@expo/env": "~2.1.1", "@expo/json-file": "~10.0.13", "@expo/metro": "~55.0.0", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "~8.4.32", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-JaWDw0dmYZ5pOqA+3/Efvl8JzCVgWQVPogHFjTRC5azUgAsFV+T7moOaZTSgg4d+5TjFZjZbMZg4SUomE7LiGg=="], + "@expo/metro-config": ["@expo/metro-config@55.0.11", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~55.0.10", "@expo/env": "~2.1.1", "@expo/json-file": "~10.0.12", "@expo/metro": "~54.2.0", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "~8.4.32", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-qGxq7RwWpj0zNvZO/e5aizKrOKYYBrVPShSbxPOVB1EXcexxTPTxnOe4pYFg/gKkLIJe0t3jSSF8IDWlGdaaOg=="], - "@expo/metro-runtime": ["@expo/metro-runtime@55.0.9", "", { "dependencies": { "@expo/log-box": "55.0.10", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-H37b2Mc/8GiQbwtUFzUTxA3KsAMZu00SRg/RhbHa9xVE7J0n5ZX4NHy0LJEFAbkzTb1TUy1hLpo3oEKnG+rLyg=="], + "@expo/metro-runtime": ["@expo/metro-runtime@55.0.7", "", { "dependencies": { "@expo/log-box": "55.0.8", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-fV+DYvJ+A3fKEwkpJiXUhrpsWy4HjjbdapwJi/QmnGLFKYrzGvGqsWG+xf3mmUDwP413t6GL9162bnyMReYOaA=="], "@expo/osascript": ["@expo/osascript@2.4.2", "", { "dependencies": { "@expo/spawn-async": "^1.7.2" } }, "sha512-/XP7PSYF2hzOZzqfjgkoWtllyeTN8dW3aM4P6YgKcmmPikKL5FdoyQhti4eh6RK5a5VrUXJTOlTNIpIHsfB5Iw=="], - "@expo/package-manager": ["@expo/package-manager@1.10.4", "", { "dependencies": { "@expo/json-file": "^10.0.13", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-y9Mr4Kmpk4abAVZrNNPCdzOZr8nLLyi18p1SXr0RCVA8IfzqZX/eY4H+50a0HTmXqIsPZrQdcdb4I3ekMS9GvQ=="], + "@expo/package-manager": ["@expo/package-manager@1.10.3", "", { "dependencies": { "@expo/json-file": "^10.0.12", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-ZuXiK/9fCrIuLjPSe1VYmfp0Sa85kCMwd8QQpgyi5ufppYKRtLBg14QOgUqj8ZMbJTxE0xqzd0XR7kOs3vAK9A=="], "@expo/plist": ["@expo/plist@0.5.2", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g=="], - "@expo/prebuild-config": ["@expo/prebuild-config@55.0.15", "", { "dependencies": { "@expo/config": "~55.0.15", "@expo/config-plugins": "~55.0.8", "@expo/config-types": "^55.0.5", "@expo/image-utils": "^0.8.13", "@expo/json-file": "^10.0.13", "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-UcCzVhVBE42UbY5U3t/q1Rk2fSFW/B50LJpB6oFpXhImJfvLKu7ayOFU9XcHd38K89i4GqSia/xXuxQvu4RUBg=="], + "@expo/prebuild-config": ["@expo/prebuild-config@55.0.11", "", { "dependencies": { "@expo/config": "~55.0.11", "@expo/config-plugins": "~55.0.7", "@expo/config-types": "^55.0.5", "@expo/image-utils": "^0.8.12", "@expo/json-file": "^10.0.12", "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-PqjbTTHXS0dnZMH4X5/0rnLxKfQqyN1s/5lmxITn+U6WDUNibatUepfjwV+5C2jU4hv5z2haqX6e9hQ0zUtDMA=="], - "@expo/require-utils": ["@expo/require-utils@55.0.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0" }, "optionalPeers": ["typescript"] }, "sha512-JAANvXqV7MOysWeVWgaiDzikoyDjJWOV/ulOW60Zb3kXJfrx2oZOtGtDXDFKD1mXuahQgoM5QOjuZhF7gFRNjA=="], + "@expo/require-utils": ["@expo/require-utils@55.0.3", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0" }, "optionalPeers": ["typescript"] }, "sha512-TS1m5tW45q4zoaTlt6DwmdYHxvFTIxoLrTHKOFrIirHIqIXnHCzpceg8wumiBi+ZXSaGY2gobTbfv+WVhJY6Fw=="], - "@expo/router-server": ["@expo/router-server@55.0.14", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^55.0.9", "expo": "*", "expo-constants": "^55.0.13", "expo-font": "^55.0.6", "expo-router": "*", "expo-server": "^55.0.7", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-YJjbeLMLp+ZjCnajHI+jEppNzXY372K0u4I4fLKGnA/loFX14aouDsg4tqZVGlZx6NUpnN8Bb3Tmw2BLTXT5Qw=="], + "@expo/router-server": ["@expo/router-server@55.0.11", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^55.0.6", "expo": "*", "expo-constants": "^55.0.9", "expo-font": "^55.0.4", "expo-router": "*", "expo-server": "^55.0.6", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-Kd8J1OOlFR00DZxn+1KfiQiXZtRut6cj8+ynqHJa7dtt/lTL4tGkYistqmVhpKJ6w886eRY5WivKy7o0ZBFkJA=="], - "@expo/schema-utils": ["@expo/schema-utils@55.0.3", "", {}, "sha512-l9KHVjTo6MvoeyvwNr6AjckGJm8NIcqZ3QSAh51cWozXW9v2AUjyCyqYtFtyntLWRZ0x/ByYJishpQo4ZQq45Q=="], + "@expo/schema-utils": ["@expo/schema-utils@55.0.2", "", {}, "sha512-QZ5WKbJOWkCrMq0/kfhV9ry8te/OaS34YgLVpG8u9y2gix96TlpRTbxM/YATjNcUR2s4fiQmPCOxkGtog4i37g=="], "@expo/sdk-runtime-versions": ["@expo/sdk-runtime-versions@1.0.0", "", {}, "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ=="], @@ -1673,21 +1582,15 @@ "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="], - "@expo/ui": ["@expo/ui@55.0.11", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-f2SaLzKjHdhDyT8qMm6d+MCXt+my8qWX3Q71ZRxy5/HQfE/NnBxkoJwscs2P9rJP8nkQr0evMZF3K28uv3UR8Q=="], + "@expo/ui": ["@expo/ui@55.0.6", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-VfKqr5gS21Y055mfmJBJqAzcDBy4edv0w0GBjZGaPOX1GtZRDA8hcZXwmeojD4tAofbFw+JiJcyYJ2CG+QjJVQ=="], "@expo/vector-icons": ["@expo/vector-icons@15.1.1", "", { "peerDependencies": { "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } }, "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw=="], "@expo/ws-tunnel": ["@expo/ws-tunnel@1.0.6", "", {}, "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q=="], - "@expo/xcpretty": ["@expo/xcpretty@4.4.3", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-wC562eD3gS6vO2tWHToFhlFnmHKfKHgF1oyvojeSkLK/ZYop1bMU+7cOMiF9Sq70CzcsLy/EMRy/uRc76QmNRw=="], + "@expo/xcpretty": ["@expo/xcpretty@4.4.1", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-KZNxZvnGCtiM2aYYZ6Wz0Ix5r47dAvpNLApFtZWnSoERzAdOMzVBOPysBoM0JlF6FKWZ8GPqgn6qt3dV/8Zlpg=="], - "@fast-csv/format": ["@fast-csv/format@4.3.5", "", { "dependencies": { "@types/node": "^14.0.1", "lodash.escaperegexp": "^4.1.2", "lodash.isboolean": "^3.0.3", "lodash.isequal": "^4.5.0", "lodash.isfunction": "^3.0.9", "lodash.isnil": "^4.0.0" } }, "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A=="], - - "@fast-csv/parse": ["@fast-csv/parse@4.3.6", "", { "dependencies": { "@types/node": "^14.0.1", "lodash.escaperegexp": "^4.1.2", "lodash.groupby": "^4.6.0", "lodash.isfunction": "^3.0.9", "lodash.isnil": "^4.0.0", "lodash.isundefined": "^3.0.1", "lodash.uniq": "^4.5.0" } }, "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA=="], - - "@fastify/busboy": ["@fastify/busboy@3.2.0", "", {}, "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA=="], - - "@fastify/otel": ["@fastify/otel@0.18.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.212.0", "@opentelemetry/semantic-conventions": "^1.28.0", "minimatch": "^10.2.4" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-3TASCATfw+ctICSb4ymrv7iCm0qJ0N9CarB+CZ7zIJ7KqNbwI5JjyDL1/sxoC0ccTO1Zyd1iQ+oqncPg5FJXaA=="], + "@fastify/otel": ["@fastify/otel@0.17.1", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.212.0", "@opentelemetry/semantic-conventions": "^1.28.0", "minimatch": "^10.2.4" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-K4wyxfUZx2ux5o+b6BtTqouYFVILohLZmSbA2tKUueJstNcBnoGPVhllCaOvbQ3ZrXdUxUC/fyrSWSCqHhdOPg=="], "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], @@ -1703,45 +1606,7 @@ "@fumadocs/ui": ["@fumadocs/ui@16.4.7", "", { "dependencies": { "next-themes": "^0.4.6", "postcss-selector-parser": "^7.1.1", "tailwind-merge": "^3.4.0" }, "peerDependencies": { "@types/react": "*", "fumadocs-core": "16.4.7", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "tailwindcss": "^4.0.0" }, "optionalPeers": ["@types/react", "next", "tailwindcss"] }, "sha512-NnkMIN5BzBRh2OzA9rp2SgbGEkEwfCfq0sE4vq2n+GkIDIggicGYUNgSl2gtIBQsKYKP/a4/0wrkQKdq4eUJlw=="], - "@google/genai": ["@google/genai@1.50.1", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ=="], - - "@graphql-hive/signal": ["@graphql-hive/signal@1.0.0", "", {}, "sha512-RiwLMc89lTjvyLEivZ/qxAC5nBHoS2CtsWFSOsN35sxG9zoo5Z+JsFHM8MlvmO9yt+MJNIyC5MLE1rsbOphlag=="], - - "@graphql-tools/batch-execute": ["@graphql-tools/batch-execute@9.0.19", "", { "dependencies": { "@graphql-tools/utils": "^10.9.1", "@whatwg-node/promise-helpers": "^1.3.0", "dataloader": "^2.2.3", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VGamgY4PLzSx48IHPoblRw0oTaBa7S26RpZXt0Y4NN90ytoE0LutlpB2484RbkfcTjv9wa64QD474+YP1kEgGA=="], - - "@graphql-tools/code-file-loader": ["@graphql-tools/code-file-loader@8.0.3", "", { "dependencies": { "@graphql-tools/graphql-tag-pluck": "8.1.0", "@graphql-tools/utils": "^10.0.0", "globby": "^11.0.3", "tslib": "^2.4.0", "unixify": "^1.0.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-gVnnlWs0Ua+5FkuHHEriFUOI3OIbHv6DS1utxf28n6NkfGMJldC4j0xlJRY0LS6dWK34IGYgD4HelKYz2l8KiA=="], - - "@graphql-tools/delegate": ["@graphql-tools/delegate@10.2.23", "", { "dependencies": { "@graphql-tools/batch-execute": "^9.0.19", "@graphql-tools/executor": "^1.4.9", "@graphql-tools/schema": "^10.0.25", "@graphql-tools/utils": "^10.9.1", "@repeaterjs/repeater": "^3.0.6", "@whatwg-node/promise-helpers": "^1.3.0", "dataloader": "^2.2.3", "dset": "^3.1.2", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-xrPtl7f1LxS+B6o+W7ueuQh67CwRkfl+UKJncaslnqYdkxKmNBB4wnzVcW8ZsRdwbsla/v43PtwAvSlzxCzq2w=="], - - "@graphql-tools/executor": ["@graphql-tools/executor@1.5.2", "", { "dependencies": { "@graphql-tools/utils": "^11.0.1", "@graphql-typed-document-node/core": "^3.2.0", "@repeaterjs/repeater": "^3.0.4", "@whatwg-node/disposablestack": "^0.0.6", "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-V7QaW/59Dml7DK0MApMP/Z+qx2qkQ0inGJGi/n1JwBHRZehXTKDNKO7OFRA0h6V1w2afmcVso2GFwlDnPyusGA=="], - - "@graphql-tools/executor-common": ["@graphql-tools/executor-common@0.0.6", "", { "dependencies": { "@envelop/core": "^5.3.0", "@graphql-tools/utils": "^10.9.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-JAH/R1zf77CSkpYATIJw+eOJwsbWocdDjY+avY7G+P5HCXxwQjAjWVkJI1QJBQYjPQDVxwf1fmTZlIN3VOadow=="], - - "@graphql-tools/executor-graphql-ws": ["@graphql-tools/executor-graphql-ws@2.0.7", "", { "dependencies": { "@graphql-tools/executor-common": "^0.0.6", "@graphql-tools/utils": "^10.9.1", "@whatwg-node/disposablestack": "^0.0.6", "graphql-ws": "^6.0.6", "isomorphic-ws": "^5.0.0", "tslib": "^2.8.1", "ws": "^8.18.3" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-J27za7sKF6RjhmvSOwOQFeNhNHyP4f4niqPnerJmq73OtLx9Y2PGOhkXOEB0PjhvPJceuttkD2O1yMgEkTGs3Q=="], - - "@graphql-tools/executor-http": ["@graphql-tools/executor-http@1.3.3", "", { "dependencies": { "@graphql-hive/signal": "^1.0.0", "@graphql-tools/executor-common": "^0.0.4", "@graphql-tools/utils": "^10.8.1", "@repeaterjs/repeater": "^3.0.4", "@whatwg-node/disposablestack": "^0.0.6", "@whatwg-node/fetch": "^0.10.4", "@whatwg-node/promise-helpers": "^1.3.0", "meros": "^1.2.1", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-LIy+l08/Ivl8f8sMiHW2ebyck59JzyzO/yF9SFS4NH6MJZUezA1xThUXCDIKhHiD56h/gPojbkpcFvM2CbNE7A=="], - - "@graphql-tools/executor-legacy-ws": ["@graphql-tools/executor-legacy-ws@1.1.27", "", { "dependencies": { "@graphql-tools/utils": "^11.0.1", "@types/ws": "^8.0.0", "isomorphic-ws": "^5.0.0", "tslib": "^2.4.0", "ws": "^8.20.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-tz0K8U9VKr9G/murdPpsARM2SxrXKtaKHaFoAZQoxHpWgbTdoGgJoyT5AoY6MZkgLRi5g24X0iZOLVtYlwy/nw=="], - - "@graphql-tools/graphql-file-loader": ["@graphql-tools/graphql-file-loader@8.1.13", "", { "dependencies": { "@graphql-tools/import": "^7.1.13", "@graphql-tools/utils": "^11.0.1", "globby": "^11.0.3", "tslib": "^2.4.0", "unixify": "^1.0.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-Su9RIYUrQ9yoKioObS5yNkGuOqwSIZVK79mre9ji+s3zr7UQepoKkuns6NrtmMcD1vUJyayzvr9YTaiLRbZGQA=="], - - "@graphql-tools/graphql-tag-pluck": ["@graphql-tools/graphql-tag-pluck@8.1.0", "", { "dependencies": { "@babel/core": "^7.22.9", "@babel/parser": "^7.16.8", "@babel/plugin-syntax-import-assertions": "^7.20.0", "@babel/traverse": "^7.16.8", "@babel/types": "^7.16.8", "@graphql-tools/utils": "^10.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-kt5l6H/7QxQcIaewInTcune6NpATojdFEW98/8xWcgmy7dgXx5vU9e0AicFZIH+ewGyZzTpwFqO2RI03roxj2w=="], - - "@graphql-tools/import": ["@graphql-tools/import@7.1.13", "", { "dependencies": { "@graphql-tools/utils": "^11.0.1", "resolve-from": "5.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-7leXxlZqVylYL2nvmcF3jUQuH3piT0unBpbPQ3F7r5UM0rehkgEcXxTeR8hZ3aQDeMVyaTli9bJjFTFErldYRg=="], - - "@graphql-tools/json-file-loader": ["@graphql-tools/json-file-loader@8.0.27", "", { "dependencies": { "@graphql-tools/utils": "^11.0.1", "globby": "^11.0.3", "tslib": "^2.4.0", "unixify": "^1.0.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-iOMleQVqNOLDslrE1eLXFJ/z7uSBHd7kM6M+vpS3CvON2nccBK0NIMkdy0385m1LCHyfBKds/rsjMnGmjdXIhw=="], - - "@graphql-tools/load": ["@graphql-tools/load@8.1.9", "", { "dependencies": { "@graphql-tools/schema": "^10.0.32", "@graphql-tools/utils": "^11.0.1", "p-limit": "3.1.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-BXaghzA0KVRvDjAlhEb26OwtmLYsSqs29nVyubIRfRy28ysdzEH+9HkYgQHmorJN+QPBbh9Gdg8nsGKeTPBpLQ=="], - - "@graphql-tools/merge": ["@graphql-tools/merge@9.1.8", "", { "dependencies": { "@graphql-tools/utils": "^11.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-25V7WDrODo1cPrmuUCrqf5qlMA4a/Ow4aHaqJ1MnTUaluwsV3UiqzCHWux3HSLb0H63mkoZiuOrU5xJhxRcoCg=="], - - "@graphql-tools/schema": ["@graphql-tools/schema@10.0.32", "", { "dependencies": { "@graphql-tools/merge": "^9.1.8", "@graphql-tools/utils": "^11.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-kJ1Qn20MPnlaEVH37639E6rzQ1tEtr6XTUhNdR4EKydl+FijtLhWX2WLZbGnvrYuG8XUcMxsZU9mRRYYNvK02w=="], - - "@graphql-tools/url-loader": ["@graphql-tools/url-loader@8.0.33", "", { "dependencies": { "@graphql-tools/executor-graphql-ws": "^2.0.1", "@graphql-tools/executor-http": "^1.1.9", "@graphql-tools/executor-legacy-ws": "^1.1.19", "@graphql-tools/utils": "^10.9.1", "@graphql-tools/wrap": "^10.0.16", "@types/ws": "^8.0.0", "@whatwg-node/fetch": "^0.10.0", "@whatwg-node/promise-helpers": "^1.0.0", "isomorphic-ws": "^5.0.0", "sync-fetch": "0.6.0-2", "tslib": "^2.4.0", "ws": "^8.17.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-Fu626qcNHcqAj8uYd7QRarcJn5XZ863kmxsg1sm0fyjyfBJnsvC7ddFt6Hayz5kxVKfsnjxiDfPMXanvsQVBKw=="], - - "@graphql-tools/utils": ["@graphql-tools/utils@10.11.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-iBFR9GXIs0gCD+yc3hoNswViL1O5josI33dUqiNStFI/MHLCEPduasceAcazRH77YONKNiviHBV8f7OgcT4o2Q=="], - - "@graphql-tools/wrap": ["@graphql-tools/wrap@10.1.4", "", { "dependencies": { "@graphql-tools/delegate": "^10.2.23", "@graphql-tools/schema": "^10.0.25", "@graphql-tools/utils": "^10.9.1", "@whatwg-node/promise-helpers": "^1.3.0", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-7pyNKqXProRjlSdqOtrbnFRMQAVamCmEREilOXtZujxY6kYit3tvWWSjUrcIOheltTffoRh7EQSjpy2JDCzasg=="], + "@google/genai": ["@google/genai@1.49.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-hO69Zl0H3x+L0KL4stl1pLYgnqnwHoLqtKy6MRlNnW8TAxjqMdOUVafomKd4z1BePkzoxJWbYILny9a2Zk43VQ=="], "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], @@ -1749,7 +1614,7 @@ "@headless-tree/react": ["@headless-tree/react@1.6.3", "", { "peerDependencies": { "@headless-tree/core": "*", "react": "*", "react-dom": "*" } }, "sha512-aiRwG6e2EPBSec9uLLy9GlTvAuCtSTouU30Nwcr5ZTsYjG/i7B/ouC8f8Zu4unzo/v1h5ztbemp+EH2TPTKh+g=="], - "@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="], + "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], "@hono/node-ws": ["@hono/node-ws@1.3.0", "", { "dependencies": { "ws": "^8.17.0" }, "peerDependencies": { "@hono/node-server": "^1.19.2", "hono": "^4.6.0" } }, "sha512-ju25YbbvLuXdqBCmLZLqnNYu1nbHIQjoyUqA8ApZOeL1k4skuiTcw5SW77/5SUYo2Xi2NVBJoVlfQurnKEp03Q=="], @@ -1761,8 +1626,6 @@ "@huggingface/tasks": ["@huggingface/tasks@0.19.90", "", {}, "sha512-nfV9luJbvwGQ/5oKXkKhCV9h4X7mwh1YaGG3ORd6UMLDSwr1OFSSatcBX0O9OtBtmNK19aGSjbLFqqgcIR6+IA=="], - "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], - "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="], @@ -1825,7 +1688,7 @@ "@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="], - "@istanbuljs/schema": ["@istanbuljs/schema@0.1.6", "", {}, "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw=="], + "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="], "@jest/create-cache-key-function": ["@jest/create-cache-key-function@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3" } }, "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA=="], @@ -1861,7 +1724,7 @@ "@langchain/openai": ["@langchain/openai@0.4.9", "", { "dependencies": { "js-tiktoken": "^1.0.12", "openai": "^4.87.3", "zod": "^3.22.4", "zod-to-json-schema": "^3.22.3" }, "peerDependencies": { "@langchain/core": ">=0.3.39 <0.4.0" } }, "sha512-NAsaionRHNdqaMjVLPkFCyjUDze+OqRHghA1Cn4fPoAafz+FXcl9c7LlEl9Xo0FH6/8yiCl7Rw2t780C/SBVxQ=="], - "@lezer/common": ["@lezer/common@1.5.2", "", {}, "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ=="], + "@lezer/common": ["@lezer/common@1.5.1", "", {}, "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw=="], "@lezer/cpp": ["@lezer/cpp@1.1.5", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw=="], @@ -1879,7 +1742,7 @@ "@lezer/json": ["@lezer/json@1.0.3", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ=="], - "@lezer/lr": ["@lezer/lr@1.4.9", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-mF6irshW4nRJEhdR0HOAxxTDGss+rQFqA0nLRlZsPh14q+DB9Fqp0YbOvyRSOeKPLfUL/w5wPQAcETvkQ1VApg=="], + "@lezer/lr": ["@lezer/lr@1.4.8", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA=="], "@lezer/markdown": ["@lezer/markdown@1.6.3", "", { "dependencies": { "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0" } }, "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw=="], @@ -1959,11 +1822,11 @@ "@mediapipe/tasks-vision": ["@mediapipe/tasks-vision@0.10.17", "", {}, "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg=="], - "@mermaid-js/parser": ["@mermaid-js/parser@1.1.0", "", { "dependencies": { "langium": "^4.0.0" } }, "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw=="], + "@mermaid-js/parser": ["@mermaid-js/parser@1.0.1", "", { "dependencies": { "langium": "^4.0.0" } }, "sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ=="], "@microsoft/fetch-event-source": ["@microsoft/fetch-event-source@2.0.1", "", {}, "sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA=="], - "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.28.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-gmloF+i+flI8ouQK7MWW4mOwuMh4RePBuPFAEPC6+pdqyWOUMDOixb6qZ69owLJpz6XmyllCouc4t8YWO+E2Nw=="], "@monogrid/gainmap-js": ["@monogrid/gainmap-js@3.4.0", "", { "dependencies": { "promise-worker-transferable": "^1.0.4" }, "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg=="], @@ -1971,29 +1834,27 @@ "@neondatabase/serverless": ["@neondatabase/serverless@1.0.2", "", { "dependencies": { "@types/node": "^22.15.30", "@types/pg": "^8.8.0" } }, "sha512-I5sbpSIAHiB+b6UttofhrN/UJXII+4tZPAq1qugzwCwLIL8EZLV7F/JyHUrEIiGgQpEXzpnjlJ+zwcEhheGvCw=="], - "@next/env": ["@next/env@16.2.4", "", {}, "sha512-dKkkOzOSwFYe5RX6y26fZgkSpVAlIOJKQHIiydQcrWH6y/97+RceSOAdjZ14Qa3zLduVUy0TXcn+EiM6t4rPgw=="], - - "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OXTFFox5EKN1Ym08vfrz+OXxmCcEjT4SFMbNRsWZE99dMqt2Kcusl5MqPXcW232RYkMLQTy0hqgAMEsfEd/l2A=="], + "@next/env": ["@next/env@16.2.1", "", {}, "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg=="], - "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-XhpVnUfmYWvD3YrXu55XdcAkQtOnvaI6wtQa8fuF5fGoKoxIUZ0kWPtcOfqJEWngFF/lOS9l3+O9CcownhiQxQ=="], + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BwZ8w8YTaSEr2HIuXLMLxIdElNMPvY9fLqb20LX9A9OMGtJilhHLbCL3ggyd0TwjmMcTxi0XXt+ur1vWUoxj2Q=="], - "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Mx/tjlNA3G8kg14QvuGAJ4xBwPk1tUHq56JxZ8CXnZwz1Etz714soCEzGQQzVMz4bEnGPowzkV6Xrp6wAkEWOQ=="], + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/vrcE6iQSJq3uL3VGVHiXeaKbn8Es10DGTGRJnRZlkNQQk3kaNtAJg8Y6xuAlrx/6INKVjkfi5rY0iEXorZ6uA=="], - "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-iVMMp14514u7Nup2umQS03nT/bN9HurK8ufylC3FZNykrwjtx7V1A7+4kvhbDSCeonTVqV3Txnv0Lu+m2oDXNg=="], + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-uLn+0BK+C31LTVbQ/QU+UaVrV0rRSJQ8RfniQAHPghDdgE+SlroYqcmFnO5iNjNfVWCyKZHYrs3Nl0mUzWxbBw=="], - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-EZOvm1aQWgnI/N/xcWOlnS3RQBk0VtVav5Zo7n4p0A7UKyTDx047k8opDbXgBpHl4CulRqRfbw3QrX2w5UOXMQ=="], + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ=="], - "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-h9FxsngCm9cTBf71AR4fGznDEDx1hS7+kSEiIRjq5kO1oXWm07DxVGZjCvk0SGx7TSjlUqhI8oOyz7NfwAdPoA=="], + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg=="], - "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-3NdJV5OXMSOeJYijX+bjaLge3mJBlh4ybydbT4GFoB/2hAojWHtMhl3CYlYoMrjPuodp0nzFVi4Tj2+WaMg+Ow=="], + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg=="], - "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-kMVGgsqhO5YTYODD9IPGGhA6iprWidQckK3LmPeW08PIFENRmgfb4MjXHO+p//d+ts2rpjvK5gXWzXSMrPl9cw=="], + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA=="], - "@noble/ciphers": ["@noble/ciphers@2.2.0", "", {}, "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA=="], + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-qvU+3a39Hay+ieIztkGSbF7+mccbbg1Tk25hc4JDylf8IHjYmY/Zm64Qq1602yPyQqvie+vf5T/uPwNxDNIoeg=="], - "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], + "@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="], - "@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="], + "@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -2055,63 +1916,63 @@ "@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="], - "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA=="], + "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.213.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-zRM5/Qj6G84Ej3F1yt33xBVY/3tnMxtL1fiDIxYbDWYaZ/eudVw3/PBiZ8G7JwUxXxjW8gU4g6LnOyfGKYHYgw=="], - "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.7.0", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MWXggArM+Y11mPS8VOrqxOj+YMGQSRuvhM91eSBX4xFpJa05mpkeVvM8pPux5ElkEjV5RMgrkisrlP/R83SpBQ=="], + "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.6.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ=="], - "@opentelemetry/core": ["@opentelemetry/core@2.7.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-DT12SXVwV2eoJrGf4nnsvZojxxeQo+LlNAsoYGRRObPWTeN6APiqZ2+nqDCQDvQX40eLi1AePONS0onoASp3yQ=="], + "@opentelemetry/core": ["@opentelemetry/core@2.6.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="], - "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w=="], + "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.213.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.213.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-3i9NdkET/KvQomeh7UaR/F4r9P25Rx6ooALlWXPIjypcEOUxksCmVu0zA70NBJWlrMW1rPr/LRidFAflLI+s/w=="], - "@opentelemetry/instrumentation-amqplib": ["@opentelemetry/instrumentation-amqplib@0.61.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-mCKoyTGfRNisge4br0NpOFSy2Z1NnEW8hbCJdUDdJFHrPqVzc4IIBPA/vX0U+LUcQqrQvJX+HMIU0dbDRe0i0Q=="], + "@opentelemetry/instrumentation-amqplib": ["@opentelemetry/instrumentation-amqplib@0.60.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-q/B2IvoVXRm1M00MvhnzpMN6rKYOszPXVsALi6u0ss4AYHe+TidZEtLW9N1ZhrobI1dSriHnBqqtAOZVAv07sg=="], - "@opentelemetry/instrumentation-connect": ["@opentelemetry/instrumentation-connect@0.57.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.38" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FMEBChnI4FLN5TE9DHwfH7QpNir1JzXno1uz/TAucVdLCyrG0jTrKIcNHt/i30A0M2AunNBCkcd8Ei26dIPKdg=="], + "@opentelemetry/instrumentation-connect": ["@opentelemetry/instrumentation-connect@0.56.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.38" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-PKp+sSZ7AfzMvGgO3VCyo1inwNu+q7A1k9X88WK4PQ+S6Hp7eFk8pie+sWHDTaARovmqq5V2osav3lQej2B0nw=="], - "@opentelemetry/instrumentation-dataloader": ["@opentelemetry/instrumentation-dataloader@0.31.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-f654tZFQXS5YeLDNb9KySrwtg7SnqZN119FauD7acBoTzuLduaiGTNz88ixcVSOOMGZ+EjJu/RFtx5klObC95g=="], + "@opentelemetry/instrumentation-dataloader": ["@opentelemetry/instrumentation-dataloader@0.30.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MXHP2Q38cd2OhzEBKAIXUi9uBlPEYzF6BNJbyjUXBQ6kLaf93kRC41vNMIz0Nl5mnuwK7fDvKT+/lpx7BXRwdg=="], - "@opentelemetry/instrumentation-express": ["@opentelemetry/instrumentation-express@0.62.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Tvx+vgAZKEQxU3Rx+xWLiR0mLxHwmk69/8ya04+VsV9WYh8w6Lhx5hm5yAMvo1wy0KqWgFKBLwSeo3sHCwdOww=="], + "@opentelemetry/instrumentation-express": ["@opentelemetry/instrumentation-express@0.61.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Xdmqo9RZuZlL29Flg8QdwrrX7eW1CZ7wFQPKHyXljNymgKhN1MCsYuqQ/7uxavhSKwAl7WxkTzKhnqpUApLMvQ=="], - "@opentelemetry/instrumentation-fs": ["@opentelemetry/instrumentation-fs@0.33.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-sCZWXGalQ01wr3tAhSR9ucqFJ0phidpAle6/17HVjD6gN8FLmZMK/8sKxdXYHy3PbnlV1P4zeiSVFNKpbFMNLA=="], + "@opentelemetry/instrumentation-fs": ["@opentelemetry/instrumentation-fs@0.32.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-koR6apx0g0wX6RRiPpjA4AFQUQUbXrK16kq4/SZjVp7u5cffJhNkY4TnITxcGA4acGSPYAfx3NHRIv4Khn1axQ=="], - "@opentelemetry/instrumentation-generic-pool": ["@opentelemetry/instrumentation-generic-pool@0.57.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-orhmlaK+ZIW9hKU+nHTbXrCSXZcH83AescTqmpamHRobRmYSQwRbD0a1odc0yAzuzOtxYiHiXAnpnIpaSSY7Ow=="], + "@opentelemetry/instrumentation-generic-pool": ["@opentelemetry/instrumentation-generic-pool@0.56.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-fg+Jffs6fqrf0uQS0hom7qBFKsbtpBiBl8+Vkc63Gx8xh6pVh+FhagmiO6oM0m3vyb683t1lP7yGYq22SiDnqg=="], - "@opentelemetry/instrumentation-graphql": ["@opentelemetry/instrumentation-graphql@0.62.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-3YNuLVPUxafXkH1jBAbGsKNsP3XVzcFDhCDCE3OqBwCwShlqQbLMRMFh1T/d5jaVZiGVmSsfof+ICKD2iOV8xg=="], + "@opentelemetry/instrumentation-graphql": ["@opentelemetry/instrumentation-graphql@0.61.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pUiVASv6nh2XrerTvlbVHh7vKFzscpgwiQ/xvnZuAIzQ5lRjWVdRPUuXbvZJ/Yq79QsE81TZdJ7z9YsXiss1ew=="], - "@opentelemetry/instrumentation-hapi": ["@opentelemetry/instrumentation-hapi@0.60.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-aNljZKYrEa7obLAxd1bCEDxF7kzCLGXTuTJZ8lMR9rIVEjmuKBXN1gfqpm/OB//Zc2zP4iIve1jBp7sr3mQV6w=="], + "@opentelemetry/instrumentation-hapi": ["@opentelemetry/instrumentation-hapi@0.59.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-33wa4mEr+9+ztwdgLor1SeBu4Opz4IsmpcLETXAd3VmBrOjez8uQtrsOhPCa5Vhbm5gzDlMYTgFRLQzf8/YHFA=="], - "@opentelemetry/instrumentation-http": ["@opentelemetry/instrumentation-http@0.214.0", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/instrumentation": "0.214.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FlkDhZDRjDJDcO2LcSCtjRpkal1NJ8y0fBqBhTvfAR3JSYY2jAIj1kSS5IjmEBt4c3aWv+u/lqLuoCDrrKCSKg=="], + "@opentelemetry/instrumentation-http": ["@opentelemetry/instrumentation-http@0.213.0", "", { "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/instrumentation": "0.213.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-B978Xsm5XEPGhm1P07grDoaOFLHapJPkOG9h016cJsyWWxmiLnPu2M/4Nrm7UCkHSiLnkXgC+zVGUAIahy8EEA=="], - "@opentelemetry/instrumentation-ioredis": ["@opentelemetry/instrumentation-ioredis@0.62.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZYt//zcPve8qklaZX+5Z4MkU7UpEkFRrxsf2cnaKYBitqDnsCN69CPAuuMOX6NYdW2rG9sFy7V/QWtBlP5XiNQ=="], + "@opentelemetry/instrumentation-ioredis": ["@opentelemetry/instrumentation-ioredis@0.61.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-hsHDadUtAFbws1YSDc1XW0svGFKiUbqv2td1Cby+UAiwvojm1NyBo/taifH0t8CuFZ0x/2SDm0iuTwrM5pnVOg=="], - "@opentelemetry/instrumentation-kafkajs": ["@opentelemetry/instrumentation-kafkajs@0.23.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.30.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-4K+nVo+zI+aDz0Z85SObwbdixIbzS9moIuKJaYsdlzcHYnKOPtB7ya8r8Ezivy/GVIBHiKJVq4tv+BEkgOMLaQ=="], + "@opentelemetry/instrumentation-kafkajs": ["@opentelemetry/instrumentation-kafkajs@0.22.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.30.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-wJU4IBQMUikdJAcTChLFqK5lo+flo7pahqd8DSLv7uMxsdOdAHj6RzKYAm8pPfUS6ItKYutYyuicwKaFwQKsoA=="], - "@opentelemetry/instrumentation-knex": ["@opentelemetry/instrumentation-knex@0.58.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Hc/o8fSsaWxZ8r1Yw4rNDLwTpUopTf4X32y4W6UhlHmW8Wizz8wfhgOKIelSeqFVTKBBPIDUOsQWuIMxBmu8Bw=="], + "@opentelemetry/instrumentation-knex": ["@opentelemetry/instrumentation-knex@0.57.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-vMCSh8kolEm5rRsc+FZeTZymWmIJwc40hjIKnXH4O0Dv/gAkJJIRXCsPX5cPbe0c0j/34+PsENd0HqKruwhVYw=="], - "@opentelemetry/instrumentation-koa": ["@opentelemetry/instrumentation-koa@0.62.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.36.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-uVip0VuGUQXZ+vFxkKxAUNq8qNl+VFlyHDh/U6IQ8COOEDfbEchdaHnpFrMYF3psZRUuoSIgb7xOeXj00RdwDA=="], + "@opentelemetry/instrumentation-koa": ["@opentelemetry/instrumentation-koa@0.61.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.36.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-lvrfWe9ShK/D2X4brmx8ZqqeWPfRl8xekU0FCn7C1dHm5k6+rTOOi36+4fnaHAP8lig9Ux6XQ1D4RNIpPCt1WQ=="], - "@opentelemetry/instrumentation-lru-memoizer": ["@opentelemetry/instrumentation-lru-memoizer@0.58.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-6grM3TdMyHzlGY1cUA+mwoPueB1F3dYKgKtZIH6jOFXqfHAByyLTc+6PFjGM9tKh52CFBJaDwodNlL/Td39z7Q=="], + "@opentelemetry/instrumentation-lru-memoizer": ["@opentelemetry/instrumentation-lru-memoizer@0.57.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-cEqpUocSKJfwDtLYTTJehRLWzkZ2eoePCxfVIgGkGkb83fMB71O+y4MvRHJPbeV2bdoWdOVrl8uO0+EynWhTEA=="], - "@opentelemetry/instrumentation-mongodb": ["@opentelemetry/instrumentation-mongodb@0.67.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-1WJp5N1lYfHq2IhECOTewFs5Tf2NfUOwQRqs/rZdXKTezArMlucxgzAaqcgp3A3YREXopXTpXHsxZTGHjNhMdQ=="], + "@opentelemetry/instrumentation-mongodb": ["@opentelemetry/instrumentation-mongodb@0.66.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-d7m9QnAY+4TCWI4q1QRkfrc6fo/92VwssaB1DzQfXNRvu51b78P+HJlWP7Qg6N6nkwdb9faMZNBCZJfftmszkw=="], - "@opentelemetry/instrumentation-mongoose": ["@opentelemetry/instrumentation-mongoose@0.60.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-8BahAZpKsOoc+lrZGb7Ofn4g3z8qtp5IxDfvAVpKXsEheQN7ONMH5djT5ihy6yf8yyeQJGS0gXFfpEAEeEHqQg=="], + "@opentelemetry/instrumentation-mongoose": ["@opentelemetry/instrumentation-mongoose@0.59.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-6/jWU+c1NgznkVLDU/2y0bXV2nJo3o9FWZ9mZ9nN6T/JBNRoMnVXZl2FdBmgH+a5MwaWLs5kmRJTP5oUVGIkPw=="], - "@opentelemetry/instrumentation-mysql": ["@opentelemetry/instrumentation-mysql@0.60.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/mysql": "2.15.27" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-08pO8GFPEIz2zquKDGteBZDNmwketdgH8hTe9rVYgW9kCJXq1Psj3wPQGx+VaX4ZJKCfPeoLMYup9+cxHvZyVQ=="], + "@opentelemetry/instrumentation-mysql": ["@opentelemetry/instrumentation-mysql@0.59.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/mysql": "2.15.27" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-r+V/Fh0sm7Ga8/zk/TI5H5FQRAjwr0RrpfPf8kNIehlsKf12XnvIaZi8ViZkpX0gyPEpLXqzqWD6QHlgObgzZw=="], - "@opentelemetry/instrumentation-mysql2": ["@opentelemetry/instrumentation-mysql2@0.60.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@opentelemetry/sql-common": "^0.41.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-m/5d3bxQALllCzezYDk/6vajh0tj5OijMMvOZGr+qN1NMXm1dzMNwyJ0gNZW7Fo3YFRyj/jJMxIw+W7d525dlw=="], + "@opentelemetry/instrumentation-mysql2": ["@opentelemetry/instrumentation-mysql2@0.59.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@opentelemetry/sql-common": "^0.41.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-n9/xrVCRBfG9egVbffnlU1uhr+HX0vF4GgtAB/Bvm48wpFgRidqD8msBMiym1kRYzmpWvJqTxNT47u1MkgBEdw=="], - "@opentelemetry/instrumentation-pg": ["@opentelemetry/instrumentation-pg@0.66.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.34.0", "@opentelemetry/sql-common": "^0.41.2", "@types/pg": "8.15.6", "@types/pg-pool": "2.0.7" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-KxfLGXBb7k2ueaPJfq2GXBDXBly8P+SpR/4Mj410hhNgmQF3sCqwXvUBQxZQkDAmsdBAoenM+yV1LhtsMRamcA=="], + "@opentelemetry/instrumentation-pg": ["@opentelemetry/instrumentation-pg@0.65.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.34.0", "@opentelemetry/sql-common": "^0.41.2", "@types/pg": "8.15.6", "@types/pg-pool": "2.0.7" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-W0zpHEIEuyZ8zvb3njaX9AAbHgPYOsSWVOoWmv1sjVRSF6ZpBqtlxBWbU+6hhq1TFWBeWJOXZ8nZS/PUFpLJYQ=="], - "@opentelemetry/instrumentation-redis": ["@opentelemetry/instrumentation-redis@0.62.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y3pPpot7WzR/8JtHcYlTYsyY8g+pbFhAqbwAuG5bLPnR6v6pt1rQc0DpH0OlGP/9CZbWBP+Zhwp9yFoygf/ZXQ=="], + "@opentelemetry/instrumentation-redis": ["@opentelemetry/instrumentation-redis@0.61.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-JnPexA034/0UJRsvH96B0erQoNOqKJZjE2ZRSw9hiTSC23LzE0nJE/u6D+xqOhgUhRnhhcPHq4MdYtmUdYTF+Q=="], - "@opentelemetry/instrumentation-tedious": ["@opentelemetry/instrumentation-tedious@0.33.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/tedious": "^4.0.14" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Q6WQwAD01MMTub31GlejoiFACYNw26J426wyjvU7by7fDIr2nZXNW4vhTGs7i7F0TnXBO3xN688g1tdUgYwJ5w=="], + "@opentelemetry/instrumentation-tedious": ["@opentelemetry/instrumentation-tedious@0.32.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/tedious": "^4.0.14" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-BQS6gG8RJ1foEqfEZ+wxoqlwfCAzb1ZVG0ad8Gfe4x8T658HJCLGLd4E4NaoQd8EvPfLqOXgzGaE/2U4ytDSWA=="], - "@opentelemetry/instrumentation-undici": ["@opentelemetry/instrumentation-undici@0.24.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/semantic-conventions": "^1.24.0" }, "peerDependencies": { "@opentelemetry/api": "^1.7.0" } }, "sha512-oKzZ3uvqP17sV0EsoQcJgjEfIp0kiZRbYu/eD8p13Cbahumf8lb/xpYeNr/hfAJ4owzEtIDcGIjprfLcYbIKBQ=="], + "@opentelemetry/instrumentation-undici": ["@opentelemetry/instrumentation-undici@0.23.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/semantic-conventions": "^1.24.0" }, "peerDependencies": { "@opentelemetry/api": "^1.7.0" } }, "sha512-LL0VySzKVR2cJSFVZaTYpZl1XTpBGnfzoQPe2W7McS2267ldsaEIqtQY6VXs2KCXN0poFjze5110PIpxHDaDGg=="], - "@opentelemetry/redis-common": ["@opentelemetry/redis-common@0.38.3", "", {}, "sha512-VCghU1JYs/4gP6Gqf/xro9MEsZ7LrMv2uONVsaESKL38ZOB9BqnI98FfS23wjMnHlpuE+TTaWSoAVNpTwYXzjw=="], + "@opentelemetry/redis-common": ["@opentelemetry/redis-common@0.38.2", "", {}, "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA=="], - "@opentelemetry/resources": ["@opentelemetry/resources@2.7.0", "", { "dependencies": { "@opentelemetry/core": "2.7.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-K+oi0hNMv94EpZbnW3eyu2X6SGVpD3O5DhG2NIp65Hc7lhAj9brRXTAVzh3wB82+q3ThakEf7Zd7RsFUqcTc7A=="], + "@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="], - "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.7.0", "", { "dependencies": { "@opentelemetry/core": "2.7.0", "@opentelemetry/resources": "2.7.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-Yg9zEXJB50DLVLpsKPk7NmNqlPlS+OvqhJGh0A8oawIOTPOwlm4eXs9BMJV7L79lvEwI+dWtAj+YjTyddV336A=="], + "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw=="], "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="], @@ -2165,7 +2026,7 @@ "@posthog/core": ["@posthog/core@1.9.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-j7KSWxJTUtNyKynLt/p0hfip/3I46dWU2dk+pt7dKRoz2l5CYueHuHK4EO7Wlgno5yo1HO4sc4s30MXMTICHJw=="], - "@prisma/instrumentation": ["@prisma/instrumentation@7.6.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.207.0" }, "peerDependencies": { "@opentelemetry/api": "^1.8" } }, "sha512-ZPW2gRiwpPzEfgeZgaekhqXrbW+Y2RJKHVqUmlhZhKzRNCcvR6DykzylDrynpArKKRQtLxoZy36fK7U0p3pdgQ=="], + "@prisma/instrumentation": ["@prisma/instrumentation@7.4.2", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.207.0" }, "peerDependencies": { "@opentelemetry/api": "^1.8" } }, "sha512-r9JfchJF1Ae6yAxcaLu/V1TGqBhAuSDe3mRNOssBfx1rMzfZ4fdNvrgUBwyb/TNTGXFxlH9AZix5P257x07nrg=="], "@promptbook/utils": ["@promptbook/utils@0.69.5", "", { "dependencies": { "spacetrim": "0.11.59" } }, "sha512-xm5Ti/Hp3o4xHrsK9Yy3MS6KbDxYbq485hDsFvxqaNA7equHLPdo8H8faTitTeb14QCDfLW4iwCxdVYu5sn6YQ=="], @@ -2383,18 +2244,16 @@ "@react-navigation/native": ["@react-navigation/native@7.2.2", "", { "dependencies": { "@react-navigation/core": "^7.17.2", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-kem1Ko2BcbAjmbQIv66dNmr6EtfDut3QU0qjsVhMnLLhktwyXb6FzZYp8gTrUb6AvkAbaJoi+BF5Pl55pAUa5w=="], - "@react-navigation/native-stack": ["@react-navigation/native-stack@7.14.11", "", { "dependencies": { "@react-navigation/elements": "^2.9.14", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.2.2", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-1ufBtJ7KbVFlQhXsYSYHqjgkmP30AzJSgW48YjWMQZ3NZGAyYe34w9Wd4KpdebQCfDClPe9maU+8crA/awa6lQ=="], + "@react-navigation/native-stack": ["@react-navigation/native-stack@7.14.10", "", { "dependencies": { "@react-navigation/elements": "^2.9.14", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.2.2", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-mCbYbYhi7Em2R2nEgwYGdLU38smy+KK+HMMVcwuzllWsF3Qb+jOUEYbB6Or7LvE7SS77BZ6sHdx4HptCEv50hQ=="], "@react-navigation/routers": ["@react-navigation/routers@7.5.3", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-1tJHg4KKRJuQ1/EvJxatrMef3NZXEPzwUIUZ3n1yJ2t7Q97siwRtbynRpQG9/69ebbtiZ8W3ScOZF/OmhvM4Rg=="], "@react-three/drei": ["@react-three/drei@10.7.7", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mediapipe/tasks-vision": "0.10.17", "@monogrid/gainmap-js": "^3.0.6", "@use-gesture/react": "^10.3.1", "camera-controls": "^3.1.0", "cross-env": "^7.0.3", "detect-gpu": "^5.0.56", "glsl-noise": "^0.0.0", "hls.js": "^1.5.17", "maath": "^0.10.8", "meshline": "^3.3.1", "stats-gl": "^2.2.8", "stats.js": "^0.17.0", "suspend-react": "^0.1.3", "three-mesh-bvh": "^0.8.3", "three-stdlib": "^2.35.6", "troika-three-text": "^0.52.4", "tunnel-rat": "^0.1.2", "use-sync-external-store": "^1.4.0", "utility-types": "^3.11.0", "zustand": "^5.0.1" }, "peerDependencies": { "@react-three/fiber": "^9.0.0", "react": "^19", "react-dom": "^19", "three": ">=0.159" }, "optionalPeers": ["react-dom"] }, "sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ=="], - "@react-three/fiber": ["@react-three/fiber@9.6.0", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-use-measure": "^2.1.7", "scheduler": "^0.27.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": ">=19 <19.3", "react-dom": ">=19 <19.3", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-90abYK2q5/qDM+GACs9zRvc5KhEEpEWqWlHSd64zTPNxg+9wCJvTfyD9x2so7hlQhjRYO1Fa6flR3BC/kpTFkA=="], + "@react-three/fiber": ["@react-three/fiber@9.5.0", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-use-measure": "^2.1.7", "scheduler": "^0.27.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": ">=19 <19.3", "react-dom": ">=19 <19.3", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA=="], "@remirror/core-constants": ["@remirror/core-constants@3.0.0", "", {}, "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg=="], - "@repeaterjs/repeater": ["@repeaterjs/repeater@3.0.6", "", {}, "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA=="], - "@replit/codemirror-css-color-picker": ["@replit/codemirror-css-color-picker@6.3.0", "", { "peerDependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-19biDANghUm7Fz7L1SNMIhK48tagaWuCOHj4oPPxc7hxPGkTVY2lU/jVZ8tsbTKQPVG7BO2CBDzs7CBwb20t4A=="], "@rn-primitives/accordion": ["@rn-primitives/accordion@1.4.0", "", { "dependencies": { "@radix-ui/react-accordion": "^1.2.12", "@rn-primitives/hooks": "1.4.0", "@rn-primitives/slot": "1.4.0", "@rn-primitives/types": "1.4.0" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native", "react-native-web"] }, "sha512-3oXnEILYiitkzGeZ2SM2Ux3aE+sy4/0Ug4AGO5Ac6ChqGdQS0yUKSEatlVNRb1/NhIyipacPS4hIYVv7bo7BJA=="], @@ -2457,73 +2316,73 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.1", "", { "os": "android", "cpu": "arm" }, "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.0", "", { "os": "android", "cpu": "arm" }, "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.1", "", { "os": "android", "cpu": "arm64" }, "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.0", "", { "os": "android", "cpu": "arm64" }, "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw=="], - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ=="], - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw=="], - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.0", "", { "os": "none", "cpu": "arm64" }, "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.0", "", { "os": "win32", "cpu": "x64" }, "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.0", "", { "os": "win32", "cpu": "x64" }, "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w=="], "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], - "@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.49.0", "", { "dependencies": { "@sentry/core": "10.49.0" } }, "sha512-n0QRx0Ysx6mPfIydTkz7VP0FmwM+/EqMZiRqdsU3aTYsngE9GmEDV0OL1bAy6a8N/C1xf9vntkuAtj6N/8Z51w=="], + "@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.46.0", "", { "dependencies": { "@sentry/core": "10.46.0" } }, "sha512-WB1gBT9G13V02ekZ6NpUhoI1aGHV2eNfjEPthkU2bGBvFpQKnstwzjg7waIRGR7cu+YSW2Q6UI6aQLgBeOPD1g=="], - "@sentry-internal/feedback": ["@sentry-internal/feedback@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" } }, "sha512-pdvMmi4dQpX5S/vAAzrhHPIw3T3HjUgDNgUiCBrlp7N9/6zGO2gNPhUnNekP+CjgI/z0rvf49RLqlDenpNrMOg=="], + "@sentry-internal/feedback": ["@sentry-internal/feedback@10.42.0", "", { "dependencies": { "@sentry/core": "10.42.0" } }, "sha512-lpPcHsog10MVYFTWE0Pf8vQRqQWwZHJpkVl2FEb9/HDdHFyTBUhCVoWo1KyKaG7GJl9AVKMAg7bp9SSNArhFNQ=="], - "@sentry-internal/replay": ["@sentry-internal/replay@10.47.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-ScdovxP7hJxgMt70+7hFvwT02GIaIUAxdEM/YPsayZBeCoAukPW8WiwztJfoKtsfPyKJ5A6f0H3PIxTPcA9Row=="], + "@sentry-internal/replay": ["@sentry-internal/replay@10.42.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.42.0", "@sentry/core": "10.42.0" } }, "sha512-Zh3EoaH39x2lqVY1YyVB2vJEyCIrT+YLUQxYl1yvP0MJgLxaR6akVjkgxbSUJahan4cX5DxpZiEHfzdlWnYPyQ=="], - "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.47.0", "", { "dependencies": { "@sentry-internal/replay": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-A5OY8friSe6g8WAK4L8IeOPiEd9D3Ps40DzRH5j2f6SUja0t90mKMvHRcRf8zq0d4BkdB+JM7tjOkwxpuv8heA=="], + "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.42.0", "", { "dependencies": { "@sentry-internal/replay": "10.42.0", "@sentry/core": "10.42.0" } }, "sha512-am3m1Fj8ihoPfoYo41Qq4KeCAAICn4bySso8Oepu9dMNe9Lcnsf+reMRS2qxTPg3pZDc4JEMOcLyNCcgnAfrHw=="], - "@sentry/babel-plugin-component-annotate": ["@sentry/babel-plugin-component-annotate@5.2.0", "", {}, "sha512-8LbOI5Kzb5F0+7LVQPi2+zGz1iPiRRFhM+7uZ/ZQ33L9BmDOYNIy3xWxCfMw2JCuMXXaxF47XCjGmR22/B0WPg=="], + "@sentry/babel-plugin-component-annotate": ["@sentry/babel-plugin-component-annotate@5.1.1", "", {}, "sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg=="], - "@sentry/browser": ["@sentry/browser@10.47.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.47.0", "@sentry-internal/feedback": "10.47.0", "@sentry-internal/replay": "10.47.0", "@sentry-internal/replay-canvas": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-rC0agZdxKA5XWfL4VwPOr/rJMogXDqZgnVzr93YWpFn9DMZT/7LzxSJVPIJwRUjx3bFEby3PcTa3YaX7pxm1AA=="], + "@sentry/browser": ["@sentry/browser@10.42.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.42.0", "@sentry-internal/feedback": "10.42.0", "@sentry-internal/replay": "10.42.0", "@sentry-internal/replay-canvas": "10.42.0", "@sentry/core": "10.42.0" } }, "sha512-iXxYjXNEBwY1MH4lDSDZZUNjzPJDK7/YLwVIJq/3iBYpIQVIhaJsoJnf3clx9+NfJ8QFKyKfcvgae61zm+hgTA=="], - "@sentry/bundler-plugin-core": ["@sentry/bundler-plugin-core@5.2.0", "", { "dependencies": { "@babel/core": "^7.18.5", "@sentry/babel-plugin-component-annotate": "5.2.0", "@sentry/cli": "^2.58.5", "dotenv": "^16.3.1", "find-up": "^5.0.0", "glob": "^13.0.6", "magic-string": "~0.30.8" } }, "sha512-+C0x4gEIJRgoMwyRFGx+TFiJ1Po2BZlT1v61+PnouiaprKL5qtZG8n5PXx/5LPLDsVjSIcXjnDrTz9aSm8SJ3w=="], + "@sentry/bundler-plugin-core": ["@sentry/bundler-plugin-core@5.1.1", "", { "dependencies": { "@babel/core": "^7.18.5", "@sentry/babel-plugin-component-annotate": "5.1.1", "@sentry/cli": "^2.58.5", "dotenv": "^16.3.1", "find-up": "^5.0.0", "glob": "^13.0.6", "magic-string": "~0.30.8" } }, "sha512-F+itpwR9DyQR7gEkrXd2tigREPTvtF5lC8qu6e4anxXYRTui1+dVR0fXNwjpyAZMhIesLfXRN7WY7ggdj7hi0Q=="], "@sentry/cli": ["@sentry/cli@2.58.5", "", { "dependencies": { "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.7", "progress": "^2.0.3", "proxy-from-env": "^1.1.0", "which": "^2.0.2" }, "optionalDependencies": { "@sentry/cli-darwin": "2.58.5", "@sentry/cli-linux-arm": "2.58.5", "@sentry/cli-linux-arm64": "2.58.5", "@sentry/cli-linux-i686": "2.58.5", "@sentry/cli-linux-x64": "2.58.5", "@sentry/cli-win32-arm64": "2.58.5", "@sentry/cli-win32-i686": "2.58.5", "@sentry/cli-win32-x64": "2.58.5" }, "bin": { "sentry-cli": "bin/sentry-cli" } }, "sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg=="], @@ -2543,25 +2402,25 @@ "@sentry/cli-win32-x64": ["@sentry/cli-win32-x64@2.58.5", "", { "os": "win32", "cpu": "x64" }, "sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg=="], - "@sentry/core": ["@sentry/core@10.49.0", "", {}, "sha512-UaFeum3LUM1mB0d67jvKnqId1yWQjyqmaDV6kWngG03x+jqXb08tJdGpSoxjXZe13jFBbiBL/wKDDYIK7rCK4g=="], + "@sentry/core": ["@sentry/core@10.46.0", "", {}, "sha512-N3fj4zqBQOhXliS1Ne9euqIKuciHCGOJfPGQLwBoW9DNz03jF+NB8+dUKtrJ79YLoftjVgf8nbgwtADK7NR+2Q=="], - "@sentry/electron": ["@sentry/electron@7.11.0", "", { "dependencies": { "@sentry/browser": "10.47.0", "@sentry/core": "10.47.0", "@sentry/node": "10.47.0" }, "peerDependencies": { "@sentry/node-native": "10.47.0" }, "optionalPeers": ["@sentry/node-native"] }, "sha512-AKz66R/o/tULOg23zJyQZU2RK2uyV7PRYEWxDeyGDIfJeg+tXN1Zwjf/WuPcpoVE3xsXcCGBReboqMLgff587Q=="], + "@sentry/electron": ["@sentry/electron@7.10.0", "", { "dependencies": { "@sentry/browser": "10.42.0", "@sentry/core": "10.42.0", "@sentry/node": "10.42.0" }, "peerDependencies": { "@sentry/node-native": "10.42.0" }, "optionalPeers": ["@sentry/node-native"] }, "sha512-RwifPIBQds31giWL5KF87R/owzcVamMcXkL2ctoe/ybsxV861cbNhXxba/XCI6YmYOGIaixqiCAasxeZ+mx1SA=="], - "@sentry/nextjs": ["@sentry/nextjs@10.49.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@rollup/plugin-commonjs": "28.0.1", "@sentry-internal/browser-utils": "10.49.0", "@sentry/bundler-plugin-core": "^5.2.0", "@sentry/core": "10.49.0", "@sentry/node": "10.49.0", "@sentry/opentelemetry": "10.49.0", "@sentry/react": "10.49.0", "@sentry/vercel-edge": "10.49.0", "@sentry/webpack-plugin": "^5.2.0", "rollup": "^4.35.0", "stacktrace-parser": "^0.1.11" }, "peerDependencies": { "next": "^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0" } }, "sha512-oVSbTbedZUfDFdgrkNpV9tclSAYF/bs+3rxKNH0KXte2dXj4nrvoinzA/3PTjbfjfgDYfInDHSPdlJv6Ev7lmA=="], + "@sentry/nextjs": ["@sentry/nextjs@10.46.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/semantic-conventions": "^1.40.0", "@rollup/plugin-commonjs": "28.0.1", "@sentry-internal/browser-utils": "10.46.0", "@sentry/bundler-plugin-core": "^5.1.0", "@sentry/core": "10.46.0", "@sentry/node": "10.46.0", "@sentry/opentelemetry": "10.46.0", "@sentry/react": "10.46.0", "@sentry/vercel-edge": "10.46.0", "@sentry/webpack-plugin": "^5.1.0", "rollup": "^4.35.0", "stacktrace-parser": "^0.1.11" }, "peerDependencies": { "next": "^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0" } }, "sha512-DVS6vHOhgFuvcos9OXrj1wcLi9iv859bmQ5lVLpbotAmPd63+kX82aQzATk1CBr3ygZrlA2lSYHDbpRzTAvIaA=="], - "@sentry/node": ["@sentry/node@10.49.0", "", { "dependencies": { "@fastify/otel": "0.18.0", "@opentelemetry/api": "^1.9.1", "@opentelemetry/core": "^2.6.1", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/instrumentation-amqplib": "0.61.0", "@opentelemetry/instrumentation-connect": "0.57.0", "@opentelemetry/instrumentation-dataloader": "0.31.0", "@opentelemetry/instrumentation-fs": "0.33.0", "@opentelemetry/instrumentation-generic-pool": "0.57.0", "@opentelemetry/instrumentation-graphql": "0.62.0", "@opentelemetry/instrumentation-hapi": "0.60.0", "@opentelemetry/instrumentation-http": "0.214.0", "@opentelemetry/instrumentation-ioredis": "0.62.0", "@opentelemetry/instrumentation-kafkajs": "0.23.0", "@opentelemetry/instrumentation-knex": "0.58.0", "@opentelemetry/instrumentation-koa": "0.62.0", "@opentelemetry/instrumentation-lru-memoizer": "0.58.0", "@opentelemetry/instrumentation-mongodb": "0.67.0", "@opentelemetry/instrumentation-mongoose": "0.60.0", "@opentelemetry/instrumentation-mysql": "0.60.0", "@opentelemetry/instrumentation-mysql2": "0.60.0", "@opentelemetry/instrumentation-pg": "0.66.0", "@opentelemetry/instrumentation-redis": "0.62.0", "@opentelemetry/instrumentation-tedious": "0.33.0", "@opentelemetry/instrumentation-undici": "0.24.0", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@prisma/instrumentation": "7.6.0", "@sentry/core": "10.49.0", "@sentry/node-core": "10.49.0", "@sentry/opentelemetry": "10.49.0", "import-in-the-middle": "^3.0.0" } }, "sha512-xr+HXABCiO5mgAJRQxsXRdNOLO0+Ee6CvXAAIqovL2A1GlhxNWc5ooPWeIrrLDJ/KGyT8zI91O5scpVXdXs0uQ=="], + "@sentry/node": ["@sentry/node@10.46.0", "", { "dependencies": { "@fastify/otel": "0.17.1", "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^2.6.0", "@opentelemetry/core": "^2.6.0", "@opentelemetry/instrumentation": "^0.213.0", "@opentelemetry/instrumentation-amqplib": "0.60.0", "@opentelemetry/instrumentation-connect": "0.56.0", "@opentelemetry/instrumentation-dataloader": "0.30.0", "@opentelemetry/instrumentation-express": "0.61.0", "@opentelemetry/instrumentation-fs": "0.32.0", "@opentelemetry/instrumentation-generic-pool": "0.56.0", "@opentelemetry/instrumentation-graphql": "0.61.0", "@opentelemetry/instrumentation-hapi": "0.59.0", "@opentelemetry/instrumentation-http": "0.213.0", "@opentelemetry/instrumentation-ioredis": "0.61.0", "@opentelemetry/instrumentation-kafkajs": "0.22.0", "@opentelemetry/instrumentation-knex": "0.57.0", "@opentelemetry/instrumentation-koa": "0.61.0", "@opentelemetry/instrumentation-lru-memoizer": "0.57.0", "@opentelemetry/instrumentation-mongodb": "0.66.0", "@opentelemetry/instrumentation-mongoose": "0.59.0", "@opentelemetry/instrumentation-mysql": "0.59.0", "@opentelemetry/instrumentation-mysql2": "0.59.0", "@opentelemetry/instrumentation-pg": "0.65.0", "@opentelemetry/instrumentation-redis": "0.61.0", "@opentelemetry/instrumentation-tedious": "0.32.0", "@opentelemetry/instrumentation-undici": "0.23.0", "@opentelemetry/resources": "^2.6.0", "@opentelemetry/sdk-trace-base": "^2.6.0", "@opentelemetry/semantic-conventions": "^1.40.0", "@prisma/instrumentation": "7.4.2", "@sentry/core": "10.46.0", "@sentry/node-core": "10.46.0", "@sentry/opentelemetry": "10.46.0", "import-in-the-middle": "^3.0.0" } }, "sha512-vF+7FrUXEtmYWuVcnvBjlWKeyLw/kwHpwnGj9oUmO/a2uKjDmUr53ZVcapggNxCjivavGYr9uHOY64AGdeUyzA=="], - "@sentry/node-core": ["@sentry/node-core@10.49.0", "", { "dependencies": { "@sentry/core": "10.49.0", "@sentry/opentelemetry": "10.49.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/core", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/instrumentation", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-7WO0KuCDPSq3G54TVUSI1CKFJwB67LasG+n/gDMBqbrarzs/Yh/s34OOMU5gfVQpncxQAmQsy4nEboQms8iNqA=="], + "@sentry/node-core": ["@sentry/node-core@10.46.0", "", { "dependencies": { "@sentry/core": "10.46.0", "@sentry/opentelemetry": "10.46.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/resources": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/context-async-hooks", "@opentelemetry/core", "@opentelemetry/instrumentation", "@opentelemetry/resources", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-gwLGXfkzmiCmUI1VWttyoZBaVp1ItpDKc8AV2mQblWPQGdLSD0c6uKV/FkU291yZA3rXsrLXVwcWoibwnjE2vw=="], - "@sentry/opentelemetry": ["@sentry/opentelemetry@10.49.0", "", { "dependencies": { "@sentry/core": "10.49.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-XNLm4dXmtegXQf+EEE2Cs84Ymlo/f5wMx+lg2S2XS4qLbXaPN/HttjhwKftd8D+8iUNfmH+xNMCSshx4s1B/1w=="], + "@sentry/opentelemetry": ["@sentry/opentelemetry@10.46.0", "", { "dependencies": { "@sentry/core": "10.46.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-dzzV2ovruGsx9jzusGGr6cNPvMgYRu2BIrF8aMZ3rkQ1OpPJjPStqtA1l1fw0aoxHOxIjFU7ml4emF+xdmMl3g=="], - "@sentry/react": ["@sentry/react@10.49.0", "", { "dependencies": { "@sentry/browser": "10.49.0", "@sentry/core": "10.49.0" }, "peerDependencies": { "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, "sha512-WdfJve0orTiumr25Ozgs2p2KaJR9xV82Z5V9IYBi0TadsurSWK6xI6SAFjw84tQht9Fp8q4UCn3QYCnApF4BfA=="], + "@sentry/react": ["@sentry/react@10.46.0", "", { "dependencies": { "@sentry/browser": "10.46.0", "@sentry/core": "10.46.0" }, "peerDependencies": { "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, "sha512-Rb1S+9OuUPVwsz7GWnQ6Kgf3azbsseUymIegg3JZHNcW/fM1nPpaljzTBnuineia113DH0pgMBcdrrZDLaosFQ=="], - "@sentry/vercel-edge": ["@sentry/vercel-edge@10.49.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/resources": "^2.6.1", "@sentry/core": "10.49.0" } }, "sha512-CL2Ggl5jFc5q3+tLhapRJMR7Ya9l/OxvnK55OG/FAwvhjfODz4V/Hf5bdOqU9LrsXXg4gWKqag/v5CBDDun8jg=="], + "@sentry/vercel-edge": ["@sentry/vercel-edge@10.46.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/resources": "^2.6.0", "@sentry/core": "10.46.0" } }, "sha512-A50gQM5ZoEwR6V3sKbq4S0RxGeKllpWTZfN+vemXh+XGi+F5U3QpEQufJgd+xHP7cxxbc1BiJIYuLmIjGbxjQA=="], "@sentry/vite-plugin": ["@sentry/vite-plugin@4.9.1", "", { "dependencies": { "@sentry/bundler-plugin-core": "4.9.1", "unplugin": "1.0.1" } }, "sha512-Tlyg2cyFYp/icX58GWvfpvZr9NLdLs2/xyFVyS8pQ0faZWmoXic3FMzoXYHV1gsdMbL1Yy5WQvGJy8j1rS8LGA=="], - "@sentry/webpack-plugin": ["@sentry/webpack-plugin@5.2.0", "", { "dependencies": { "@sentry/bundler-plugin-core": "5.2.0" }, "peerDependencies": { "webpack": ">=5.0.0" } }, "sha512-ssV/uJK3ixf8UHBrNdLBXcnprUwppJNilbFv+19I81KTH4gVwzKXsVTMO91j6lyAXtk2mORwmEFwxZqScFfc7g=="], + "@sentry/webpack-plugin": ["@sentry/webpack-plugin@5.1.1", "", { "dependencies": { "@sentry/bundler-plugin-core": "5.1.1", "uuid": "^9.0.0" }, "peerDependencies": { "webpack": ">=5.0.0" } }, "sha512-XgQg+t2aVrlQDfIiAEizqR/bsy6GtBygwgR+Kw11P/cYczj4W9PZ2IYqQEStBzHqnRTh5DbpyMcUNW2CujdA9A=="], "@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], @@ -2581,10 +2440,6 @@ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@simple-git/args-pathspec": ["@simple-git/args-pathspec@1.0.3", "", {}, "sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA=="], - - "@simple-git/argv-parser": ["@simple-git/argv-parser@1.1.1", "", { "dependencies": { "@simple-git/args-pathspec": "^1.0.3" } }, "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw=="], - "@sinclair/typebox": ["@sinclair/typebox@0.27.10", "", {}, "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA=="], "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], @@ -2603,13 +2458,13 @@ "@slack/types": ["@slack/types@2.20.1", "", {}, "sha512-eWX2mdt1ktpn8+40iiMc404uGrih+2fxiky3zBcPjtXKj6HLRdYlmhrPkJi7JTJm8dpXR6BWVWEDBXtaWMKD6A=="], - "@slack/web-api": ["@slack/web-api@7.15.1", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.20.1", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.15.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-y+TAF7TszcmFzbVtBkFqAdBwKSoD+8shkNxhp4WIfFwXmCKdFje9WD6evROApPa2FTy1v1uc9yBaJs3609PPgg=="], + "@slack/web-api": ["@slack/web-api@7.15.0", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.20.1", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.13.5", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-va7zYIt3QHG1x9M/jqXXRPFMoOVlVSSRHC5YH+DzKYsrz5xUKOA3lR4THsu/Zxha9N1jOndbKFKLtr0WOPW1Vw=="], - "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="], + "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.13", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.0", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-vYahwBAtRaAcFbOmE9aLr12z7RiHYDSLcnogSdxfm7kKfsNa3wH+NU5r7vTeB5rKvLsWyPjVX8iH94brP7umiQ=="], "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow=="], - "@smithy/types": ["@smithy/types@4.14.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg=="], + "@smithy/types": ["@smithy/types@4.14.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ=="], "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.2", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q=="], @@ -2629,8 +2484,6 @@ "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="], - "@streamdown/code": ["@streamdown/code@1.0.2", "", { "dependencies": { "shiki": "^3.19.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-QKLS3sC8no5y0YvhGLA+ZjtNhznWU09IvFcjRKgSA35ulckMLw3b5T1ha+o1DaW8BS8l0zceLPFZa3/X9+agWQ=="], - "@streamdown/mermaid": ["@streamdown/mermaid@1.0.2", "", { "dependencies": { "mermaid": "^11.12.2" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-Fr/4sBWnAeSnxM3PcrV/+DiZe5oPMq9gOkUIAH7ZauJeuwrZ/DVzD4g0zlav6AH0axh2m/sOfrfLtY5aLT7niw=="], "@superset/admin": ["@superset/admin@workspace:apps/admin"], @@ -2661,24 +2514,18 @@ "@superset/macos-process-metrics": ["@superset/macos-process-metrics@workspace:packages/macos-process-metrics"], - "@superset/macos-window-blur": ["@superset/macos-window-blur@workspace:packages/macos-window-blur"], - "@superset/marketing": ["@superset/marketing@workspace:apps/marketing"], "@superset/mcp": ["@superset/mcp@workspace:packages/mcp"], "@superset/mobile": ["@superset/mobile@workspace:apps/mobile"], - "@superset/open-link": ["@superset/open-link@workspace:apps/open-link"], - "@superset/panes": ["@superset/panes@workspace:packages/panes"], "@superset/relay": ["@superset/relay@workspace:apps/relay"], "@superset/shared": ["@superset/shared@workspace:packages/shared"], - "@superset/superset-browser-mcp": ["@superset/superset-browser-mcp@workspace:packages/superset-browser-mcp"], - "@superset/trpc": ["@superset/trpc@workspace:packages/trpc"], "@superset/typescript": ["@superset/typescript@workspace:tooling/typescript"], @@ -2745,31 +2592,31 @@ "@tanstack/pacer-lite": ["@tanstack/pacer-lite@0.2.1", "", {}, "sha512-3PouiFjR4B6x1c969/Pl4ZIJleof1M0n6fNX8NRiC9Sqv1g06CVDlEaXUR4212ycGFyfq4q+t8Gi37Xy+z34iQ=="], - "@tanstack/query-core": ["@tanstack/query-core@5.99.0", "", {}, "sha512-3Jv3WQG0BCcH7G+7lf/bP8QyBfJOXeY+T08Rin3GZ1bshvwlbPt7NrDHMEzGdKIOmOzvIQmxjk28YEQX60k7pQ=="], + "@tanstack/query-core": ["@tanstack/query-core@5.95.2", "", {}, "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ=="], - "@tanstack/query-devtools": ["@tanstack/query-devtools@5.99.0", "", {}, "sha512-m4ufXaJ8FjWXw7xDtyzE/6fkZAyQFg9WrbMrUpt8ZecRJx58jiFOZ2lxZMphZdIpAnIeto/S8stbwLKLusyckQ=="], + "@tanstack/query-devtools": ["@tanstack/query-devtools@5.95.2", "", {}, "sha512-QfaoqBn9uAZ+ICkA8brd1EHj+qBF6glCFgt94U8XP5BT6ppSsDBI8IJ00BU+cAGjQzp6wcKJL2EmRYvxy0TWIg=="], "@tanstack/react-db": ["@tanstack/react-db@0.1.83", "", { "dependencies": { "@tanstack/db": "0.6.5", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-LNV0C7OARazooT2hLTr5anXo6tbEyX2rHZQ0j9HZ/iNBI+Tx/y19o5Nd3ooyAYz5LEHJJxb8iM8ZTVB/diGnXw=="], - "@tanstack/react-query": ["@tanstack/react-query@5.99.0", "", { "dependencies": { "@tanstack/query-core": "5.99.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-OY2bCqPemT1LlqJ8Y2CUau4KELnIhhG9Ol3ZndPbdnB095pRbPo1cHuXTndg8iIwtoHTgwZjyaDnQ0xD0mYwAw=="], + "@tanstack/react-query": ["@tanstack/react-query@5.95.2", "", { "dependencies": { "@tanstack/query-core": "5.95.2" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA=="], - "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.99.0", "", { "dependencies": { "@tanstack/query-devtools": "5.99.0" }, "peerDependencies": { "@tanstack/react-query": "^5.99.0", "react": "^18 || ^19" } }, "sha512-CqqX7LCU9yOfCY/vBURSx2YSD83ryfX+QkfkaKionTfg1s2Hdm572Ro99gW3QPoJjzvsj1HM4pnN4nbDy3MXKA=="], + "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.95.2", "", { "dependencies": { "@tanstack/query-devtools": "5.95.2" }, "peerDependencies": { "@tanstack/react-query": "^5.95.2", "react": "^18 || ^19" } }, "sha512-AFQFmbznVkbtfpx8VJ2DylW17wWagQel/qLstVLkYmNRo2CmJt3SNej5hvl6EnEeljJIdC3BTB+W7HZtpsH+3g=="], - "@tanstack/react-router": ["@tanstack/react-router@1.168.22", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "1.168.15", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-W2LyfkfJtDCf//jOjZeUBWwOVl8iDRVTECpGHa2M28MT3T5/VVnjgicYNHR/ax0Filk1iU67MRjcjHheTYvK1Q=="], + "@tanstack/react-router": ["@tanstack/react-router@1.168.8", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "1.168.7", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-t0S0QueXubBKmI9eLPcN/A1sLQgTu8/yHerjrvvsGeD12zMdw0uJPKwEKpStQF2OThQtw64cs34uUSYXBUTSNw=="], "@tanstack/react-store": ["@tanstack/react-store@0.9.3", "", { "dependencies": { "@tanstack/store": "0.9.3", "use-sync-external-store": "^1.6.0" }, "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" } }, "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg=="], "@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="], - "@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.24", "", { "dependencies": { "@tanstack/virtual-core": "3.14.0" }, "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" } }, "sha512-aIJvz5OSkhNIhZIpYivrxrPTKYsjW9Uzy+sP/mx0S3sev2HyvPb7xmjbYvokzEpfgYHy/HjzJ2zFAETuUfgCpg=="], + "@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.23", "", { "dependencies": { "@tanstack/virtual-core": "3.13.23" }, "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" } }, "sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ=="], - "@tanstack/router-cli": ["@tanstack/router-cli@1.166.33", "", { "dependencies": { "@tanstack/router-generator": "1.166.32", "chokidar": "^3.6.0", "yargs": "^17.7.2" }, "bin": { "tsr": "bin/tsr.cjs" } }, "sha512-gCWBbCVkfT2OzgxQVV275BjRYKvfh7SEKD73ATHWyLE8ifm8/O2700roObVHUy+Y0jJT91Am0UkjsES0O2jqzw=="], + "@tanstack/router-cli": ["@tanstack/router-cli@1.166.23", "", { "dependencies": { "@tanstack/router-generator": "1.166.22", "chokidar": "^3.6.0", "yargs": "^17.7.2" }, "bin": { "tsr": "bin/tsr.cjs" } }, "sha512-vvp0LoH/nxWbkkYiDbmT0FD9spcjN85AOaENX9Pf9R9dfyCX9ihsoVrvlMAXJKCFJDGmd63RTjf1ZRVkrKMBnw=="], - "@tanstack/router-core": ["@tanstack/router-core@1.168.15", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^3.0.0", "seroval": "^1.5.0", "seroval-plugins": "^1.5.0" }, "bin": { "intent": "bin/intent.js" } }, "sha512-Wr0424NDtD8fT/uALobMZ9DdcfsTyXtW5IPR++7zvW8/7RaIOeaqXpVDId8ywaGtqPWLWOfaUg2zUtYtukoXYA=="], + "@tanstack/router-core": ["@tanstack/router-core@1.168.7", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-z4UEdlzMrFaKBsG4OIxlZEm+wsYBtEp//fnX6kW18jhQpETNcM6u2SXNdX+bcIYp6AaR7ERS3SBENzjC/xxwQQ=="], - "@tanstack/router-generator": ["@tanstack/router-generator@1.166.32", "", { "dependencies": { "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.15", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "magic-string": "^0.30.21", "prettier": "^3.5.0", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-VuusKwEXcgKq+myq1JQfZogY8scTXIIeFls50dJ/UXgCXWp5n14iFreYNlg41wURcak2oA3M+t2TVfD0xUUD6g=="], + "@tanstack/router-generator": ["@tanstack/router-generator@1.166.22", "", { "dependencies": { "@tanstack/router-core": "1.168.7", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-wQ7H8/Q2rmSPuaxWnurJ3DATNnqWV2tajxri9TSiW4QHsG7cWPD34+goeIinKG+GajJyEdfVpz6w/gRJXfbAPw=="], - "@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.22", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.15", "@tanstack/router-generator": "1.166.32", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.21", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0", "vite-plugin-solid": "^2.11.10 || ^3.0.0-0", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-wYPzIvBK8bcmXVUpZfSgGBXOrfBAdF4odKevz6rejio5rEd947NtKDF5R7eYdwlAOmRqYpLJnJ1QHkc5t8bY4w=="], + "@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.9", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.7", "@tanstack/router-generator": "1.166.22", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.8", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-h/VV05FEHd4PVyc5Zy8B3trWLcdLt/Pmp+mfifmBKGRw+MUtvdQKbBHhmy4ouOf67s5zDJMc+n8R3xgU7bDwFA=="], "@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="], @@ -2777,67 +2624,63 @@ "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="], - "@tanstack/virtual-core": ["@tanstack/virtual-core@3.14.0", "", {}, "sha512-JLANqGy/D6k4Ujmh8Tr25lGimuOXNiaVyXaCAZS0W+1390sADdGnyUdSWNIfd49gebtIxGMij4IktRVzrdr12Q=="], + "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.23", "", {}, "sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg=="], "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.161.7", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ=="], - "@taplo/core": ["@taplo/core@0.2.0", "", {}, "sha512-r8bl54Zj1In3QLkiW/ex694bVzpPJ9EhwqT9xkcUVODnVUGirdB1JTsmiIv0o1uwqZiwhi8xNnTOQBRQCpizrQ=="], - - "@taplo/lib": ["@taplo/lib@0.5.0", "", { "dependencies": { "@taplo/core": "^0.2.0" } }, "sha512-+xIqpQXJco3T+VGaTTwmhxLa51qpkQxCjRwezjFZgr+l21ExlywJFcDfTrNmL6lG6tqb0h8GyJKO3UPGPtSCWg=="], - "@tavily/core": ["@tavily/core@0.7.2", "", { "dependencies": { "axios": "^1.7.7", "https-proxy-agent": "^7.0.6", "js-tiktoken": "^1.0.14" } }, "sha512-N9xfw9miPD1jyVKYTMWV1hQvWPNjATT9Hffr6tv7VMHzwOPOeBwfX/R25ZE2F7meTyq6xSeGxclWnLVH2xHqFA=="], - "@tiptap/core": ["@tiptap/core@3.22.3", "", { "peerDependencies": { "@tiptap/pm": "^3.22.3" } }, "sha512-Dv9MKK5BDWCF0N2l6/Pxv3JNCce2kwuWf2cKMBc2bEetx0Pn6o7zlFmSxMvYK4UtG1Tw9Yg/ZHi6QOFWK0Zm9Q=="], + "@tiptap/core": ["@tiptap/core@3.21.0", "", { "peerDependencies": { "@tiptap/pm": "^3.21.0" } }, "sha512-IfnQiuEeabDSPr1C/zHFTbnvlTf5z0DE/d/xz4C6bkL4ZBDJ3rr99h2qsaV0l8F+kbNswZMlQdM8rxNlMy95fQ=="], - "@tiptap/extension-blockquote": ["@tiptap/extension-blockquote@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-IaUx3zh7yLHXzIXKL+fw/jzFhsIImdhJyw0lMhe8FfYrefFqXJFYW/sey6+L/e8B3AWvTksPA6VBwefzbH77JA=="], + "@tiptap/extension-blockquote": ["@tiptap/extension-blockquote@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-JDM/RR6rM0dMCZ1UnEf7eqmN6pAdIa2llhN+E24HdTGNJCklMFhLAGE/OT8/1r7M0WWA9GVO7/PTe4EdGh6+lQ=="], - "@tiptap/extension-bold": ["@tiptap/extension-bold@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-tysipHla2zCWr8XNIWRaW9O+7i7/SoEqnRqSRUUi2ailcJjlia+RBy3RykhkgyThrQDStu5KGBS/UvrXwA+O1A=="], + "@tiptap/extension-bold": ["@tiptap/extension-bold@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-iyEJRzG7XTCPlHwEDzUw3HnuYYCfL7lNpcCHmxcpYMrIUA8rv7EUxerIwApT6xY8hQ/07ljuJKgOyPvnJOOzuA=="], - "@tiptap/extension-bubble-menu": ["@tiptap/extension-bubble-menu@3.22.3", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-Y6zQjh0ypDg32HWgICEvmPSKjGLr39k3aDxxt/H0uQEZSfw4smT0hxUyyyjVjx68C6t6MTnwdfz0hPI5lL68vQ=="], + "@tiptap/extension-bubble-menu": ["@tiptap/extension-bubble-menu@3.21.0", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-/fabRRhhf8i4LAx9e8xz9ppqN5KgdJk3TxMuxAD5vAWGsejvhSoPa8O8H/QwwyntXm1Vue8aQiMHsUk48b2hGQ=="], - "@tiptap/extension-bullet-list": ["@tiptap/extension-bullet-list@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-xOmW/b1hgECIE6r3IeZvKn4VVlG3+dfTjCWE6lnnyLaqdNkNhKS1CwUmDZdYNLUS2ryIUtgz5ID1W/8A3PhbiA=="], + "@tiptap/extension-bullet-list": ["@tiptap/extension-bullet-list@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-PWNF+xwxgOeXYGD88sCQLKL0eBoQqjUnZNALxBjN3Y7x4llalh42rHOp2Nt2t6UbQgqTBtBzU/uFcussTpxreQ=="], - "@tiptap/extension-code": ["@tiptap/extension-code@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-wafWTDQOuMKtXpZEuk1PFQmzopabBciNLryL90MB9S03MNLaQQZYLnmYkDBlzAaLAbgF5QiC+2XZQEBQuTVjFQ=="], + "@tiptap/extension-code": ["@tiptap/extension-code@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-D7wA9jp+4X2r1f3FIoga73s6Rn4rmZY57Jes6a4rK3HY+3yHk1r057pPIZSY8Drfs97jxHQVFdfUYUomLSFYBA=="], - "@tiptap/extension-code-block": ["@tiptap/extension-code-block@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-RiQtEjDAPrHpdo6sw6b7fOw/PijqgFIsozKKkGcSeBgWHQuFg7q9OxJTj+l0e60rVwSu/5gmKEEobzM9bX+t2Q=="], + "@tiptap/extension-code-block": ["@tiptap/extension-code-block@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-zrVOcOzDCjHQ8NJcC+qHmZZKiwnP/NMSb3qVJlSMN8TzuHept1MZCDa2Mbo70O6I0txo456SGuXB9sqV1vHmGg=="], - "@tiptap/extension-code-block-lowlight": ["@tiptap/extension-code-block-lowlight@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/extension-code-block": "^3.22.3", "@tiptap/pm": "^3.22.3", "highlight.js": "^11", "lowlight": "^2 || ^3" } }, "sha512-NGFuD9zb1QfnCgD2zW4XaUEdQvd/ydm9FmXXh8eawx/+C8xt3p21DIKRERvxWrCvvVNzIUEpZRRYehPOJiD1eg=="], + "@tiptap/extension-code-block-lowlight": ["@tiptap/extension-code-block-lowlight@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/extension-code-block": "^3.21.0", "@tiptap/pm": "^3.21.0", "highlight.js": "^11", "lowlight": "^2 || ^3" } }, "sha512-79sS0tqoGVX6wq30ejzohpUVLeGOkTTUn5hCqjsniyYPTEtrn4tHyBnS4Du2TbrDV4SqcwgisWExhuB8pfEdYQ=="], - "@tiptap/extension-document": ["@tiptap/extension-document@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-MCSr1PFPtTd++lA3H1RNgqAczAE59XXJ5wUFIQf2F+/0DPY5q2SU4g5QsNJVxPPft5mrNT4C6ty8xBPrALFEdA=="], + "@tiptap/extension-document": ["@tiptap/extension-document@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-7oCyzXI9ChvJQUlr23AURdfVar4OIsrYUvqdhEwo3bjcI/Q/j0KJiXfuh6ZzL5eVaINSailH53sZaGg4THQtUg=="], - "@tiptap/extension-dropcursor": ["@tiptap/extension-dropcursor@3.22.3", "", { "peerDependencies": { "@tiptap/extensions": "^3.22.3" } }, "sha512-taXq9Tl5aybdFbptJtFRHX9LFJzbXphAbPp4/vutFyTrBu5meXDxuS+B9pEmE+Or0XcolTlW2nDZB0Tqnr18JQ=="], + "@tiptap/extension-dropcursor": ["@tiptap/extension-dropcursor@3.21.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.21.0" } }, "sha512-6fsDSVAM2iz7eElvT6iivMrGBGjIP/oPigVZ/SPm6f31phaYhz6TIOEgV/Lr2jaPIOgyK4U0cU4Yd4KUBCmhzQ=="], - "@tiptap/extension-floating-menu": ["@tiptap/extension-floating-menu@3.22.3", "", { "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-0f8b4KZ3XKai8GXWseIYJGdOfQr3evtFbBo3U08zy2aYzMMXWG0zEF7qe5/oiYp2aZ95edjjITnEceviTsZkIg=="], + "@tiptap/extension-floating-menu": ["@tiptap/extension-floating-menu@3.21.0", "", { "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-n2HzTB+I/5rAl8R/1sKMv92JiY1oDK1hroXizxEKYa6dskJcAMW0CfYyPcPOZWQQEe7qoeOvQISr2ooLAKW+Mw=="], - "@tiptap/extension-gapcursor": ["@tiptap/extension-gapcursor@3.22.3", "", { "peerDependencies": { "@tiptap/extensions": "^3.22.3" } }, "sha512-L/Px4UeQEVG/D9WIlcAOIej+4wyIBCMUSYicSR+hW68UsObe4rxVbUas1QgidQKm6DOhoT7U7D4KQHA/Gdg/7A=="], + "@tiptap/extension-gapcursor": ["@tiptap/extension-gapcursor@3.21.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.21.0" } }, "sha512-wGjgAoYBTvPAe9QYMI5px355XcNeMkaUrMY9IHbMqgqdmHcDxqooxM4H6sYVX2CRcHwXy4I8NQAoOhSYrQJDMg=="], - "@tiptap/extension-hard-break": ["@tiptap/extension-hard-break@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-J0v8I99y9tbvVmgKYKzKP/JYNsWaZYS7avn4rzLft2OhnyTfwt3OoY8DtpHmmi6apSUaCtoWHWta/TmoEfK1nQ=="], + "@tiptap/extension-hard-break": ["@tiptap/extension-hard-break@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-6JFVSAOQ1qhQHi9mVcdn2/XO8YIMgYV8zjarzNUzP6Sf2waeE5BLXjlg6rIH/945sY1J+FndTojLru6gQ07a5A=="], - "@tiptap/extension-heading": ["@tiptap/extension-heading@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-XBHuhiEV2EEhZHpOLcplLqAmBIhJciU3I6AtwmqeEqDC0P114uMEfAO7JGlbBZdCYotNer26PKnu44TBTeNtkw=="], + "@tiptap/extension-heading": ["@tiptap/extension-heading@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-ji6VJmoRnDzAHYflEYEZohMHRi77UGLW1o3ua7UhI32iJ9nuYssbPNuzEeE4SvENMQwZRszad5+a+dKAa+NC7g=="], - "@tiptap/extension-history": ["@tiptap/extension-history@3.22.3", "", { "peerDependencies": { "@tiptap/extensions": "^3.22.3" } }, "sha512-3kev2iP84YPjwUk8BaM28EQiVHbBmE0lkcIjh/6yvgRxRwblzRwyJuFcsVOY5ouBVxl9Rg1rcFFCAs8CFNFkUg=="], + "@tiptap/extension-history": ["@tiptap/extension-history@3.21.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.21.0" } }, "sha512-aYUxm0fLXGfn4XAsRq53lOX1cB+GRF8rScVuDHmQfEaJHNo09DSRtvgWnDHVdqIS8FvKkBcTO8eyPOBPMvkWiA=="], - "@tiptap/extension-horizontal-rule": ["@tiptap/extension-horizontal-rule@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-wI2bFzScs+KgWeBH/BtypcVKeYelCyqV0RG8nxsZMWtPrBhqixzNd0Oi3gEKtjSjKUqMQ/kjJAIRuESr5UzlHA=="], + "@tiptap/extension-horizontal-rule": ["@tiptap/extension-horizontal-rule@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-vNBnOfFEY62CoJPGo4nonRM7RiOvhII1vhoO+WFr1GxDqCAfmEFjToflt7JT1UJdo6lMVcD+aaaAgOiuSz5p6g=="], - "@tiptap/extension-image": ["@tiptap/extension-image@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-Qpp8c5LOQaNpHrzjqZtoxtIR+8sSqJ7k8v+8anmYw3nxjvt2kpfT28Vd7aWMX55ZS43LaxMx+MkZqbmgUmMP0w=="], + "@tiptap/extension-image": ["@tiptap/extension-image@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-W9786a2K4LSZJMPeRLmoDulJeXOsM0ueRV2MHjTol7ikPRauROB7GUbAz9DyPAJHA2AGUfpswnGAYPO3tz5CLg=="], - "@tiptap/extension-italic": ["@tiptap/extension-italic@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-LteA4cb4EGCiUtrK2JHvDF/Zg0/YqV4DUyHhAAho+oGEQDupZlsS6m0ia5wQcclkiTLzsoPrwcSNu6RDGQ16wQ=="], + "@tiptap/extension-italic": ["@tiptap/extension-italic@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-2I8oPvwyXhRn1k8lbDFIutzvhtLEjoO5mmQCNX4TnT4PdxxaSrK9+ihYg12VeqhUeO7dg1MKiFqws0HVBrwzWg=="], - "@tiptap/extension-link": ["@tiptap/extension-link@3.22.3", "", { "dependencies": { "linkifyjs": "^4.3.2" }, "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-S8/P2o9pv6B3kqLjH2TRWwSAximGbciNc6R8/QcN6HWLYxp0N0JoqN3rZHl9VWIBAGRWc4zkt80dhqrl2xmgfQ=="], + "@tiptap/extension-link": ["@tiptap/extension-link@3.21.0", "", { "dependencies": { "linkifyjs": "^4.3.2" }, "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-oMU7Yve1sbgBsaFAUc2R0GPf4d3ZPVJeMUFC6b6X9rJIvx/IhEUEn9toQcSBGfp02uWK9NdQyIFYFdWlVXH++w=="], - "@tiptap/extension-list": ["@tiptap/extension-list@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-rqvv/dtqwbX+8KnPv0eMYp6PnBcuhPMol5cv1GlS8Nq/Cxt68EWGUHBuTFesw+hdnRQLmKwzoO1DlRn7PhxYRQ=="], + "@tiptap/extension-list": ["@tiptap/extension-list@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-KeBlEtLrGce2d3dgL89hmwWEtREuzlW4XY5bYWpKNvCbFqvdSb3n7vkdkw32YclZmMWxAcABgW6ucCStkE0rsQ=="], - "@tiptap/extension-list-item": ["@tiptap/extension-list-item@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-80CNf4oO5y8+LdckT4CyMe1t01EyhpRrQC9H45JW20P7559Nrchp5my3vvMtIAJbpTPPZtcB7LwdzWGKsG5drg=="], + "@tiptap/extension-list-item": ["@tiptap/extension-list-item@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-1ZymZmlQVbAoC4q5x3cro0v5+3I6l+BHqbhIMQLjQFlAOJfcE0pvqRzAFW7PduxUj41tXEtsYqp2NREvO9F5Fg=="], - "@tiptap/extension-list-keymap": ["@tiptap/extension-list-keymap@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-pKuyj5llu35zd/s2u/H9aydKZjmPRAIK5P1q/YXULhhCNln2RnmuRfQ5NklAqTD3yGciQ2lxDwwf7J6iw3ergA=="], + "@tiptap/extension-list-keymap": ["@tiptap/extension-list-keymap@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-EzrfW3ASNFPWKhR8sNOq7Kqw4hvaTAOn4dlI7chB8HIANSrlyPOUn+eKAnO6HQgsUgsbjg2GbTUrGrxcoLykUg=="], - "@tiptap/extension-ordered-list": ["@tiptap/extension-ordered-list@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-orAghtmd+K4Euu4BgI1hG+iZDXBYOyl5YTwiLBc2mQn+pqtZ9LqaH2us4ETwEwNP3/IWXGSAimUZ19nuL+eM2w=="], + "@tiptap/extension-ordered-list": ["@tiptap/extension-ordered-list@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-+d+0orokMfqaBfvr9tUBgGvo2ZCV+fR3JzsJTmnLBWOkhBSJN7H4pnfXPTue0qwspUwRmkLJxdIlU+J7HkMrng=="], - "@tiptap/extension-paragraph": ["@tiptap/extension-paragraph@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-oO7rhfyhEuwm+50s9K3GZPjYyEEEvFAvm1wXopvZnhbkBLydIWImBfrZoC5IQh4/sRDlTIjosV2C+ji5y0tUSg=="], + "@tiptap/extension-paragraph": ["@tiptap/extension-paragraph@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-cMPG/jCoZ9NmLZ5ctFziILaxJGfDtMTb5OLBhifMFZeMVwF1pEJIygDEfnX/HSruv507weZSQG4pERO2tRszMg=="], - "@tiptap/extension-placeholder": ["@tiptap/extension-placeholder@3.22.3", "", { "peerDependencies": { "@tiptap/extensions": "^3.22.3" } }, "sha512-7vbtlDVO00odqCnsMSmA4b6wjL5PFdfExFsdsDO0K0VemqHZ/doIRx/tosNUD1VYSOyKQd8U7efUjkFyVoIPlg=="], + "@tiptap/extension-placeholder": ["@tiptap/extension-placeholder@3.21.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.21.0" } }, "sha512-fs+cQqMh1d1naV6OgOhP/0qbRJwtw8DpQMj3/oqGKbaRRKIeecEaZPXYRd7MYa4e9K0Cfk5Bm0MNs9lwu/BYsw=="], - "@tiptap/extension-strike": ["@tiptap/extension-strike@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-jY2InoUlKkuk5KHoIDGdML1OCA2n6PRHAtxwHNkAmiYh0Khf0zaVPGFpx4dgQrN7W5Q1WE6oBZnjrvy6qb7w0g=="], + "@tiptap/extension-strike": ["@tiptap/extension-strike@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-easnVaN11Wl+5fOtfvzJ10J762S9TRXZaMj5rLBGavgf82DCYHqhGhBqpLQrJ41r4nPABGlYvTRoxfvBLB74Lg=="], "@tiptap/extension-table": ["@tiptap/extension-table@3.18.0", "", { "peerDependencies": { "@tiptap/core": "^3.18.0", "@tiptap/pm": "^3.18.0" } }, "sha512-04BQYiSKxhy33Pd7UFZchW8UYH0FOts8LCwel11n507w2lNd/wbYMTI2A5AfOEOXvr6Xwx/jOWX4MWuhMqiZwQ=="], @@ -2847,23 +2690,23 @@ "@tiptap/extension-table-row": ["@tiptap/extension-table-row@3.18.0", "", { "peerDependencies": { "@tiptap/extension-table": "^3.18.0" } }, "sha512-3m7/SmWOlmRHExayHrU6I0wqwuzGE7vE8S3ORqUc7gA9yYA5PbnEQF+1K6jtVQjQd4LsJwBVqIBBPdD5WP1Tvg=="], - "@tiptap/extension-task-item": ["@tiptap/extension-task-item@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-bUxP6fmlrF4sbpHnkm0nTKNVmtQXNnhrbWsUt0MCnvAd9y5Nq3ohpOzMOCL71AEHfmeV1kEkPbpdwKb1R7XDbg=="], + "@tiptap/extension-task-item": ["@tiptap/extension-task-item@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-Rt7g61pcmgTHTy8mU2MDi4+FERKLAvoejJqmrCKf1CJUGzwWMsyRlKvS7FykpzfSrDiVlE7uSFCUkd/avgV0HQ=="], - "@tiptap/extension-task-list": ["@tiptap/extension-task-list@3.22.3", "", { "peerDependencies": { "@tiptap/extension-list": "^3.22.3" } }, "sha512-ze/DNj7Uq/Xjo+t8UuumnvJcmGVrVvLar11nFxobgpij21ja6XiUNMZ+BywvFurWbh5NrHeSYV07vFOWWf5Cpg=="], + "@tiptap/extension-task-list": ["@tiptap/extension-task-list@3.21.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.21.0" } }, "sha512-uH2h4Z2JmafFH5TfWYmKbfO7+jt3mgF59ESj+Qc9Szd1j9JJvLOH6anrIxqsyi50jz0QCl/lPv38PKr/ugvjtQ=="], - "@tiptap/extension-text": ["@tiptap/extension-text@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-Q9R7JsTdomP5uUjtPjNKxHT1xoh/i9OJZnmgJLe7FcgZEaPOQ3bWxmKZoLZQfDfZjyB8BtH+Hc7nUvhCMOePxw=="], + "@tiptap/extension-text": ["@tiptap/extension-text@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-Zx8QdB8a5iBuE4uO21c3BjmpBfaJEr2Jd1QFnsdgx11fm6P7dGgZaGko1FaINhfOPRGTN6O/kiF02cDMdOHa/w=="], - "@tiptap/extension-underline": ["@tiptap/extension-underline@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3" } }, "sha512-Ch6CBWRa5w90yYSPUW6x9Py9JdrXMqk3pZ9OIlMYD8A7BqyZGfiHerX7XDMYDS09KjyK3U9XH60/zxYOzXdDLA=="], + "@tiptap/extension-underline": ["@tiptap/extension-underline@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0" } }, "sha512-gGmBEymbWnr8AIS8bI/bPw5rcwo7wAFcBw/TsLd1nAanu1dDqSRNDBrit3m02Ru+D88u2SfNvmbOPI1pz+1f5w=="], - "@tiptap/extensions": ["@tiptap/extensions@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-s5eiMq0m5N6N+W7dU6rd60KgZyyCD7FvtPNNswISfPr12EQwJBfbjWwTqd0UKNzA4fNrhQEERXnzORkykttPeA=="], + "@tiptap/extensions": ["@tiptap/extensions@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-MN1uh5PmHT1F2BNsbc21MIS0AMFFA73oODlp/4ckpBR4o5AxRwV+8f43Cd52UL4MgMkKj/A+QfZ7iK9IDb0h5A=="], - "@tiptap/pm": ["@tiptap/pm@3.22.3", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-NjfWjZuvrqmpICT+GZWNIjtOdhPyqFKDMtQy7tsQ5rErM9L2ZQdy/+T/BKSO1JdTeBhdg9OP+0yfsqoYp2aT6A=="], + "@tiptap/pm": ["@tiptap/pm@3.21.0", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-I3sNo7oMMsR6FFz1ecvPb9uCF0VQuS2WV67j8Io2M7DJicRWCE/GM5DaiYjTeWBbnByk6BuG0txoJATAqPVliQ=="], - "@tiptap/react": ["@tiptap/react@3.22.3", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "fast-equals": "^5.3.3", "use-sync-external-store": "^1.4.0" }, "optionalDependencies": { "@tiptap/extension-bubble-menu": "^3.22.3", "@tiptap/extension-floating-menu": "^3.22.3" }, "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-6MNr6z0PxwfJFs+BKhHcvPNvY+UV1PXgqzTiTM4Z9guml84iVZxv7ZOCSj1dFYTr3Bf1MiOs4hT1yvBFlTfIaQ=="], + "@tiptap/react": ["@tiptap/react@3.21.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "fast-equals": "^5.3.3", "use-sync-external-store": "^1.4.0" }, "optionalDependencies": { "@tiptap/extension-bubble-menu": "^3.21.0", "@tiptap/extension-floating-menu": "^3.21.0" }, "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-p+OKJgxmFB3t5nY3mjaqjKaj8vJX9++OkdrZLRxYuG7ScAHemWraWQ25sgNZl1LDaRYrdnNYxx9MP0CXOSB6ew=="], - "@tiptap/starter-kit": ["@tiptap/starter-kit@3.22.3", "", { "dependencies": { "@tiptap/core": "^3.22.3", "@tiptap/extension-blockquote": "^3.22.3", "@tiptap/extension-bold": "^3.22.3", "@tiptap/extension-bullet-list": "^3.22.3", "@tiptap/extension-code": "^3.22.3", "@tiptap/extension-code-block": "^3.22.3", "@tiptap/extension-document": "^3.22.3", "@tiptap/extension-dropcursor": "^3.22.3", "@tiptap/extension-gapcursor": "^3.22.3", "@tiptap/extension-hard-break": "^3.22.3", "@tiptap/extension-heading": "^3.22.3", "@tiptap/extension-horizontal-rule": "^3.22.3", "@tiptap/extension-italic": "^3.22.3", "@tiptap/extension-link": "^3.22.3", "@tiptap/extension-list": "^3.22.3", "@tiptap/extension-list-item": "^3.22.3", "@tiptap/extension-list-keymap": "^3.22.3", "@tiptap/extension-ordered-list": "^3.22.3", "@tiptap/extension-paragraph": "^3.22.3", "@tiptap/extension-strike": "^3.22.3", "@tiptap/extension-text": "^3.22.3", "@tiptap/extension-underline": "^3.22.3", "@tiptap/extensions": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-vdW/Oo1fdwTL1VOQ5YYbTov00ANeHLquBVEZyL/EkV7Xv5io9rXQsCysJfTSHhiQlyr2MtWFB4+CPGuwXjQWOQ=="], + "@tiptap/starter-kit": ["@tiptap/starter-kit@3.21.0", "", { "dependencies": { "@tiptap/core": "^3.21.0", "@tiptap/extension-blockquote": "^3.21.0", "@tiptap/extension-bold": "^3.21.0", "@tiptap/extension-bullet-list": "^3.21.0", "@tiptap/extension-code": "^3.21.0", "@tiptap/extension-code-block": "^3.21.0", "@tiptap/extension-document": "^3.21.0", "@tiptap/extension-dropcursor": "^3.21.0", "@tiptap/extension-gapcursor": "^3.21.0", "@tiptap/extension-hard-break": "^3.21.0", "@tiptap/extension-heading": "^3.21.0", "@tiptap/extension-horizontal-rule": "^3.21.0", "@tiptap/extension-italic": "^3.21.0", "@tiptap/extension-link": "^3.21.0", "@tiptap/extension-list": "^3.21.0", "@tiptap/extension-list-item": "^3.21.0", "@tiptap/extension-list-keymap": "^3.21.0", "@tiptap/extension-ordered-list": "^3.21.0", "@tiptap/extension-paragraph": "^3.21.0", "@tiptap/extension-strike": "^3.21.0", "@tiptap/extension-text": "^3.21.0", "@tiptap/extension-underline": "^3.21.0", "@tiptap/extensions": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-w7fWxglDtqXFBgRYH+LforJyUboSAQllnWQbGVSTyX4rsICqZjkb3f6CTSUWpGoGKmlmbb2ZpEuoik7tur9d8Q=="], - "@tiptap/suggestion": ["@tiptap/suggestion@3.22.3", "", { "peerDependencies": { "@tiptap/core": "^3.22.3", "@tiptap/pm": "^3.22.3" } }, "sha512-m2c+5gDj2vW7UI1J4JHCKehQUVE12qBhgF+DC+WEWUU8ZrFNf5OEYWQHDNsopa5RRpilfKfhPNbMtXgvGOsk6g=="], + "@tiptap/suggestion": ["@tiptap/suggestion@3.21.0", "", { "peerDependencies": { "@tiptap/core": "^3.21.0", "@tiptap/pm": "^3.21.0" } }, "sha512-ShgbaH2hbCRLV+AaVuSx7a/nzPOSdUeW0TNeuxZfWim62MBcx33qtllja1zOoY2tgGXokEihuzFODx83IyvGfQ=="], "@tokenlens/core": ["@tokenlens/core@1.3.0", "", {}, "sha512-d8YNHNC+q10bVpi95fELJwJyPVf1HfvBEI18eFQxRSZTdByXrP+f/ZtlhSzkx0Jl0aEmYVeBA5tPeeYRioLViQ=="], @@ -2899,7 +2742,7 @@ "@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="], - "@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="], + "@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="], @@ -2973,8 +2816,6 @@ "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], - "@types/diff": ["@types/diff@6.0.0", "", {}, "sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA=="], - "@types/draco3d": ["@types/draco3d@1.4.10", "", {}, "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw=="], "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], @@ -3009,8 +2850,6 @@ "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="], - "@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="], - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/keyv": ["@types/keyv@3.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="], @@ -3037,13 +2876,13 @@ "@types/mysql": ["@types/mysql@2.15.27", "", { "dependencies": { "@types/node": "*" } }, "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA=="], - "@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], "@types/offscreencanvas": ["@types/offscreencanvas@2019.7.3", "", {}, "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="], - "@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="], + "@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="], "@types/pg-pool": ["@types/pg-pool@2.0.7", "", { "dependencies": { "@types/pg": "*" } }, "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng=="], @@ -3107,7 +2946,7 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - "@types/yargs": ["@types/yargs@16.0.5", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ=="], + "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], @@ -3135,35 +2974,19 @@ "@use-gesture/react": ["@use-gesture/react@10.3.1", "", { "dependencies": { "@use-gesture/core": "10.3.1" }, "peerDependencies": { "react": ">= 16.8.0" } }, "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g=="], - "@vercel/blob": ["@vercel/blob@2.3.3", "", { "dependencies": { "async-retry": "^1.3.3", "is-buffer": "^2.0.5", "is-node-process": "^1.2.0", "throttleit": "^2.1.0", "undici": "^6.23.0" } }, "sha512-MtD7VLo6hU07eHR7bmk5SIMD290q574UaNYTe46qeyRT+hWrCy26CoAqfd7PnIefVXvRehRZBzukxuTO9iGTVg=="], + "@vercel/blob": ["@vercel/blob@2.3.2", "", { "dependencies": { "async-retry": "^1.3.3", "is-buffer": "^2.0.5", "is-node-process": "^1.2.0", "throttleit": "^2.1.0", "undici": "^6.23.0" } }, "sha512-FjlTJ5ffGj0RssrU0dJ90Zgr83AdhpIs2y9f3x386w+q9sM0P8m8Ouxsm3fqsjr4IyqTTo7Ioc2PJqxxOKNhjA=="], "@vercel/kv": ["@vercel/kv@3.0.0", "", { "dependencies": { "@upstash/redis": "^1.34.0" } }, "sha512-pKT8fRnfyYk2MgvyB6fn6ipJPCdfZwiKDdw7vB+HL50rjboEBHDVBEcnwfkEpVSp2AjNtoaOUH7zG+bVC/rvSg=="], - "@vercel/oidc": ["@vercel/oidc@3.2.0", "", {}, "sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug=="], + "@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="], "@vitejs/plugin-react": ["@vitejs/plugin-react@5.2.0", "", { "dependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.3", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw=="], - "@vscode/l10n": ["@vscode/l10n@0.0.18", "", {}, "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ=="], - - "@vscode/ripgrep": ["@vscode/ripgrep@1.17.1", "", { "dependencies": { "https-proxy-agent": "^7.0.2", "proxy-from-env": "^1.1.0", "yauzl": "^2.9.2" } }, "sha512-xTs7DGyAO3IsJYOCTBP8LnTvPiYVKEuyv8s0xyJDBXfs8rhBfqnZPvb6xDT+RnwWzcXqW27xLS/aGrkjX7lNWw=="], - - "@vue/compiler-core": ["@vue/compiler-core@3.5.32", "", { "dependencies": { "@babel/parser": "^7.29.2", "@vue/shared": "3.5.32", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ=="], - - "@vue/compiler-dom": ["@vue/compiler-dom@3.5.32", "", { "dependencies": { "@vue/compiler-core": "3.5.32", "@vue/shared": "3.5.32" } }, "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.31", "", { "dependencies": { "@babel/parser": "^7.29.2", "@vue/shared": "3.5.31", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-k/ueL14aNIEy5Onf0OVzR8kiqF/WThgLdFhxwa4e/KF/0qe38IwIdofoSWBTvvxQOesaz6riAFAUaYjoF9fLLQ=="], - "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.32", "", { "dependencies": { "@babel/parser": "^7.29.2", "@vue/compiler-core": "3.5.32", "@vue/compiler-dom": "3.5.32", "@vue/compiler-ssr": "3.5.32", "@vue/shared": "3.5.32", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.8", "source-map-js": "^1.2.1" } }, "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg=="], + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.31", "", { "dependencies": { "@vue/compiler-core": "3.5.31", "@vue/shared": "3.5.31" } }, "sha512-BMY/ozS/xxjYqRFL+tKdRpATJYDTTgWSo0+AJvJNg4ig+Hgb0dOsHPXvloHQ5hmlivUqw1Yt2pPIqp4e0v1GUw=="], - "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.32", "", { "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/shared": "3.5.32" } }, "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw=="], - - "@vue/reactivity": ["@vue/reactivity@3.5.32", "", { "dependencies": { "@vue/shared": "3.5.32" } }, "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ=="], - - "@vue/runtime-core": ["@vue/runtime-core@3.5.32", "", { "dependencies": { "@vue/reactivity": "3.5.32", "@vue/shared": "3.5.32" } }, "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ=="], - - "@vue/runtime-dom": ["@vue/runtime-dom@3.5.32", "", { "dependencies": { "@vue/reactivity": "3.5.32", "@vue/runtime-core": "3.5.32", "@vue/shared": "3.5.32", "csstype": "^3.2.3" } }, "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ=="], - - "@vue/server-renderer": ["@vue/server-renderer@3.5.32", "", { "dependencies": { "@vue/compiler-ssr": "3.5.32", "@vue/shared": "3.5.32" }, "peerDependencies": { "vue": "3.5.32" } }, "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ=="], - - "@vue/shared": ["@vue/shared@3.5.32", "", {}, "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg=="], + "@vue/shared": ["@vue/shared@3.5.31", "", {}, "sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw=="], "@wdio/config": ["@wdio/config@9.27.0", "", { "dependencies": { "@wdio/logger": "9.18.0", "@wdio/types": "9.27.0", "@wdio/utils": "9.27.0", "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", "import-meta-resolve": "^4.0.0", "jiti": "^2.6.1" } }, "sha512-9y8z7ugIbU6ycKrA2SqCpKh1/hobut2rDq9CLt/BNVzSlebBBVOTMiAt1XroZzcPnA7/ZqpbkpOsbpPUaAQuNQ=="], @@ -3209,39 +3032,31 @@ "@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], - "@whatwg-node/disposablestack": ["@whatwg-node/disposablestack@0.0.6", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.6.3" } }, "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw=="], - - "@whatwg-node/fetch": ["@whatwg-node/fetch@0.10.13", "", { "dependencies": { "@whatwg-node/node-fetch": "^0.8.3", "urlpattern-polyfill": "^10.0.0" } }, "sha512-b4PhJ+zYj4357zwk4TTuF2nEe0vVtOrwdsrNo5hL+u1ojXNhh1FgJ6pg1jzDlwlT4oBdzfSwaBwMCtFCsIWg8Q=="], - - "@whatwg-node/node-fetch": ["@whatwg-node/node-fetch@0.8.5", "", { "dependencies": { "@fastify/busboy": "^3.1.1", "@whatwg-node/disposablestack": "^0.0.6", "@whatwg-node/promise-helpers": "^1.3.2", "tslib": "^2.6.3" } }, "sha512-4xzCl/zphPqlp9tASLVeUhB5+WJHbuWGYpfoC2q1qh5dw0AqZBW7L27V5roxYWijPxj4sspRAAoOH3d2ztaHUQ=="], - - "@whatwg-node/promise-helpers": ["@whatwg-node/promise-helpers@1.3.2", "", { "dependencies": { "tslib": "^2.6.3" } }, "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA=="], - "@workflow/serde": ["@workflow/serde@4.1.0-beta.2", "", {}, "sha512-8kkeoQKLDaKXefjV5dbhBj2aErfKp1Mc4pb6tj8144cF+Em5SPbyMbyLCHp+BVrFfFVCBluCtMx+jjvaFVZGww=="], "@xmldom/xmldom": ["@xmldom/xmldom@0.8.12", "", {}, "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg=="], - "@xterm/addon-clipboard": ["@xterm/addon-clipboard@0.3.0-beta.195", "", { "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-V266O7m5wtLCcnXGUbi70cl96vyBcwaVTImftBEBXAo6X+Pn5NpG48QgP+svtt0gB7Sc0FDA/TBVeXuFyoX+kA=="], + "@xterm/addon-clipboard": ["@xterm/addon-clipboard@0.3.0-beta.197", "", { "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-o0u0xR/6QwTj7WytfMaNbz4Gm/lp2eW3EFzHN6LvQhqZEBdMt+GUb/GHgCM7YO35TP21W7DInqvZl+1WOzanJQ=="], - "@xterm/addon-fit": ["@xterm/addon-fit@0.12.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-Ihc+azRK3HFB2NVBEoWRkEUGYVxoojK2X4Jx6YxiRKdAu6bYzDTzTImE/0EDOjjz2AUUqddRwCUdSbz2/WvYfA=="], + "@xterm/addon-fit": ["@xterm/addon-fit@0.12.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-EoYQVIWp90XmNXBfrEocz5tk44JLMdHL9+Asd57Bj9DuERLLszA8pkF3wbuR5C7555g3sRTMTHlzYQ3gv9xbOw=="], - "@xterm/addon-image": ["@xterm/addon-image@0.10.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-jm6uzMpfXXut+Yfza/GNCUw2pOw3Bpsn4QEHvh5KCc8dfEuyoLeqmn026Y2kXY2BGoxj+DEHlmlPnL54ihCb2Q=="], + "@xterm/addon-image": ["@xterm/addon-image@0.10.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-31oIqBm+Yk3xyYGjBhhp308gDyFywv3JJAWBflycgqZFbvfZ2ju4IvHmvKJhp8qC+0ac6SRAA7XBKGqtoZjcsA=="], - "@xterm/addon-ligatures": ["@xterm/addon-ligatures@0.11.0-beta.195", "", { "dependencies": { "lru-cache": "^6.0.0", "opentype.js": "^0.8.0" }, "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-sGVuanoIVynj01vRlV8nT9cCPHGJU4zzlju0g37KiKn8C+W8sAQ7TlC+XUqAZTwClWMyrozRxETWOnKlfRsZKw=="], + "@xterm/addon-ligatures": ["@xterm/addon-ligatures@0.11.0-beta.197", "", { "dependencies": { "lru-cache": "^6.0.0", "opentype.js": "^0.8.0" }, "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-76arq3li5i71YP8RMatAsE7H79FvRV/gaLF/iwgxeQgIXurVt3bEuwta64JlMe+BchelmoVv22T4yQjFo2pOkQ=="], - "@xterm/addon-progress": ["@xterm/addon-progress@0.3.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-Y+sPNUPEKXwESizWCq+/rLMmj1uO/jPbcktoZMJlYLb0QeRTwDxAFKyz9EY7scJVitCjtZOlQz377sH8IK2o2w=="], + "@xterm/addon-progress": ["@xterm/addon-progress@0.3.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-ZvWE78sIBu0rAjpvycuKZqBVWLcm5ePO/oH4tBIwJLIY3g2FpRKKorBGPN9raBHw3Bfxzg7tZAFqv6iuDZxEIw=="], - "@xterm/addon-search": ["@xterm/addon-search@0.17.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-n7sQ3u1e1gSfKJvhKCz3W/Ov7KLAOB8auC9m+7sSaFgPCuFfi2/bP4I/TswPUDF5YpkYs9leBzeVdo08/+Cglg=="], + "@xterm/addon-search": ["@xterm/addon-search@0.17.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-F2hAFAheDDElC/25UcacZTx65JYnjoD6hhMVcLBbXrYhf0io1mtOZTVG5oxeitx1vpdLH1JGMmwFpHUSPspZzQ=="], - "@xterm/addon-serialize": ["@xterm/addon-serialize@0.15.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-BKlEQ5cao0J8sLvtFU/kmc4LAkAS+2JkblVIEu/FFHWUsuEaA4yZz4BtZrWBhql2JRfOq62hZFrqahZ0ViuZgA=="], + "@xterm/addon-serialize": ["@xterm/addon-serialize@0.15.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-uJEsQj0DDhDISLqusG/KP5Ely2N6IGw2NGTG8jiFClr6pr6TF1sMxdBTgPoNSwfnLMOORzEe92Fv9VMd7FqTKw=="], - "@xterm/addon-unicode11": ["@xterm/addon-unicode11@0.10.0-beta.195", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-+mb/c0OhOvITYwnNvzvSPTBOdtMxGAaeNAkajPH3xvPxeHOAQRSuX+gmWJZkSPhQJRMFE5tSZ2o6BgF8fXSixw=="], + "@xterm/addon-unicode11": ["@xterm/addon-unicode11@0.10.0-beta.197", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-/8zKqf+7R+r6p+/7R7y4ztXwfzDXIqtUp9agxLxAFHLsmCzgqhWX8VL3lOUISK6GR5OLZi15wfOopMTUiDugqQ=="], - "@xterm/addon-webgl": ["@xterm/addon-webgl@0.20.0-beta.194", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.195" } }, "sha512-aX4yGkHyoJVmxh3ZVMha7CYdTFu7tuzTJ0ljyXKAVFrdO+Wve4luK8w3wLmxuvqa9LWA9muMx/bGeEWtwD/Nlg=="], + "@xterm/addon-webgl": ["@xterm/addon-webgl@0.20.0-beta.196", "", { "peerDependencies": { "@xterm/xterm": "^6.1.0-beta.197" } }, "sha512-5nYgVRwHFVihNNFAARbePZyxi3yAd4VAnF44FaGIjYWCIkA/N27Nl7NwSEX5nHedEbRY/ZfVq/zGFKQBetZlEw=="], - "@xterm/headless": ["@xterm/headless@6.1.0-beta.195", "", {}, "sha512-sUOeZ08431n5wx6ukrQ96eXEGN7z8swUfvHkl4nAEqpYEMxS/ua+E6v5PGT6fpQFbOt2R3zIm6LDIfy9GX24mA=="], + "@xterm/headless": ["@xterm/headless@6.1.0-beta.197", "", {}, "sha512-/yFl1fl20Rdons0Ng356caGWO/Qeubxr3zWE3PHUaIRuQ5hFng83lhGbNRZMMZJO/OXArXlaxbeuFWYGbYWhGg=="], - "@xterm/xterm": ["@xterm/xterm@6.1.0-beta.195", "", {}, "sha512-lLVfI3T4pX4W4qrbf2Qhdq5Pa00FkOOUz9vlOm6f1r5wel1mUafeJL8zacfsUVdc03MsCKHRyZkLubmDEnabcw=="], + "@xterm/xterm": ["@xterm/xterm@6.1.0-beta.197", "", {}, "sha512-vzoc8sBcsvFpziSgeVGKZQDT1T/9MmEUKfUDpVqc3slDv7o0SiQCjvPeOF8y1++5vx2xmUn8lfcLnbfdtigtSQ=="], "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], @@ -3277,12 +3092,10 @@ "aggregate-error": ["aggregate-error@4.0.1", "", { "dependencies": { "clean-stack": "^4.0.0", "indent-string": "^5.0.0" } }, "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w=="], - "ai": ["ai@6.0.168", "", { "dependencies": { "@ai-sdk/gateway": "3.0.104", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2HqCJuO+1V2aV7vfYs5LFEUfxbkGX+5oa54q/gCCTL7KLTdbxcCu5D7TdLA5kwsrs3Szgjah9q6D9tpjHM3hUQ=="], + "ai": ["ai@6.0.141", "", { "dependencies": { "@ai-sdk/gateway": "3.0.83", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-+GomGQWaId3xN0wcugUW/H7xMMaFkID2PiS7K/Wugj45G3efv0BXhQ3psRZoQVoRbOpdNoUqcK/KTB+FR4h6qg=="], "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], - "ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="], - "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], @@ -3295,8 +3108,6 @@ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "ansi_up": ["ansi_up@6.0.6", "", {}, "sha512-yIa1x3Ecf8jWP4UWEunNjqNX6gzE4vg2gGz+xqRGY+TBSucnYp6RRdPV4brmtg6bQ1ljD48mZ5iGSEj7QEpRKA=="], - "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], @@ -3307,9 +3118,9 @@ "app-builder-lib": ["app-builder-lib@26.8.1", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.3", "@electron/rebuild": "^4.0.3", "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "26.8.1", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.3", "plist": "3.1.0", "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", "semver": "~7.7.3", "tar": "^7.5.7", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0", "which": "^5.0.0" }, "peerDependencies": { "dmg-builder": "26.8.1", "electron-builder-squirrel-windows": "26.8.1" } }, "sha512-p0Im/Dx5C4tmz8QEE1Yn4MkuPC8PrnlRneMhWJj7BBXQfNTJUshM/bp3lusdEsDbvvfJZpXWnYesgSLvwtM2Zw=="], - "archiver": ["archiver@5.3.2", "", { "dependencies": { "archiver-utils": "^2.1.0", "async": "^3.2.4", "buffer-crc32": "^0.2.1", "readable-stream": "^3.6.0", "readdir-glob": "^1.1.2", "tar-stream": "^2.2.0", "zip-stream": "^4.1.0" } }, "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw=="], + "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], - "archiver-utils": ["archiver-utils@2.1.0", "", { "dependencies": { "glob": "^7.1.4", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash.defaults": "^4.2.0", "lodash.difference": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^2.0.0" } }, "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw=="], + "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], @@ -3323,8 +3134,6 @@ "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - "arrgv": ["arrgv@1.0.2", "", {}, "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw=="], "arrify": ["arrify@3.0.0", "", {}, "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw=="], @@ -3333,7 +3142,7 @@ "assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="], - "ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="], + "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], @@ -3363,8 +3172,6 @@ "axios": ["axios@1.14.0", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ=="], - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - "b4a": ["b4a@1.8.0", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg=="], "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="], @@ -3391,7 +3198,7 @@ "babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.2.0", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg=="], - "babel-preset-expo": ["babel-preset-expo@55.0.17", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.4", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^55.0.13", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-voPAKycqeqOE+4g/nW6gGaNPMnj3MYCYbVEZlZDUlztGVxlKKkUD+xwlK0ZU/uy6HxAY+tjBEpvsabD5g6b2oQ=="], + "babel-preset-expo": ["babel-preset-expo@55.0.13", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.4", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^55.0.8", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-7m3Hpi6R1M+3u2LEU15OV59ATtbqz6kFvL6y9TaZTeOGLV28MFULawCQw3BtO/qMYUPz0vkH1OdbCuG7E2cTbg=="], "babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="], @@ -3401,13 +3208,13 @@ "bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="], - "bare-fs": ["bare-fs@4.7.1", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw=="], + "bare-fs": ["bare-fs@4.5.6", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw=="], - "bare-os": ["bare-os@3.8.7", "", {}, "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w=="], + "bare-os": ["bare-os@3.8.4", "", {}, "sha512-4JboWUl7/2LhgU536tjUszzaVC8/WEWKtyX5crayvlN71ih8+O2SdvBhotQeDsuhhmPZmLCrPBJEcwVPhI/kkQ=="], "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], - "bare-stream": ["bare-stream@2.13.0", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-3zAJRZMDFGjdn+RVnNpF9kuELw+0Fl3lpndM4NcEOhb9zwtSo/deETfuIwMSE5BXanA0FrN1qVjffGwAg2Y7EA=="], + "bare-stream": ["bare-stream@2.11.0", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Y/+iQ49fL3rIn6w/AVxI/2+BRrpmzJvdWt5Jv8Za6Ngqc6V227c+pYjYYgLdpR3MwQ9ObVXD0ZrqoBztakM0rw=="], "bare-url": ["bare-url@2.4.0", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA=="], @@ -3415,17 +3222,17 @@ "base64id": ["base64id@2.0.0", "", {}, "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.12", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ=="], - "basic-ftp": ["basic-ftp@5.3.0", "", {}, "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w=="], + "basic-ftp": ["basic-ftp@5.2.0", "", {}, "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw=="], "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="], "before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], - "better-auth": ["better-auth@1.5.6", "", { "dependencies": { "@better-auth/core": "1.5.6", "@better-auth/drizzle-adapter": "1.5.6", "@better-auth/kysely-adapter": "1.5.6", "@better-auth/memory-adapter": "1.5.6", "@better-auth/mongo-adapter": "1.5.6", "@better-auth/prisma-adapter": "1.5.6", "@better-auth/telemetry": "1.5.6", "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.2", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.12", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-QSpJTqaT1XVfWRQe/fm3PgeuwOIlz1nWX/Dx7nsHStJ382bLzmDbQk2u7IT0IJ6wS5SRxfqEE1Ev9TXontgyAQ=="], + "better-auth": ["better-auth@1.6.5", "", { "dependencies": { "@better-auth/core": "1.6.5", "@better-auth/drizzle-adapter": "1.6.5", "@better-auth/kysely-adapter": "1.6.5", "@better-auth/memory-adapter": "1.6.5", "@better-auth/mongo-adapter": "1.6.5", "@better-auth/prisma-adapter": "1.6.5", "@better-auth/telemetry": "1.6.5", "@better-auth/utils": "0.4.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.5", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.14", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": "^0.45.2", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-rSt8JtJOJK0MqPShXINCmM6DV30GsDvnCTlIxQIzP9OpUx/umA40nUc4ALZHQyqAPbw1ib/a549kIWw/WyxxKA=="], - "better-call": ["better-call@1.3.2", "", { "dependencies": { "@better-auth/utils": "^0.3.1", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw=="], + "better-call": ["better-call@1.3.5", "", { "dependencies": { "@better-auth/utils": "^0.4.0", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-kOFJkBP7utAQLEYrobZm3vkTH8mXq5GNgvjc5/XEST1ilVHaxXUXfeDeFlqoETMtyqS4+3/h4ONX2i++ebZrvA=="], "better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="], @@ -3437,8 +3244,6 @@ "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "binary": ["binary@0.3.0", "", { "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" } }, "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg=="], - "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], @@ -3447,7 +3252,7 @@ "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], - "bluebird": ["bluebird@3.4.7", "", {}, "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="], + "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], "blueimp-md5": ["blueimp-md5@2.19.0", "", {}, "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w=="], @@ -3465,7 +3270,7 @@ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], "bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="], @@ -3477,17 +3282,13 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "buffer-indexof-polyfill": ["buffer-indexof-polyfill@1.0.2", "", {}, "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A=="], - - "buffers": ["buffers@0.1.1", "", {}, "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="], - "bufferutil": ["bufferutil@4.1.0", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw=="], "builder-util": ["builder-util@26.8.1", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.12", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" } }, "sha512-pm1lTYbGyc90DHgCDO7eo8Rl4EqKLciayNbZqGziqnH9jrlKe8ZANGdityLZU+pJh16dfzjAx2xQq9McuIPEtw=="], "builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], - "bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="], + "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], @@ -3509,14 +3310,12 @@ "camera-controls": ["camera-controls@3.1.2", "", { "peerDependencies": { "three": ">=0.126.1" } }, "sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001788", "", {}, "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001782", "", {}, "sha512-dZcaJLJeDMh4rELYFw1tvSn1bhZWYFOt468FcbHHxx/Z/dFidd1I6ciyFdi3iwfQCyOjqo9upF6lGQYtMiJWxw=="], "cbor": ["cbor@8.1.0", "", { "dependencies": { "nofilter": "^3.1.0" } }, "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - "chainsaw": ["chainsaw@0.1.0", "", { "dependencies": { "traverse": ">=0.3.0 <0.4" } }, "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ=="], - "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], @@ -3527,15 +3326,15 @@ "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], - "chat": ["chat@4.26.0", "", { "dependencies": { "@workflow/serde": "4.1.0-beta.2", "mdast-util-to-string": "^4.0.0", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "remend": "^1.2.1", "unified": "^11.0.5" } }, "sha512-QToDnIEGpyb8yQA6YLMHOSRK30YVk4RtsyFyuWFYyB2c4jQlyIrSWtwVK7qyvmvqzQp9uDwCdJRAhS8GtCHAGQ=="], + "chat": ["chat@4.24.0", "", { "dependencies": { "@workflow/serde": "4.1.0-beta.2", "mdast-util-to-string": "^4.0.0", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "remend": "^1.2.1", "unified": "^11.0.5" } }, "sha512-0TxglwtGRMGlqERuHVZZ27Z4YBeZH3oRXCqHZYuI41L7xcSHF5C3wEHTMdVqHp3p8ZKQcKYQPOwYWvaeFVa4+g=="], "cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="], "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="], - "chevrotain": ["chevrotain@12.0.0", "", { "dependencies": { "@chevrotain/cst-dts-gen": "12.0.0", "@chevrotain/gast": "12.0.0", "@chevrotain/regexp-to-ast": "12.0.0", "@chevrotain/types": "12.0.0", "@chevrotain/utils": "12.0.0" } }, "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ=="], + "chevrotain": ["chevrotain@11.1.2", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", "@chevrotain/regexp-to-ast": "11.1.2", "@chevrotain/types": "11.1.2", "@chevrotain/utils": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg=="], - "chevrotain-allstar": ["chevrotain-allstar@0.4.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^12.0.0" } }, "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA=="], + "chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="], "chokidar": ["chokidar@3.6.0", "", { "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" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], @@ -3597,9 +3396,7 @@ "code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="], - "code-inspector-plugin": ["code-inspector-plugin@1.5.1", "", { "dependencies": { "@code-inspector/core": "1.5.1", "@code-inspector/esbuild": "1.5.1", "@code-inspector/mako": "1.5.1", "@code-inspector/turbopack": "1.5.1", "@code-inspector/vite": "1.5.1", "@code-inspector/webpack": "1.5.1", "chalk": "4.1.1" } }, "sha512-7gOqqBurKCucnls1ZHw0KWb7Z5u7gg3Q2pFSY9rrttFmwRaFJfJiscKEbm7X9IKmeEvkFRtNvNrHbSVQ67L8pQ=="], - - "code-red": ["code-red@1.0.4", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "@types/estree": "^1.0.1", "acorn": "^8.10.0", "estree-walker": "^3.0.3", "periscopic": "^3.1.0" } }, "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw=="], + "code-inspector-plugin": ["code-inspector-plugin@1.4.5", "", { "dependencies": { "@code-inspector/core": "1.4.5", "@code-inspector/esbuild": "1.4.5", "@code-inspector/mako": "1.4.5", "@code-inspector/turbopack": "1.4.5", "@code-inspector/vite": "1.4.5", "@code-inspector/webpack": "1.4.5", "chalk": "4.1.1" } }, "sha512-yp3zHd5AZhtVoBNOzKQuJVo1wZe7AIO2vAiVhF8WIAK02IwM9+gY+Pr9deajx+XyJLbzMW+3CgdfLIh+xxW2Hg=="], "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], @@ -3625,7 +3422,7 @@ "compare-version": ["compare-version@0.1.2", "", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="], - "compress-commons": ["compress-commons@4.1.2", "", { "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg=="], + "compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="], "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="], @@ -3649,7 +3446,7 @@ "console-table-printer": ["console-table-printer@2.15.0", "", { "dependencies": { "simple-wcswidth": "^1.1.2" } }, "sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw=="], - "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], + "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -3659,7 +3456,7 @@ "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - "cookie-es": ["cookie-es@3.1.1", "", {}, "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg=="], + "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], @@ -3669,34 +3466,24 @@ "core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="], - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + "core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], "cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="], - "cosmiconfig": ["cosmiconfig@8.3.6", "", { "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="], - - "cosmiconfig-toml-loader": ["cosmiconfig-toml-loader@1.0.0", "", { "dependencies": { "@iarna/toml": "^2.2.5" } }, "sha512-H/2gurFWVi7xXvCyvsWRLCMekl4tITJcX0QEsDMpzxtuxDyM59xLatYNg4s/k9AA/HdtCYfj2su8mgA0GSDLDA=="], - "crc": ["crc@3.8.0", "", { "dependencies": { "buffer": "^5.1.0" } }, "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ=="], "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], - "crc32-stream": ["crc32-stream@4.0.3", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^3.4.0" } }, "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw=="], + "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], "crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="], - "cron-parser": ["cron-parser@5.5.0", "", { "dependencies": { "luxon": "^3.7.1" } }, "sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww=="], - - "cronstrue": ["cronstrue@3.14.0", "", { "bin": { "cronstrue": "bin/cli.js" } }, "sha512-XnW4vuK/jPJjmTyDWiej1Zq36Od7ITwxaV2O1pzHZuyMVvdy7NAvyvIBzybt+idqSpfqYuoDG7uf/ocGtJVWxA=="], - "cross-dirname": ["cross-dirname@0.1.0", "", {}, "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q=="], "cross-env": ["cross-env@10.1.0", "", { "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw=="], - "cross-inspect": ["cross-inspect@1.0.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A=="], - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="], @@ -3721,7 +3508,7 @@ "currently-unhandled": ["currently-unhandled@0.4.1", "", { "dependencies": { "array-find-index": "^1.0.1" } }, "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng=="], - "cytoscape": ["cytoscape@3.33.2", "", {}, "sha512-sj4HXd3DokGhzZAdjDejGvTPLqlt84vNFN8m7bGsOzDY5DyVcxIb2ejIXat2Iy7HxWhdT/N1oKyheJ5YdpsGuw=="], + "cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="], "cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="], @@ -3795,8 +3582,6 @@ "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], - "dataloader": ["dataloader@2.2.3", "", {}, "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA=="], - "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="], "date-fns-jalali": ["date-fns-jalali@4.1.0-0", "", {}, "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg=="], @@ -3811,8 +3596,6 @@ "debounce-fn": ["debounce-fn@6.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ=="], - "debounce-promise": ["debounce-promise@3.1.2", "", {}, "sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg=="], - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], @@ -3825,8 +3608,6 @@ "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], - "dedent-js": ["dedent-js@1.0.1", "", {}, "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ=="], - "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], "deep-rename-keys": ["deep-rename-keys@0.2.1", "", { "dependencies": { "kind-of": "^3.0.2", "rename-keys": "^1.1.2" } }, "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A=="], @@ -3873,11 +3654,11 @@ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], - "devtools-protocol": ["devtools-protocol@0.0.1595872", "", {}, "sha512-kRfgp8vWVjBu/fbYCiVFiOqsCk3CrMKEo3WbgGT2NXK2dG7vawWPBljixajVgGK9II8rDO9G0oD0zLt3I1daRg=="], + "devtools-protocol": ["devtools-protocol@0.0.1581282", "", {}, "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ=="], "dexie": ["dexie@4.4.2", "", {}, "sha512-zMtV8q79EFE5U8FKZvt0Y/77PCU/Hr/RDxv1EDeo228L+m/HTbeN2AjoQm674rhQCX8n3ljK87lajt7UQuZfvw=="], - "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="], + "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], "dir-compare": ["dir-compare@4.2.0", "", { "dependencies": { "minimatch": "^3.0.5", "p-limit": "^3.1.0 " } }, "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ=="], @@ -3895,14 +3676,6 @@ "dnssd-advertise": ["dnssd-advertise@1.1.4", "", {}, "sha512-AmGyK9WpNf06WeP5TjHZq/wNzP76OuEeaiTlKr9E/EEelYLczywUKoqRz+DPRq/ErssjT4lU+/W7wzJW+7K/ZA=="], - "dockerfile-ast": ["dockerfile-ast@0.7.1", "", { "dependencies": { "vscode-languageserver-textdocument": "^1.0.8", "vscode-languageserver-types": "^3.17.3" } }, "sha512-oX/A4I0EhSkGqrFv0YuvPkBUSYp1XiY8O8zAKc8Djglx8ocz+JfOr8gP0ryRMC2myqvDLagmnZaU9ot1vG2ijw=="], - - "dockerfile-language-server-nodejs": ["dockerfile-language-server-nodejs@0.15.0", "", { "dependencies": { "dockerfile-language-service": "0.16.1", "dockerfile-utils": "0.16.3", "vscode-languageserver": "~8.0.0", "vscode-languageserver-textdocument": "~1.0.8" }, "bin": { "docker-langserver": "bin/docker-langserver" } }, "sha512-iS3GUUAn1bC3sDdLyg6CUnIaVQfViJBh+FhWBPftK6kJkhUMxFG2sr25OqMVaZgRsVuJEoNpflgJN3FCbkA01A=="], - - "dockerfile-language-service": ["dockerfile-language-service@0.16.1", "", { "dependencies": { "dockerfile-ast": "0.7.1", "dockerfile-utils": "0.16.3", "vscode-languageserver-textdocument": "1.0.8", "vscode-languageserver-types": "3.17.3" } }, "sha512-4tKDJHXl7BQMSi807TlyJ+4ApH5WkDai2PSFju/pjy7atRchJgn4UrmPlq8E0dVqyZwyTiNfapHxqsUQyQSMOg=="], - - "dockerfile-utils": ["dockerfile-utils@0.16.3", "", { "dependencies": { "dockerfile-ast": "0.7.1", "vscode-languageserver-textdocument": "^1.0.8", "vscode-languageserver-types": "^3.17.3" }, "bin": { "dockerfile-utils": "bin/dockerfile-utils" } }, "sha512-BslaqRR6PzCnhu+toDbkVAjq0B0CEgrCltk+enJ/xwCmvAHB1QqpO9QhXVIzMg/iSuD4tzS0Ex9n4Ik5ffI7pA=="], - "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="], "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], @@ -3911,13 +3684,13 @@ "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], - "dompurify": ["dompurify@3.4.0", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg=="], + "dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="], "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], "dot-prop": ["dot-prop@10.1.0", "", { "dependencies": { "type-fest": "^5.0.0" } }, "sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q=="], - "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], + "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="], "dotenv-cli": ["dotenv-cli@11.0.0", "", { "dependencies": { "cross-spawn": "^7.0.6", "dotenv": "^17.1.0", "dotenv-expand": "^12.0.0", "minimist": "^1.2.6" }, "bin": { "dotenv": "cli.js" } }, "sha512-r5pA8idbk7GFWuHEU7trSTflWcdBpQEK+Aw17UrSHjS6CReuhrrPcyC3zcQBPQvhArRHnBo/h6eLH1fkCvNlww=="], @@ -3927,14 +3700,10 @@ "drizzle-kit": ["drizzle-kit@0.31.8", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg=="], - "drizzle-orm": ["drizzle-orm@0.45.1", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA=="], - - "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], + "drizzle-orm": ["drizzle-orm@0.45.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - "duplexer2": ["duplexer2@0.1.4", "", { "dependencies": { "readable-stream": "^2.0.2" } }, "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA=="], - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], @@ -3957,7 +3726,7 @@ "electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="], - "electron-to-chromium": ["electron-to-chromium@1.5.340", "", {}, "sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="], "electron-updater": ["electron-updater@6.8.3", "", { "dependencies": { "builder-util-runtime": "9.5.1", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", "semver": "~7.7.3", "tiny-typed-emitter": "^2.1.0" } }, "sha512-Z6sgw3jgbikWKXei1ENdqFOxBP0WlXg3TtKfz0rgw2vIZFJUyI4pD7ZN7jrkm7EoMK+tcm/qTnPUdqfZukBlBQ=="], @@ -3965,8 +3734,6 @@ "electron-winstaller": ["electron-winstaller@5.4.0", "", { "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", "fs-extra": "^7.0.1", "lodash": "^4.17.21", "temp": "^0.9.0" }, "optionalDependencies": { "@electron/windows-sign": "^1.1.2" } }, "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg=="], - "elkjs": ["elkjs@0.11.1", "", {}, "sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg=="], - "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="], "embla-carousel-react": ["embla-carousel-react@8.6.0", "", { "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" } }, "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA=="], @@ -3997,8 +3764,6 @@ "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="], - "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], - "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], @@ -4069,9 +3834,7 @@ "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], - "eventsource-parser": ["eventsource-parser@3.0.7", "", {}, "sha512-zwxwiQqexizSXFZV13zMiEtW1E3lv7RlUv+1f5FBiR4x7wFhEjm3aFTyYkZQWzyN08WnPdox015GoRH5D/E5YA=="], - - "exceljs": ["exceljs@4.4.0", "", { "dependencies": { "archiver": "^5.0.0", "dayjs": "^1.8.34", "fast-csv": "^4.3.1", "jszip": "^3.10.1", "readable-stream": "^3.6.0", "saxes": "^5.0.1", "tmp": "^0.2.0", "unzipper": "^0.10.11", "uuid": "^8.3.0" } }, "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg=="], + "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], @@ -4079,73 +3842,73 @@ "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], - "expo": ["expo@55.0.15", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.24", "@expo/config": "~55.0.15", "@expo/config-plugins": "~55.0.8", "@expo/devtools": "55.0.2", "@expo/fingerprint": "0.16.6", "@expo/local-build-cache-provider": "55.0.11", "@expo/log-box": "55.0.10", "@expo/metro": "~55.0.0", "@expo/metro-config": "55.0.16", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~55.0.17", "expo-asset": "~55.0.15", "expo-constants": "~55.0.14", "expo-file-system": "~55.0.16", "expo-font": "~55.0.6", "expo-keep-awake": "~55.0.6", "expo-modules-autolinking": "55.0.17", "expo-modules-core": "55.0.22", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.1" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-sHIvqG477UU1jZHhaexXbUgsU7y+xnYZqDW1HrUkEBYiuEb5lobvWLmwea76EBVkityQx46UDtepFtarpUJQqQ=="], + "expo": ["expo@55.0.9", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.19", "@expo/config": "~55.0.11", "@expo/config-plugins": "~55.0.7", "@expo/devtools": "55.0.2", "@expo/fingerprint": "0.16.6", "@expo/local-build-cache-provider": "55.0.7", "@expo/log-box": "55.0.8", "@expo/metro": "~54.2.0", "@expo/metro-config": "55.0.11", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~55.0.13", "expo-asset": "~55.0.10", "expo-constants": "~55.0.9", "expo-file-system": "~55.0.12", "expo-font": "~55.0.4", "expo-keep-awake": "~55.0.4", "expo-modules-autolinking": "55.0.12", "expo-modules-core": "55.0.18", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.1" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-bYDhqr2v2UtTf/9s493bUVRtxsYqXF4KXkaS3sSW827DmgxNJv0NuWKWwfqFdDxKvDELd488J5X9l9ogqUrwOA=="], - "expo-application": ["expo-application@55.0.14", "", { "peerDependencies": { "expo": "*" } }, "sha512-NgqDIt3eCf4aVLp1L6AcEanCYoyJeuBsGrgGSzOIvxAsOvp5X3SYKW3ROgpKUnLQEKMWlzwETpjsUGszcqkk8g=="], + "expo-application": ["expo-application@55.0.10", "", { "peerDependencies": { "expo": "*" } }, "sha512-5ccf+S6hsQz+doi907TOJxKzV5AKgAgw004z4FoDWSoGhfab0LUPg6uyvOspuU4cbNvqw8EAy08hZbVO8nKc9Q=="], - "expo-asset": ["expo-asset@55.0.15", "", { "dependencies": { "@expo/image-utils": "^0.8.13", "expo-constants": "~55.0.14" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-d3FIpHJ6ZngYXxRItYWBGT5H8Wkk7/l4fMe8Mmd2xDyKrO0/CM7c8r/J5M71D+BJr5P3My8wertGYZXHSiZYxQ=="], + "expo-asset": ["expo-asset@55.0.10", "", { "dependencies": { "@expo/image-utils": "^0.8.12", "expo-constants": "~55.0.9" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-wxjNBKIaDyachq7oJgVlWVFzZ6SnNpJFJhkkcymXoTPt5O3XmDM+a6fT91xQQawCXTyZuCc1sNxKMetEofeYkg=="], - "expo-constants": ["expo-constants@55.0.14", "", { "dependencies": { "@expo/config": "~55.0.15", "@expo/env": "~2.1.1" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-l23QVQCYBPKT5zbxxZdJeuhiunadvWdjcQ9+GC8h+02jCoLmWRk20064nCINnQTP3Hf+uLPteUiwYrJd0e446w=="], + "expo-constants": ["expo-constants@55.0.9", "", { "dependencies": { "@expo/config": "~55.0.10", "@expo/env": "~2.1.1" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-iBiXjZeuU5S/8docQeNzsVvtDy4w0zlmXBpFEi1ypwugceEpdQQab65TVRbusXAcwpNVxCPMpNlDssYp0Pli2g=="], - "expo-crypto": ["expo-crypto@55.0.14", "", { "peerDependencies": { "expo": "*" } }, "sha512-TfAADBGZNNv9OOmdKFJCz54wDj87ufxtzQNSY+Roycpm8e5tuCnDIL7EjqUOmNTGH99Jj8ftPGFt4KGG2Ii2fg=="], + "expo-crypto": ["expo-crypto@55.0.10", "", { "peerDependencies": { "expo": "*" } }, "sha512-3emt67pWch07F7DPQutn7CUpaiCJI8OOFxCGiwmzeSqSjuWP9upGOXkLQNVWf+29KZQRTVgf88LhDC2GFshMNA=="], - "expo-dev-client": ["expo-dev-client@55.0.27", "", { "dependencies": { "expo-dev-launcher": "55.0.28", "expo-dev-menu": "55.0.23", "expo-dev-menu-interface": "55.0.2", "expo-manifests": "~55.0.15", "expo-updates-interface": "~55.1.5" }, "peerDependencies": { "expo": "*" } }, "sha512-Ala2ER6v1NPFySdnuQN/GpQZI9r7E9eSMvzD32vv8A4FJkPfzjvj6U5uH4IytQQLVTa837fknXRvOMwRb9ZYQQ=="], + "expo-dev-client": ["expo-dev-client@55.0.19", "", { "dependencies": { "expo-dev-launcher": "55.0.20", "expo-dev-menu": "55.0.17", "expo-dev-menu-interface": "55.0.1", "expo-manifests": "~55.0.11", "expo-updates-interface": "~55.1.3" }, "peerDependencies": { "expo": "*" } }, "sha512-NViuWgo1oqcKPei/M+FwwFC93cAsVhX7yT1/8pYPjMzPeZjV0DO82eur4H1ZwcmyxqSGjlae5R+MGXW88NeYEA=="], - "expo-dev-launcher": ["expo-dev-launcher@55.0.28", "", { "dependencies": { "@expo/schema-utils": "^55.0.3", "expo-dev-menu": "55.0.23", "expo-manifests": "~55.0.15" }, "peerDependencies": { "expo": "*" } }, "sha512-jwCD7YeGqZMWrS4KODb51kPBDta8bDrPjhYCnodglcQ0jhPVsAnVSbtsQ2/TaaYUUtv+ipm1ufhNTFtcwya9kA=="], + "expo-dev-launcher": ["expo-dev-launcher@55.0.20", "", { "dependencies": { "@expo/schema-utils": "^55.0.2", "expo-dev-menu": "55.0.17", "expo-manifests": "~55.0.11" }, "peerDependencies": { "expo": "*" } }, "sha512-vnIUk4k3ZyXSrSA7O4MVkWAIlErbSMEW8KexDGRVhEJkkAYZA2Yq5EcqJTrukvDC6/Jomx3Rpti+UfpLMIUk/g=="], - "expo-dev-menu": ["expo-dev-menu@55.0.23", "", { "dependencies": { "expo-dev-menu-interface": "55.0.2" }, "peerDependencies": { "expo": "*" } }, "sha512-m6B2EwkoX9hwzP50EZPX8vc/szGfvNFsUTw3ExTWnxiJ9/IM0WfCFYjt8siFjMHcyblIjBt/XLN6mw6q8m2AEg=="], + "expo-dev-menu": ["expo-dev-menu@55.0.17", "", { "dependencies": { "expo-dev-menu-interface": "55.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-UhYYHzNEy2imyPf0CFn4+2cIypqJ8D+pNBh9LxSVJaC4c3sARcGm+n52W4JA492KKiSyRrmwcWcbCMPLNj6sKQ=="], - "expo-dev-menu-interface": ["expo-dev-menu-interface@55.0.2", "", { "peerDependencies": { "expo": "*" } }, "sha512-DomUNvGzY/xliwnMdbAYY780sCv19N7zIbifc0ClcoCzJZpNSCkvJ2qGIFRPyM/7DmqmlHGCKi8di7kYYLKNEg=="], + "expo-dev-menu-interface": ["expo-dev-menu-interface@55.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-FkNtwq1q6NmYoy28pj+ZLuHmirJgc039pQbJ167MZJIaprLcMN1yy67qA7xBHK+FNJ8AN8kGCtMTPByg5UC72A=="], - "expo-device": ["expo-device@55.0.15", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "*" } }, "sha512-vXy4U/IeYI+zHGG45Ap6J7EuyQmkstyo8I+/5YGr5q2zmqLBo6SWE62wii8i9hLHheHn6AtF9UPrSWAREJrE8A=="], + "expo-device": ["expo-device@55.0.10", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "*" } }, "sha512-jvPImQg5LN7LNL57sGY6WaJxrWrPKXueUiDctZ7brLyiZfioS6wUieLwOTTkHUdtSSBtHkTvUg675w0sOzwlTg=="], - "expo-file-system": ["expo-file-system@55.0.16", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-EetQ/zVFK07Vmz4Yke0fvoES4xVwScTdd0PMoLekuMX7puE4op75pNnEdh1M0AeWzkqLrBoZIaU2ynSrKN5VZg=="], + "expo-file-system": ["expo-file-system@55.0.12", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-MFN/3L3gm174nxP2HqKQsSsPbjAj92wuidKFGSbl3Lt6oJTS09EbTwszX5BhYeeVSprcsw8pnlxYSmhkSqGEFw=="], - "expo-font": ["expo-font@55.0.6", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-x9czUA3UQWjIwa0ZUEs/eWJNqB4mAue/m4ltESlNPLZhHL0nWWqIfsyHmklTLFH7mVfcHSJvew6k+pR2FE1zVw=="], + "expo-font": ["expo-font@55.0.4", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-ZKeGTFffPygvY5dM/9ATM2p7QDkhsaHopH7wFAWgP2lKzqUMS9B/RxCvw5CaObr9Ro7x9YptyeRKX2HmgmMfrg=="], - "expo-glass-effect": ["expo-glass-effect@55.0.10", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-5kL/jATvgJWdrqPdxixrECJqD2l8cfQ4ALr1DK7qi9XkyI97ejXvUjB2VsfEePNy3Fg+/VwzA3n3L7Nv3tAPkw=="], + "expo-glass-effect": ["expo-glass-effect@55.0.8", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-IvUjHb/4t6r2H/LXDjcQ4uDoHrmO2cLOvEb9leLavQ4HX5+P4LRtQrMDMlkWAn5Wo5DkLcG8+1CrQU2nqgogTA=="], - "expo-image": ["expo-image@55.0.8", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-fNdvdYVcGn3g1x6o5AXHKzk4xX8U6rg2W9vFdE1pQO80kWCNReh003ypqSrGy4dD+zA8FtZjrNF3oMDGnPpIGQ=="], + "expo-image": ["expo-image@55.0.6", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-TKuu0uBmgTZlhd91Glv+V4vSBMlfl0bdQxfl97oKKZUo3OBC13l3eLik7v3VNLJN7PZbiwOAiXkZkqSOBx/Xsw=="], - "expo-json-utils": ["expo-json-utils@55.0.2", "", {}, "sha512-QJMOZOPOG7CTnKcrdVaiummn2va1MCO56z++eyWkDv3GBRODldM6MFMDf/jTREWthFc2Nxo6TuyWRrEV9S6n/Q=="], + "expo-json-utils": ["expo-json-utils@55.0.0", "", {}, "sha512-aupt/o5PDAb8dXDCb0JcRdkqnTLxe/F+La7jrnyd/sXlYFfRgBJLFOa1SqVFXm1E/Xam1SE/yw6eAb+DGY7Arg=="], - "expo-keep-awake": ["expo-keep-awake@55.0.6", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-acJjeHqkNxMVckEcJhGQeIksqqsarscSHJtT559bNgyiM4r14dViQ66su7bb6qDVeBt0K7z3glXI1dHVck1Zgg=="], + "expo-keep-awake": ["expo-keep-awake@55.0.4", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-vwfdMtMS5Fxaon8gC0AiE70SpxTsHJ+rjeoVJl8kdfdbxczF7OIaVmfjFJ5Gfigd/WZiLqxhfZk34VAkXF4PNg=="], - "expo-linking": ["expo-linking@55.0.13", "", { "dependencies": { "expo-constants": "~55.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-xbOqNWQCC5RGtXSW83ZCKOjRivyxO2zBouRYy/hgbsyrHUJhztMAjlq8RKYDUL8D6QVsH9Q81SNoq4Zhcn+4HQ=="], + "expo-linking": ["expo-linking@55.0.9", "", { "dependencies": { "expo-constants": "~55.0.9", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-QWEefQZUu7PuJzye19Hr6msqpO4VB4TiY4T/6AkISJzZnoZGxWg16s3JTZS7D/b3VMm8VQfhw9I5NF/7f8EPcA=="], - "expo-localization": ["expo-localization@55.0.13", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-fXiEUUihIrXmAEzoneaTOFcQ7TKmr25RR/ymrB/MvYTVnmevFA1zY2KI0VSiXY+NKKjZ8mG65YSn1wh4gEYKxA=="], + "expo-localization": ["expo-localization@55.0.9", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-ABRg4wEt15OCp9/3XOLC4ltPVvXmJgeCKNTJ4Nb8N6byuHITJHvZ3PwcC2YGpTzlAqfGbcs3rJdfg1ObT54PJQ=="], - "expo-manifests": ["expo-manifests@55.0.15", "", { "dependencies": { "@expo/config": "~55.0.14", "expo-json-utils": "~55.0.2" }, "peerDependencies": { "expo": "*" } }, "sha512-p40ftXpgLTFGddFy35MYZMyjm/E6IQdn3l6fBZZ6zeraEzYLt+VLHYsplOL9ccTYvUSWKN9aOWRpoEYpyGVBVw=="], + "expo-manifests": ["expo-manifests@55.0.11", "", { "dependencies": { "@expo/config": "~55.0.10", "expo-json-utils": "~55.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-3+pFun4C9F/eFMVpwZgOBrBWq5sfu7rS1uxTrcg9G7jUFatNe5W6hr+M7z7aQPDf0J1afaSudUZPawx1LLf15w=="], "expo-mcp": ["expo-mcp@0.2.4", "", { "dependencies": { "@expo/mcp-tunnel": "~0.2.3", "@modelcontextprotocol/sdk": "^1.26.0", "debug": "^4.4.3", "glob": "^11.0.3", "jimp-compact": "0.16.1", "resolve-from": "^5.0.0", "ws": "^8.18.3", "xml2js": "^0.6.2", "zod": "^3.25.76", "zx": "^8.8.1" }, "bin": { "expo-mcp": "bin/expo-mcp.mjs" } }, "sha512-rBomlm+085wNa+UF9YC3bXGZR6LlYPfOlUXwKBB5R7+dnASk0VjWFETuxyApdtXw9OItmOsAXolUxrAlEYfqSA=="], - "expo-modules-autolinking": ["expo-modules-autolinking@55.0.17", "", { "dependencies": { "@expo/require-utils": "^55.0.4", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-VhlEVGnP+xBjfSKDKNN7GAPKN2whIfV08jsZvNj7UGyJWpZYiO6Emx1FLP5xd1+JZVpIrt/kxR641kdcPo7Ehw=="], + "expo-modules-autolinking": ["expo-modules-autolinking@55.0.12", "", { "dependencies": { "@expo/require-utils": "^55.0.3", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-nZOPjpl4v5YInNftJpX10bYxDNNq2HM+hWTfr3FPE1/i0lES/cnvaB8v4XKpDTuAUdBwkGYadTfNwNG9k/Ftgw=="], - "expo-modules-core": ["expo-modules-core@55.0.22", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-NC5GyvCHvnOvi5MtgLv68oUSrRP/0UORGzU/MX+7BIA8ctgBPxKSjPXPSfhwk3gMzj7eHBhYwlu0HJsIEnVd9A=="], + "expo-modules-core": ["expo-modules-core@55.0.18", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-Qwr3qCCZd/aMtenUo6KmPaFy/uFeNz0rLfRxv0tNsWFF27XS2wjDwb87A7lD2ii8iJhjYEHVetRvFkcDxCw8Lw=="], - "expo-network": ["expo-network@55.0.13", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-7u+npCmCPRpVrjkUlQtUetPnTN1gRyj7z13bBM5w9w1AHMb4PfoxtIys5EB9ukzNYBg/gaZ/y5dtxomGpc6BKw=="], + "expo-network": ["expo-network@55.0.9", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-vuL7s+Zbsbcqh2XxhaZ45mfuYZVn7ikukL27be7hN3zkLxoABNPgbVt+/gEKOxyv2Gzr/Q5JZvfVxCuwDDh0Fg=="], - "expo-router": ["expo-router@55.0.12", "", { "dependencies": { "@expo/metro-runtime": "^55.0.9", "@expo/schema-utils": "^55.0.3", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.5", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^55.0.10", "expo-image": "^55.0.8", "expo-server": "^55.0.7", "expo-symbols": "^55.0.7", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.10", "@react-navigation/drawer": "^7.9.4", "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^55.0.13", "expo-linking": "^55.0.12", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-Bm6IhI0Kl5/tDlCHPms8jDqy1O6HLHIOrMsEmmAQ5Lgg5UBtDfRThEyHPVOLNTOs8e7/bG/Ftz6a4UgQVA+NhQ=="], + "expo-router": ["expo-router@55.0.8", "", { "dependencies": { "@expo/metro-runtime": "^55.0.7", "@expo/schema-utils": "^55.0.2", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.5", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^55.0.8", "expo-image": "^55.0.6", "expo-server": "^55.0.6", "expo-symbols": "^55.0.5", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.8", "@react-navigation/drawer": "^7.9.4", "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^55.0.9", "expo-linking": "^55.0.9", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-SG51cnmH84Htxa+vXJPw4xl10rDCrWkC/3m38Sn51Bg+9N2nPPJMhCYifAcR9ZYK6mlb2BPG1GiHVjZw78DSxQ=="], - "expo-secure-store": ["expo-secure-store@55.0.13", "", { "peerDependencies": { "expo": "*" } }, "sha512-I6r0JNO1Fd4o0Gu7Ixiic7s89lqgdUHq17uBH9y1f/AntoyKn71TdtYJH82RgfsBbu5qNVzrwImmvlANyOlITQ=="], + "expo-secure-store": ["expo-secure-store@55.0.9", "", { "peerDependencies": { "expo": "*" } }, "sha512-TIPGjM73LKlebpXwgAu/yL7lNWr6RQYmFw3vgYHOqLFYQMpsBqkQmopovbNX3c/0+RCE9KZlLAkcz8r6detILQ=="], - "expo-server": ["expo-server@55.0.7", "", {}, "sha512-Cc1btFyPsD9P4DT2xd1pG/uR96TLVMx0W+dPm9Gjk1uDV9xuzvMcUsY7nf9bt4U5pGyWWkCXmPJcKwWfdl51Pw=="], + "expo-server": ["expo-server@55.0.6", "", {}, "sha512-xI72FTm469FfuuBL2R5aNtthgH+GR7ygOpsx/KcPS0K8AZaZd7VjtEExbzn9/qyyYkWW3T+3dAmCDKOMX8gdmQ=="], - "expo-status-bar": ["expo-status-bar@55.0.5", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-qb0c3rJO2b7CC0gUVGi1JYp92oLenWdYGyk8l4YQs6U+uaXUTPv6aaFa3KkT2HON10re3AxxPNJci8rsz6kPxg=="], + "expo-status-bar": ["expo-status-bar@55.0.4", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-BPDjUXKqv1F9j2YNGLRZfkBEZXIEEpqj+t81y4c+4fdSN3Pos7goIHXgcl2ozbKQLgKRZQyNZQtbUgh5UjHYUQ=="], - "expo-symbols": ["expo-symbols@55.0.7", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-y4ALLbncSGQzhFLw1PaIBbO39xzaw3ie249HmK6zK/WLJYfw4Z/9UU4iPKO3KCE4FyCKIzd+yRsvzvlri23YrQ=="], + "expo-symbols": ["expo-symbols@55.0.5", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-W/QYRvnYVes947ZYOHtuKL8Gobs7BUjeu9oknzbo4jGnou7Ks6bj1CwdT0ZWNBgaTopbS4/POXumJIkW4cTPSQ=="], - "expo-system-ui": ["expo-system-ui@55.0.15", "", { "dependencies": { "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-hnpYpXgm1sXDb46yb7RB+Iq9z44wtDuFOYC8m2pfBNj3Dnv5xnh3CL2N4CpAbLZPwMSBrNk9Opkb9VFwn1FM6A=="], + "expo-system-ui": ["expo-system-ui@55.0.11", "", { "dependencies": { "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-ZxcR9/BtL+fkKp1KPPLLc8xgvbqRcyYg+Drf3XjonY/bHIHiyZY1RLnVLxY1wSpFEly5pJkS9erspFok1ES5dQ=="], - "expo-updates-interface": ["expo-updates-interface@55.1.5", "", { "peerDependencies": { "expo": "*" } }, "sha512-YOk9vhplWi0djoeqxMlEQgcDFeOGhnj4dWU0v1QvF5RqpqwLGdx780E0k3zL85xw6LXljVN78d6g8z51qIZu5g=="], + "expo-updates-interface": ["expo-updates-interface@55.1.3", "", { "peerDependencies": { "expo": "*" } }, "sha512-UVVIiZqymQZJL+o/jh65kXOI97xdkbqBJJM0LMabaPMNLFnc6/WvOMOzmQs7SPyKb8+0PeBaFd7tj5DzF6JeQg=="], - "expo-web-browser": ["expo-web-browser@55.0.14", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-bTDkBSQBnrlnYcM7Aak72AOvJuvdgA3M8p//Lazrm0Nfa77T9cRXzQ6KhLrB08V39n1+00d1dvuTWznJslkmdg=="], + "expo-web-browser": ["expo-web-browser@55.0.10", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-2d6qVrg/nt0JvW5uAqOMDG/xITIXFe1Prkq1ri+I3PrC0QmV5cMYNSagU9ykfC8S7YKWxF1qO7Qsih9fxNa9dw=="], "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], - "express-rate-limit": ["express-rate-limit@8.3.2", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg=="], + "express-rate-limit": ["express-rate-limit@8.3.1", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw=="], "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], @@ -4161,9 +3924,7 @@ "fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="], - "fast-copy": ["fast-copy@4.0.3", "", {}, "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw=="], - - "fast-csv": ["fast-csv@4.3.6", "", { "dependencies": { "@fast-csv/format": "4.3.5", "@fast-csv/parse": "4.3.6" } }, "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw=="], + "fast-copy": ["fast-copy@4.0.2", "", {}, "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -4181,9 +3942,9 @@ "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - "fast-xml-builder": ["fast-xml-builder@1.1.5", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA=="], + "fast-xml-builder": ["fast-xml-builder@1.1.4", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg=="], - "fast-xml-parser": ["fast-xml-parser@5.7.1", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.5", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA=="], + "fast-xml-parser": ["fast-xml-parser@5.5.11", "", { "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.4.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-QL0eb0YbSTVWF6tTf1+LEMSgtCEjBYPpnAjoLC8SscESlAjXEIRJ7cHtLG0pLeDFaZLa4VKZLArtA/60ZS7vyA=="], "fastembed": ["fastembed@2.1.0", "", { "dependencies": { "@anush008/tokenizers": "^0.0.0", "@huggingface/hub": "^2.7.1", "onnxruntime-node": "1.21.0", "progress": "^2.0.3", "tar": "^6.2.0" } }, "sha512-oQkpcRHBppJ3+a3w9dU0uytSY0N1cnEa/iVMc8AXEd+tvT529GekOEFhNviJy89R3lvQXF6cdIMTXHj1Gi00xQ=="], @@ -4225,7 +3986,7 @@ "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="], - "follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], + "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="], @@ -4263,8 +4024,6 @@ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "fstream": ["fstream@1.0.12", "", { "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" } }, "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg=="], - "fumadocs-core": ["fumadocs-core@16.4.7", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.7.5", "@orama/orama": "^3.1.18", "@shikijs/rehype": "^3.21.0", "@shikijs/transformers": "^3.21.0", "estree-util-value-to-estree": "^3.5.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "image-size": "^2.0.2", "negotiator": "^1.0.0", "npm-to-yarn": "^3.0.1", "path-to-regexp": "^8.3.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", "shiki": "^3.21.0", "tinyglobby": "^0.2.15", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "@mixedbread/sdk": "^0.46.0", "@orama/core": "1.x.x", "@oramacloud/client": "2.x.x", "@tanstack/react-router": "1.x.x", "@types/react": "*", "algoliasearch": "5.x.x", "lucide-react": "*", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", "react-router": "7.x.x", "waku": "^0.26.0 || ^0.27.0", "zod": "4.x.x" }, "optionalPeers": ["@mixedbread/sdk", "@orama/core", "@oramacloud/client", "@tanstack/react-router", "@types/react", "algoliasearch", "lucide-react", "next", "react", "react-dom", "react-router", "waku", "zod"] }, "sha512-oEsoha5EjyQnhRb6s5tNYEM+AiDA4BN80RyevRohsKPXGRQ2K3ddMaFAQq5kBaqA/Xxb+vqrElyRtzmdif7w2A=="], "fumadocs-mdx": ["fumadocs-mdx@14.2.5", "", { "dependencies": { "@mdx-js/mdx": "^3.1.1", "@standard-schema/spec": "^1.1.0", "chokidar": "^5.0.0", "esbuild": "^0.27.2", "estree-util-value-to-estree": "^3.5.0", "js-yaml": "^4.1.1", "mdast-util-to-markdown": "^2.1.2", "picocolors": "^1.1.1", "picomatch": "^4.0.3", "remark-mdx": "^3.1.1", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3", "zod": "^4.3.5" }, "peerDependencies": { "@fumadocs/mdx-remote": "^1.4.0", "@types/react": "*", "fumadocs-core": "^15.0.0 || ^16.0.0", "next": "^15.3.0 || ^16.0.0", "react": "*", "vite": "6.x.x || 7.x.x" }, "optionalPeers": ["@fumadocs/mdx-remote", "@types/react", "next", "react", "vite"], "bin": { "fumadocs-mdx": "dist/bin.js" } }, "sha512-1WJeJ1Xago2lRq6GhTvTb+hxDtWUBr7lHi4YgHNBYSpWKsTfOor3UxgZV1UYBrd32cq4xHdtMK33LM67gA0eBA=="], @@ -4273,7 +4032,7 @@ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "fuse.js": ["fuse.js@7.3.0", "", {}, "sha512-plz8RVjfcDedTGfVngWH1jmJvBvAwi1v2jecfDerbEnMcmOYUEEwKFTHbNoCiYyzaK2Ws8lABkTCcRSqCY1q4w=="], + "fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="], "gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="], @@ -4301,7 +4060,7 @@ "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], - "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], + "get-tsconfig": ["get-tsconfig@4.13.7", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q=="], "get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="], @@ -4339,17 +4098,7 @@ "grapheme-splitter": ["grapheme-splitter@1.0.4", "", {}, "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="], - "graphql": ["graphql@16.13.2", "", {}, "sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig=="], - - "graphql-config": ["graphql-config@5.0.3", "", { "dependencies": { "@graphql-tools/graphql-file-loader": "^8.0.0", "@graphql-tools/json-file-loader": "^8.0.0", "@graphql-tools/load": "^8.0.0", "@graphql-tools/merge": "^9.0.0", "@graphql-tools/url-loader": "^8.0.0", "@graphql-tools/utils": "^10.0.0", "cosmiconfig": "^8.1.0", "jiti": "^1.18.2", "minimatch": "^4.2.3", "string-env-interpolation": "^1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "cosmiconfig-toml-loader": "^1.0.0", "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" }, "optionalPeers": ["cosmiconfig-toml-loader"] }, "sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ=="], - - "graphql-language-service": ["graphql-language-service@5.5.0", "", { "dependencies": { "debounce-promise": "^3.1.2", "nullthrows": "^1.0.0", "vscode-languageserver-types": "^3.17.1" }, "peerDependencies": { "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" }, "bin": { "graphql": "dist/temp-bin.js" } }, "sha512-9EvWrLLkF6Y5e29/2cmFoAO6hBPPAZlCyjznmpR11iFtRydfkss+9m6x+htA8h7YznGam+TtJwS6JuwoWWgb2Q=="], - - "graphql-language-service-cli": ["graphql-language-service-cli@3.5.0", "", { "dependencies": { "@babel/polyfill": "^7.12.1", "@types/yargs": "16.0.5", "graphql-language-service": "^5.3.0", "graphql-language-service-server": "^2.14.0", "yargs": "^16.2.0" }, "peerDependencies": { "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0-alpha.2" }, "bin": { "graphql-lsp": "bin/graphql.js" } }, "sha512-H8QakLrpub/lrUrvxeiubOMTNWuM1Z9ntwk2YlRS3II6Rz3LnwzO4ZYsKVTplrEQkG8HqYkbOOo1CbXyGRdQWA=="], - - "graphql-language-service-server": ["graphql-language-service-server@2.14.8", "", { "dependencies": { "@astrojs/compiler": "^2.10.1", "@babel/parser": "^7.23.6", "@babel/types": "^7.23.5", "@graphql-tools/code-file-loader": "8.0.3", "cosmiconfig-toml-loader": "^1.0.0", "dotenv": "10.0.0", "fast-glob": "^3.2.7", "glob": "^7.2.0", "graphql-config": "5.0.3", "graphql-language-service": "^5.3.1", "lru-cache": "^10.2.0", "mkdirp": "^1.0.4", "node-abort-controller": "^3.0.1", "nullthrows": "^1.0.0", "source-map-js": "1.0.2", "svelte": "^4.2.19", "svelte2tsx": "^0.7.0", "typescript": "^5.3.3", "vscode-jsonrpc": "^8.0.1", "vscode-languageserver": "^8.0.1", "vscode-languageserver-types": "^3.17.2", "vscode-uri": "^3.0.2", "vue": "^3.2.0" }, "peerDependencies": { "graphql": "^16.0.0" } }, "sha512-fcfkjr4rDIOeaJw/oyXl/vlPrP4FNz+h8v6x2VhuMm2kV9FuiIOBGLPcrB2kp1xp/qVICYqdI/uKuGBghrSHOA=="], - - "graphql-ws": ["graphql-ws@6.0.8", "", { "peerDependencies": { "@fastify/websocket": "^10 || ^11", "crossws": "~0.3", "graphql": "^15.10.1 || ^16", "ws": "^8" }, "optionalPeers": ["@fastify/websocket", "crossws", "ws"] }, "sha512-m3EOaNsUBXwAnkBWbzPfe0Nq8pXUfxsWnolC54sru3FzHvhTZL0Ouf/BoQsaGAXqM+YPerXOJ47BUnmgmoupCw=="], + "graphql": ["graphql@15.10.2", "", {}, "sha512-1PRqdDPAmViWr4h1GVBT8RoPZfWSGZa7kDzleTilOfVIslsgf+cia3Nl95v1KDmR4iERPaT7WzQ+tN4MJmbg3w=="], "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], @@ -4363,7 +4112,7 @@ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="], + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], @@ -4397,8 +4146,6 @@ "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], "hermes-compiler": ["hermes-compiler@0.14.0", "", {}, "sha512-clxa193o+GYYwykWVFfpHduCATz8fR5jvU7ngXpfKHj+E9hr9vjLNtdLSEe8MUbObvVexV3wcyxQ00xTPIrB1Q=="], @@ -4411,18 +4158,16 @@ "highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="], - "hls.js": ["hls.js@1.6.16", "", {}, "sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA=="], + "hls.js": ["hls.js@1.6.15", "", {}, "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA=="], "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], - "hono": ["hono@4.12.14", "", {}, "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w=="], + "hono": ["hono@4.12.9", "", {}, "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA=="], "hono-openapi": ["hono-openapi@1.3.0", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.8.3", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-xDvCWpWEIv0weEmnl3EjRQzqbHIO8LnfzMuYOCmbuyE5aes6aXxLg4vM3ybnoZD5TiTUkA6PuRQPJs3R7WRBig=="], "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], - "html-to-image": ["html-to-image@1.11.13", "", {}, "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg=="], - "html-to-text": ["html-to-text@9.0.5", "", { "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", "dom-serializer": "^2.0.0", "htmlparser2": "^8.0.2", "selderee": "^0.11.0" } }, "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg=="], "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], @@ -4467,8 +4212,6 @@ "immutability-helper": ["immutability-helper@3.1.1", "", {}, "sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ=="], - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - "import-in-the-middle": ["import-in-the-middle@2.0.1", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bruMpJ7xz+9jwGzrwEhWgvRrlKRYCRDBrfU+ur3FcasYXLJDxTruJ//8g2Noj+QFyRBeqbpj8Bhn4Fbw6HjvhA=="], "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], @@ -4559,12 +4302,10 @@ "isbinaryfile": ["isbinaryfile@5.0.7", "", {}, "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ=="], - "isbot": ["isbot@5.1.39", "", {}, "sha512-obH0yYahGXdzNxo+djmHhBYThUKDkz565cxkIlt2L9hXfv1NlaLKoDBHo6KxXsYrIXx2RK3x5vY36CfZcobxEw=="], + "isbot": ["isbot@5.1.36", "", {}, "sha512-C/ZtXyJqDPZ7G7JPr06ApWyYoHjYexQbS6hPYD4WYCzpv2Qes6Z+CCEfTX4Owzf+1EJ933PoI2p+B9v7wpGZBQ=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "isomorphic-ws": ["isomorphic-ws@5.0.0", "", { "peerDependencies": { "ws": "*" } }, "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw=="], - "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], "istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="], @@ -4625,7 +4366,7 @@ "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], - "json-schema-to-zod": ["json-schema-to-zod@2.8.1", "", { "bin": { "json-schema-to-zod": "dist/cjs/cli.js" } }, "sha512-fRr1mHgZ7hboLKBUdR428gd9dIHUFGivUqOeiDcSmyXkNZCtB1uGaZLvsjZ4GaN5pwBIs+TGIOf6s+Rp5/R/zA=="], + "json-schema-to-zod": ["json-schema-to-zod@2.8.0", "", { "bin": { "json-schema-to-zod": "dist/cjs/cli.js" } }, "sha512-0c5uztkkxXEMIofz1Ia06eNZp9uZSFgz//+pd4biGSY1wxkwdVLWKf6njIPcBFO8P/Ic2np6ArpHNNMELHd5OA=="], "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], @@ -4637,8 +4378,6 @@ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="], @@ -4647,7 +4386,7 @@ "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], - "katex": ["katex@0.16.45", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA=="], + "katex": ["katex@0.16.44", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ=="], "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], @@ -4657,13 +4396,13 @@ "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], - "koffi": ["koffi@2.16.0", "", {}, "sha512-h/2NJueOKWd0YYycEOWDspomizgNfuOKf/V7ZE2fytvuRtHoY9Tb+y4x6GJ6pFqaVndWn9dLK+sCI14eWtu5rA=="], + "koffi": ["koffi@2.15.2", "", {}, "sha512-r9tjJLVRSOhCRWdVyQlF3/Ugzeg13jlzS4czS82MAgLff4W+BcYOW7g8Y62t9O5JYjYOLAjAovAZDNlDfZNu+g=="], - "kysely": ["kysely@0.28.16", "", {}, "sha512-3i5pmOiZvMDj00qhrIVbH0AnioVTx22DMP7Vn5At4yJO46iy+FM8Y/g61ltenLVSo3fiO8h8Q3QOFgf/gQ72ww=="], + "kysely": ["kysely@0.28.14", "", {}, "sha512-SU3lgh0rPvq7upc6vvdVrCsSMUG1h3ChvHVOY7wJ2fw4C9QEB7X3d5eyYEyULUX7UQtxZJtZXGuT6U2US72UYA=="], - "lan-network": ["lan-network@0.2.1", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A=="], + "lan-network": ["lan-network@0.2.0", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-EZgbsXMrGS+oK+Ta12mCjzBFse+SIewGdwrSTr5g+MSymnjpox2x05ceI20PQejJOFvOgzcXrfDk/SdY7dSCtw=="], - "langium": ["langium@4.2.2", "", { "dependencies": { "@chevrotain/regexp-to-ast": "~12.0.0", "chevrotain": "~12.0.0", "chevrotain-allstar": "~0.4.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.1.0" } }, "sha512-JUshTRAfHI4/MF9dH2WupvjSXyn8JBuUEWazB8ZVJUtXutT0doDlAv1XKbZ1Pb5sMexa8FF4CFBc0iiul7gbUQ=="], + "langium": ["langium@4.2.1", "", { "dependencies": { "chevrotain": "~11.1.1", "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.1.0" } }, "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ=="], "langsmith": ["langsmith@0.3.87", "", { "dependencies": { "@types/uuid": "^10.0.0", "chalk": "^4.1.2", "console-table-printer": "^2.12.1", "p-queue": "^6.6.2", "semver": "^7.6.3", "uuid": "^10.0.0" }, "peerDependencies": { "@opentelemetry/api": "*", "@opentelemetry/exporter-trace-otlp-proto": "*", "@opentelemetry/sdk-trace-base": "*", "openai": "*" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/exporter-trace-otlp-proto", "@opentelemetry/sdk-trace-base", "openai"] }, "sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q=="], @@ -4713,27 +4452,21 @@ "line-column-path": ["line-column-path@3.0.0", "", { "dependencies": { "type-fest": "^2.0.0" } }, "sha512-Atocnm7Wr9nuvAn97yEPQa3pcQI5eLQGBz+m6iTb+CVw+IOzYB9MrYK7jI7BfC9ISnT4Fu0eiwhAScV//rp4Hw=="], - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], "linkifyjs": ["linkifyjs@4.3.2", "", {}, "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA=="], - "listenercount": ["listenercount@1.0.1", "", {}, "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="], - "load-json-file": ["load-json-file@7.0.1", "", {}, "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ=="], "loader-runner": ["loader-runner@4.3.1", "", {}, "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q=="], "locate-app": ["locate-app@2.5.0", "", { "dependencies": { "@promptbook/utils": "0.69.5", "type-fest": "4.26.0", "userhome": "1.0.1" } }, "sha512-xIqbzPMBYArJRmPGUZD9CzV9wOqmVtQnaAn3wrj3s6WYW0bQvPI7x+sPYUGmDTYMHefVK//zc6HEYZ1qnxIK+Q=="], - "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - "lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="], + "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], - "lodash-es": ["lodash-es@4.18.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="], + "lodash-es": ["lodash-es@4.17.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="], "lodash.chunk": ["lodash.chunk@4.2.0", "", {}, "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="], @@ -4741,38 +4474,16 @@ "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], - "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], - - "lodash.difference": ["lodash.difference@4.5.0", "", {}, "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="], - "lodash.escaperegexp": ["lodash.escaperegexp@4.1.2", "", {}, "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="], - "lodash.flatten": ["lodash.flatten@4.4.0", "", {}, "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="], - - "lodash.groupby": ["lodash.groupby@4.6.0", "", {}, "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw=="], - - "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], - "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="], - "lodash.isfunction": ["lodash.isfunction@3.0.9", "", {}, "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw=="], - - "lodash.isnil": ["lodash.isnil@4.0.0", "", {}, "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng=="], - - "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], - - "lodash.isundefined": ["lodash.isundefined@3.0.1", "", {}, "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA=="], - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "lodash.samplesize": ["lodash.samplesize@4.2.0", "", {}, "sha512-1ZhKV7/nuISuaQdxfCqrs4HHxXIYN+0Z4f7NMQn2PHkxFZJGavJQ1j/paxyJnLJmN2ZamNN6SMepneV+dCgQTA=="], "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="], - "lodash.union": ["lodash.union@4.6.0", "", {}, "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="], - - "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], - "lodash.zip": ["lodash.zip@4.2.0", "", {}, "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg=="], "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], @@ -4793,7 +4504,7 @@ "lowlight": ["lowlight@3.3.0", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.0.0", "highlight.js": "~11.11.0" } }, "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ=="], - "lru-cache": ["lru-cache@11.3.5", "", {}, "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw=="], + "lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], @@ -4801,8 +4512,6 @@ "lucide-react-native": ["lucide-react-native@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-native": "*", "react-native-svg": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0" } }, "sha512-ZF2ok8SzyUaiCIrLGqYh/6SPs+huVzbZOCv0i411L4+oP3tJgQvvKePiVgWCioa7HsT2xaJZSrdd92cuB2/+ew=="], - "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], - "maath": ["maath@0.10.8", "", { "peerDependencies": { "@types/three": ">=0.134.0", "three": ">=0.134.0" } }, "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], @@ -4821,7 +4530,7 @@ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], - "marked": ["marked@17.0.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA=="], + "marked": ["marked@17.0.5", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg=="], "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="], @@ -4829,7 +4538,7 @@ "matcher": ["matcher@5.0.0", "", { "dependencies": { "escape-string-regexp": "^5.0.0" } }, "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw=="], - "material-icon-theme": ["material-icon-theme@5.33.1", "", { "dependencies": { "chroma-js": "^3.1.2", "events": "^3.3.0", "fast-deep-equal": "^3.1.3", "svgson": "^5.3.1" } }, "sha512-imiILyUW/Y6YvxbobfReC4PpzjPfpMTUiiH9gN5sloQ3dJAhfJRE40l2q8pMT8+V4xRHiIZ5vaZtJw4D03qduQ=="], + "material-icon-theme": ["material-icon-theme@5.32.0", "", { "dependencies": { "chroma-js": "^3.1.2", "events": "^3.3.0", "fast-deep-equal": "^3.1.3", "svgson": "^5.3.1" } }, "sha512-SxJxCcnk6cJIbd+AxmoeghXJ24joXGmUzjiGci16sX4mXZdXprGEzM6ZZ0VHGAofxNlMqznEbExINwFLsxf8eQ=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], @@ -4885,9 +4594,7 @@ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - "mermaid": ["mermaid@11.14.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.1.0", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.1", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.19", "dompurify": "^3.3.1", "katex": "^0.16.25", "khroma": "^2.1.0", "lodash-es": "^4.17.23", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g=="], - - "meros": ["meros@1.3.2", "", { "peerDependencies": { "@types/node": ">=13" }, "optionalPeers": ["@types/node"] }, "sha512-Q3mobPbvEx7XbwhnC1J1r60+5H6EZyNccdzSz0eGexJRwouUtTZxPVRGdqKtxlpD84ScK4+tIGldkqDtCKdI0A=="], + "mermaid": ["mermaid@11.13.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.0.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.1", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.19", "dompurify": "^3.3.1", "katex": "^0.16.25", "khroma": "^2.1.0", "lodash-es": "^4.17.23", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-fEnci+Immw6lKMFI8sqzjlATTyjLkRa6axrEgLV2yHTfv8r+h1wjFbV6xeRtd4rUV1cS4EpR9rwp3Rci7TRWDw=="], "meshline": ["meshline@3.3.1", "", { "peerDependencies": { "three": ">=0.137" } }, "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ=="], @@ -4895,33 +4602,33 @@ "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], - "metro": ["metro@0.83.5", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.33.3", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-config": "0.83.5", "metro-core": "0.83.5", "metro-file-map": "0.83.5", "metro-resolver": "0.83.5", "metro-runtime": "0.83.5", "metro-source-map": "0.83.5", "metro-symbolicate": "0.83.5", "metro-transform-plugins": "0.83.5", "metro-transform-worker": "0.83.5", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-BgsXevY1MBac/3ZYv/RfNFf/4iuW9X7f4H8ZNkiH+r667HD9sVujxcmu4jvEzGCAm4/WyKdZCuyhAcyhTHOucQ=="], + "metro": ["metro@0.83.3", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.32.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q=="], - "metro-babel-transformer": ["metro-babel-transformer@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.33.3", "nullthrows": "^1.1.1" } }, "sha512-d9FfmgUEVejTiSb7bkQeLRGl6aeno2UpuPm3bo3rCYwxewj03ymvOn8s8vnS4fBqAPQ+cE9iQM40wh7nGXR+eA=="], + "metro-babel-transformer": ["metro-babel-transformer@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g=="], - "metro-cache": ["metro-cache@0.83.5", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.5" } }, "sha512-oH+s4U+IfZyg8J42bne2Skc90rcuESIYf86dYittcdWQtPfcaFXWpByPyTuWk3rR1Zz3Eh5HOrcVImfEhhJLng=="], + "metro-cache": ["metro-cache@0.83.3", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.3" } }, "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q=="], - "metro-cache-key": ["metro-cache-key@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Ycl8PBajB7bhbAI7Rt0xEyiF8oJ0RWX8EKkolV1KfCUlC++V/GStMSGpPLwnnBZXZWkCC5edBPzv1Hz1Yi0Euw=="], + "metro-cache-key": ["metro-cache-key@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw=="], - "metro-config": ["metro-config@0.83.5", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.5", "metro-cache": "0.83.5", "metro-core": "0.83.5", "metro-runtime": "0.83.5", "yaml": "^2.6.1" } }, "sha512-JQ/PAASXH7yczgV6OCUSRhZYME+NU8NYjI2RcaG5ga4QfQ3T/XdiLzpSb3awWZYlDCcQb36l4Vl7i0Zw7/Tf9w=="], + "metro-config": ["metro-config@0.83.3", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.3", "metro-cache": "0.83.3", "metro-core": "0.83.3", "metro-runtime": "0.83.3", "yaml": "^2.6.1" } }, "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA=="], - "metro-core": ["metro-core@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.5" } }, "sha512-YcVcLCrf0ed4mdLa82Qob0VxYqfhmlRxUS8+TO4gosZo/gLwSvtdeOjc/Vt0pe/lvMNrBap9LlmvZM8FIsMgJQ=="], + "metro-core": ["metro-core@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.3" } }, "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw=="], - "metro-file-map": ["metro-file-map@0.83.5", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-ZEt8s3a1cnYbn40nyCD+CsZdYSlwtFh2kFym4lo+uvfM+UMMH+r/BsrC6rbNClSrt+B7rU9T+Te/sh/NL8ZZKQ=="], + "metro-file-map": ["metro-file-map@0.83.3", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA=="], - "metro-minify-terser": ["metro-minify-terser@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Toe4Md1wS1PBqbvB0cFxBzKEVyyuYTUb0sgifAZh/mSvLH84qA1NAWik9sISWatzvfWf3rOGoUoO5E3f193a3Q=="], + "metro-minify-terser": ["metro-minify-terser@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ=="], - "metro-resolver": ["metro-resolver@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-7p3GtzVUpbAweJeCcUJihJeOQl1bDuimO5ueo1K0BUpUtR41q5EilbQ3klt16UTPPMpA+tISWBtsrqU556mY1A=="], + "metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="], - "metro-runtime": ["metro-runtime@0.83.6", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-WQPua1G2VgYbwRn6vSKxOhTX7CFbSf/JdUu6Nd8bZnPXckOf7HQ2y51NXNQHoEsiuawathrkzL8pBhv+zgZFmg=="], + "metro-runtime": ["metro-runtime@0.83.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA=="], - "metro-source-map": ["metro-source-map@0.83.6", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.6", "nullthrows": "^1.1.1", "ob1": "0.83.6", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-AqJbOMMpeyyM4iNI91pchqDIszzNuuHApEhg6OABqZ+9mjLEqzcIEQ/fboZ7x74fNU5DBd2K36FdUQYPqlGClA=="], + "metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], - "metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="], + "metro-symbolicate": ["metro-symbolicate@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw=="], - "metro-transform-plugins": ["metro-transform-plugins@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-KxYKzZL+lt3Os5H2nx7YkbkWVduLZL5kPrE/Yq+Prm/DE1VLhpfnO6HtPs8vimYFKOa58ncl60GpoX0h7Wm0Vw=="], + "metro-transform-plugins": ["metro-transform-plugins@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A=="], - "metro-transform-worker": ["metro-transform-worker@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.83.5", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-minify-terser": "0.83.5", "metro-source-map": "0.83.5", "metro-transform-plugins": "0.83.5", "nullthrows": "^1.1.1" } }, "sha512-8N4pjkNXc6ytlP9oAM6MwqkvUepNSW39LKYl9NjUMpRDazBQ7oBpQDc8Sz4aI8jnH6AGhF7s1m/ayxkN1t04yA=="], + "metro-transform-worker": ["metro-transform-worker@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-minify-terser": "0.83.3", "metro-source-map": "0.83.3", "metro-transform-plugins": "0.83.3", "nullthrows": "^1.1.1" } }, "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA=="], "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], @@ -5007,9 +4714,9 @@ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], - "miniflare": ["miniflare@4.20260415.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.8", "workerd": "1.20260415.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-JoExRWN4YBI2luA5BoSMFEgi8rQWXUGzo3mtE+58VXCLV3jj/Xnk5Yeqs/IXWz8Es5GJIaq6BtsixDvAxXSIng=="], + "miniflare": ["miniflare@4.20260317.3", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.4", "workerd": "1.20260317.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-tK78D3X4q30/SXqVwMhWrUfH+ffRou9dJLC+jkhNy5zh1I7i7T4JH6xihOvYxdCSBavJ5fQXaaxDJz6orh09BA=="], - "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -5047,15 +4754,15 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "multitars": ["multitars@0.2.5", "", {}, "sha512-T/i4uZOzd4j2VnS28eAOJS0MgeAbcsFIijRPeLRhVv54hP9OqsC/FjYK0JmMTWxGhF2fv34oH1mtR6XLBKkNlw=="], + "multitars": ["multitars@0.2.4", "", {}, "sha512-XgLbg1HHchFauMCQPRwMj6MSyDd5koPlTA1hM3rUFkeXzGpjU/I9fP3to7yrObE9jcN8ChIOQGrM0tV0kUZaKg=="], "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - "nanoid": ["nanoid@5.1.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw=="], + "nanoid": ["nanoid@5.1.7", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ=="], - "nanostores": ["nanostores@1.3.0", "", {}, "sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA=="], + "nanostores": ["nanostores@1.2.0", "", {}, "sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg=="], "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], @@ -5065,11 +4772,11 @@ "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], - "netmask": ["netmask@2.1.1", "", {}, "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA=="], + "netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="], "neverthrow": ["neverthrow@7.2.0", "", {}, "sha512-iGBUfFB7yPczHHtA8dksKTJ9E8TESNTAx1UQWW6TzMF280vo9jdPYpLUXrMN1BCkPdHFdNG3fxOt2CUad8KhAw=="], - "next": ["next@16.2.4", "", { "dependencies": { "@next/env": "16.2.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.4", "@next/swc-darwin-x64": "16.2.4", "@next/swc-linux-arm64-gnu": "16.2.4", "@next/swc-linux-arm64-musl": "16.2.4", "@next/swc-linux-x64-gnu": "16.2.4", "@next/swc-linux-x64-musl": "16.2.4", "@next/swc-win32-arm64-msvc": "16.2.4", "@next/swc-win32-x64-msvc": "16.2.4", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-kPvz56wF5frc+FxlHI5qnklCzbq53HTwORaWBGdT0vNoKh1Aya9XC8aPauH4NJxqtzbWsS5mAbctm4cr+EkQ2Q=="], + "next": ["next@16.2.1", "", { "dependencies": { "@next/env": "16.2.1", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.2.1", "@next/swc-darwin-x64": "16.2.1", "@next/swc-linux-arm64-gnu": "16.2.1", "@next/swc-linux-arm64-musl": "16.2.1", "@next/swc-linux-x64-gnu": "16.2.1", "@next/swc-linux-x64-musl": "16.2.1", "@next/swc-win32-arm64-msvc": "16.2.1", "@next/swc-win32-x64-msvc": "16.2.1", "sharp": "^0.34.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q=="], "next-mdx-remote": ["next-mdx-remote@6.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ=="], @@ -5077,8 +4784,6 @@ "node-abi": ["node-abi@3.89.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA=="], - "node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="], - "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], "node-api-version": ["node-api-version@0.2.1", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q=="], @@ -5093,13 +4798,11 @@ "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], - "node-html-parser": ["node-html-parser@6.1.13", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg=="], - "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="], "node-pty": ["node-pty@1.1.0", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg=="], - "node-releases": ["node-releases@2.0.37", "", {}, "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg=="], + "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], "node-simctl": ["node-simctl@7.7.5", "", { "dependencies": { "@appium/logger": "^1.3.0", "asyncbox": "^3.0.0", "bluebird": "^3.5.1", "lodash": "^4.2.1", "rimraf": "^5.0.0", "semver": "^7.0.0", "source-map-support": "^0.x", "teen_process": "^2.2.0", "uuid": "^11.0.1", "which": "^5.0.0" } }, "sha512-lWflzDW9xLuOOvR6mTJ9efbDtO/iSCH6rEGjxFxTV0vGgz5XjoZlW2BkNCCZib0B6Y23tCOiYhYJaMQYB8FKIQ=="], @@ -5123,7 +4826,7 @@ "nypm": ["nypm@0.6.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^2.0.0", "tinyexec": "^0.3.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg=="], - "ob1": ["ob1@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-m/xZYkwcjo6UqLMrUICEB3iHk7Bjt3RSR7KXMi6Y1MO/kGkPhoRmfUDF6KAan3rLAZ7ABRqnQyKUTwaqZgUV4w=="], + "ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -5197,12 +4900,8 @@ "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], - "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], "parse-numeric-range": ["parse-numeric-range@1.3.0", "", {}, "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="], @@ -5221,13 +4920,13 @@ "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], - "patchright-core": ["patchright-core@1.59.4", "", { "bin": { "patchright-core": "cli.js" } }, "sha512-7/vyX0XK0cpGKlcnUD+Rhjv5o9rrmZQl4v/NI+EUBed+VaU5EORpkOF0Gdi+fP698fLhY0tXwacKBUqKE38jQA=="], + "patchright-core": ["patchright-core@1.59.3", "", { "bin": { "patchright-core": "cli.js" } }, "sha512-EXq8a3nOoiubBtM77W9vYJDP/nFBuGaQK5CAzkaCr9/PTU5DPT1PDW0mDLdeX0P7bzSUgXEHiogHlC4zK2qSzw=="], "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - "path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="], + "path-expression-matcher": ["path-expression-matcher@1.4.0", "", {}, "sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], @@ -5237,7 +4936,7 @@ "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], + "path-to-regexp": ["path-to-regexp@8.4.0", "", {}, "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg=="], "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], @@ -5249,8 +4948,6 @@ "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], - "periscopic": ["periscopic@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } }, "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw=="], - "pg": ["pg@8.20.0", "", { "dependencies": { "pg-connection-string": "^2.12.0", "pg-pool": "^3.13.0", "pg-protocol": "^1.13.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA=="], "pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="], @@ -5307,7 +5004,7 @@ "portfinder": ["portfinder@1.0.38", "", { "dependencies": { "async": "^3.2.6", "debug": "^4.3.6" } }, "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg=="], - "postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="], + "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], "postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], @@ -5321,19 +5018,19 @@ "posthog-js": ["posthog-js@1.310.1", "", { "dependencies": { "@posthog/core": "1.9.0", "core-js": "^3.38.1", "fflate": "^0.4.8", "preact": "^10.19.3", "web-vitals": "^4.2.4" } }, "sha512-UkR6zzlWNtqHDXHJl2Yk062DOmZyVKTPL5mX4j4V+u3RiYbMHJe47+PpMMUsvK1R2e1r/m9uSlHaJMJRzyUjGg=="], - "posthog-node": ["posthog-node@5.29.2", "", { "dependencies": { "@posthog/core": "1.25.2" }, "peerDependencies": { "rxjs": "^7.0.0" }, "optionalPeers": ["rxjs"] }, "sha512-rI7kkF0XqDc0G1qjx+Hb4iuY9NAlL+XQNoGOpnEpRNTUcXvjY6WlsRGZ9m2whgc39emrrYdszi/YT8wZkr2xsg=="], + "posthog-node": ["posthog-node@5.28.8", "", { "dependencies": { "@posthog/core": "1.24.3" }, "peerDependencies": { "rxjs": "^7.0.0" }, "optionalPeers": ["rxjs"] }, "sha512-UD55SdSbgUvoOb3HkvNC22ZgpdeNknDrao8+yYTB/rDnwgaibPB7pJJzgn4j7MIUw7DOTEHEmJRqza1EDtK2Zw=="], - "posthog-react-native": ["posthog-react-native@4.42.1", "", { "dependencies": { "@posthog/core": "1.25.2" }, "peerDependencies": { "@react-native-async-storage/async-storage": ">=1.0.0", "@react-navigation/native": ">= 5.0.0", "expo-application": ">= 4.0.0", "expo-device": ">= 4.0.0", "expo-file-system": ">= 13.0.0", "expo-localization": ">= 11.0.0", "posthog-react-native-session-replay": ">= 1.5.4", "react-native-device-info": ">= 10.0.0", "react-native-localize": ">= 3.0.0", "react-native-navigation": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-svg": ">= 15.0.0" }, "optionalPeers": ["@react-native-async-storage/async-storage", "@react-navigation/native", "expo-application", "expo-device", "expo-file-system", "expo-localization", "posthog-react-native-session-replay", "react-native-device-info", "react-native-localize", "react-native-navigation", "react-native-safe-area-context"] }, "sha512-uthbnPjXkbz6afB+X3N8gYConph++fkLSL66VrEjP0+T8sBwhHyjkZl0IZLJentYml8jW2VyKX6FLDN0pfi/dw=="], + "posthog-react-native": ["posthog-react-native@4.39.0", "", { "dependencies": { "@posthog/core": "1.24.3" }, "peerDependencies": { "@react-native-async-storage/async-storage": ">=1.0.0", "@react-navigation/native": ">= 5.0.0", "expo-application": ">= 4.0.0", "expo-device": ">= 4.0.0", "expo-file-system": ">= 13.0.0", "expo-localization": ">= 11.0.0", "posthog-react-native-session-replay": ">= 1.5.0", "react-native-device-info": ">= 10.0.0", "react-native-localize": ">= 3.0.0", "react-native-navigation": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-svg": ">= 15.0.0" }, "optionalPeers": ["@react-native-async-storage/async-storage", "@react-navigation/native", "expo-application", "expo-device", "expo-file-system", "expo-localization", "posthog-react-native-session-replay", "react-native-device-info", "react-native-localize", "react-native-navigation", "react-native-safe-area-context"] }, "sha512-hFVI+udE1QjJ719Qnkn3EEAibZS3Pg94oTDnz0xcxi38FUPwU4OdsafkaxphRrPRF6WXMdKkRWgEuRgIJp6cIg=="], "postject": ["postject@1.0.0-alpha.6", "", { "dependencies": { "commander": "^9.4.0" }, "bin": { "postject": "dist/cli.js" } }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="], "potpack": ["potpack@1.0.2", "", {}, "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ=="], - "preact": ["preact@10.29.1", "", {}, "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg=="], + "preact": ["preact@10.29.0", "", {}, "sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg=="], "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], - "prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="], + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="], @@ -5369,7 +5066,7 @@ "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], - "prosemirror-changeset": ["prosemirror-changeset@2.4.1", "", { "dependencies": { "prosemirror-transform": "^1.0.0" } }, "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw=="], + "prosemirror-changeset": ["prosemirror-changeset@2.4.0", "", { "dependencies": { "prosemirror-transform": "^1.0.0" } }, "sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng=="], "prosemirror-collab": ["prosemirror-collab@1.3.1", "", { "dependencies": { "prosemirror-state": "^1.0.0" } }, "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ=="], @@ -5387,7 +5084,7 @@ "prosemirror-markdown": ["prosemirror-markdown@1.13.4", "", { "dependencies": { "@types/markdown-it": "^14.0.0", "markdown-it": "^14.0.0", "prosemirror-model": "^1.25.0" } }, "sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw=="], - "prosemirror-menu": ["prosemirror-menu@1.3.2", "", { "dependencies": { "crelt": "^1.0.0", "prosemirror-commands": "^1.0.0", "prosemirror-history": "^1.0.0", "prosemirror-state": "^1.0.0" } }, "sha512-6VgUJTYod0nMBlCaYJGhXGLu7Gt4AvcwcOq0YfJCY/6Uh+3S7UsWhpy6rJFCBFOmonq1hD8KyWOtZhkppd4YPg=="], + "prosemirror-menu": ["prosemirror-menu@1.3.0", "", { "dependencies": { "crelt": "^1.0.0", "prosemirror-commands": "^1.0.0", "prosemirror-history": "^1.0.0", "prosemirror-state": "^1.0.0" } }, "sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg=="], "prosemirror-model": ["prosemirror-model@1.25.4", "", { "dependencies": { "orderedmap": "^2.0.0" } }, "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA=="], @@ -5401,17 +5098,17 @@ "prosemirror-trailing-node": ["prosemirror-trailing-node@3.0.0", "", { "dependencies": { "@remirror/core-constants": "3.0.0", "escape-string-regexp": "^4.0.0" }, "peerDependencies": { "prosemirror-model": "^1.22.1", "prosemirror-state": "^1.4.2", "prosemirror-view": "^1.33.8" } }, "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ=="], - "prosemirror-transform": ["prosemirror-transform@1.12.0", "", { "dependencies": { "prosemirror-model": "^1.21.0" } }, "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w=="], + "prosemirror-transform": ["prosemirror-transform@1.11.0", "", { "dependencies": { "prosemirror-model": "^1.21.0" } }, "sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw=="], - "prosemirror-view": ["prosemirror-view@1.41.8", "", { "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } }, "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA=="], + "prosemirror-view": ["prosemirror-view@1.41.7", "", { "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } }, "sha512-jUwKNCEIGiqdvhlS91/2QAg21e4dfU5bH2iwmSDQeosXJgKF7smG0YSplOWK0cjSNgIqXe7VXqo7EIfUFJdt3w=="], - "protobufjs": ["protobufjs@7.5.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg=="], + "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], "proxy-agent": ["proxy-agent@6.5.0", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "http-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.6", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.1.0", "proxy-from-env": "^1.1.0", "socks-proxy-agent": "^8.0.5" } }, "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A=="], - "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="], "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], @@ -5419,11 +5116,9 @@ "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], - "puppeteer-core": ["puppeteer-core@24.41.0", "", { "dependencies": { "@puppeteer/browsers": "2.13.0", "chromium-bidi": "14.0.0", "debug": "^4.4.3", "devtools-protocol": "0.0.1595872", "typed-query-selector": "^2.12.1", "webdriver-bidi-protocol": "0.4.1", "ws": "^8.19.0" } }, "sha512-rLIUri7E/NQ3APSEYCCozaSJx0u8Tu9wxO6BJwnvXmIgILSK3L0TombaVh3izp1njAGrO6H2ru0hcIrLF+gWLw=="], - - "pyright": ["pyright@1.1.409", "", { "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "pyright": "index.js", "pyright-langserver": "langserver.index.js" } }, "sha512-13VFQyw4mJzshZxcxiYbNjo1hG/WHSRDj70Y3lbJEHqCkI2dvBAUTti8VV6Ezsr5gT93pFvC0e/jAQS4JdHarA=="], + "puppeteer-core": ["puppeteer-core@24.40.0", "", { "dependencies": { "@puppeteer/browsers": "2.13.0", "chromium-bidi": "14.0.0", "debug": "^4.4.3", "devtools-protocol": "0.0.1581282", "typed-query-selector": "^2.12.1", "webdriver-bidi-protocol": "0.4.1", "ws": "^8.19.0" } }, "sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag=="], - "qs": ["qs@6.15.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg=="], + "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], @@ -5475,7 +5170,7 @@ "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="], - "react-hook-form": ["react-hook-form@7.72.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-RhwBoy2ygeVZje+C+bwJ8g0NjTdBmDlJvAUHTxRjTmSUKPYsKfMphkS2sgEMotsY03bP358yEYlnUeZy//D9Ig=="], + "react-hook-form": ["react-hook-form@7.72.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-V4v6jubaf6JAurEaVnT9aUPKFbNtDgohj5CIgVGyPHvT9wRx5OZHVjz31GsxnPNI278XMu+ruFz+wGOscHaLKw=="], "react-hotkeys-hook": ["react-hotkeys-hook@5.2.4", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-BgKg+A1+TawkYluh5Bo4cTmcgMN5L29uhJbDUQdHwPX+qgXRjIPYU5kIDHyxnAwCkCBiu9V5OpB2mpyeluVF2A=="], @@ -5485,9 +5180,9 @@ "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], - "react-medium-image-zoom": ["react-medium-image-zoom@5.4.3", "", { "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" } }, "sha512-cDIwdn35fRUPsGnnj/cG6Pacll+z+Mfv6EWU2wDO5ngbZjg5uLRb2ZhEnh92ufbXCJDFvXHekb8G3+oKqUcv5g=="], + "react-medium-image-zoom": ["react-medium-image-zoom@5.4.1", "", { "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" } }, "sha512-DD2iZYaCfAwiQGR8AN62r/cDJYoXhezlYJc5HY4TzBUGuGge43CptG0f7m0PEIM72aN6GfpjohvY1yYdtCJB7g=="], - "react-mosaic-component": ["react-mosaic-component@6.2.0", "", { "dependencies": { "classnames": "^2.3.2", "immutability-helper": "^3.1.1", "lodash": "^4.18.1", "prop-types": "^15.8.1", "rdndmb-html5-to-touch": "^8.0.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dnd-multi-backend": "^8.0.0", "react-dnd-touch-backend": "^16.0.1", "uuid": "^9.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-v7By4y0tFJNFAI/BUhXfTct87WQY9WaCpQwLaqed15jpE4g2sAo34GIB3LIhDHuhwwTU5lvmlVJUXcUggqSBQA=="], + "react-mosaic-component": ["react-mosaic-component@6.1.1", "", { "dependencies": { "classnames": "^2.3.2", "immutability-helper": "^3.1.1", "lodash": "^4.17.21", "prop-types": "^15.8.1", "rdndmb-html5-to-touch": "^8.0.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dnd-multi-backend": "^8.0.0", "react-dnd-touch-backend": "^16.0.1", "uuid": "^9.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-Ivuj6AxRDlo/H8OiEDU1mdgivxuKbwGOa5Ub6Yf+bHcu0JWioT7ttlpCWF63/gKrJBlRMB6fW9/eNOXINg9+Gg=="], "react-native": ["react-native@0.83.1", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.1", "@react-native/codegen": "0.83.1", "@react-native/community-cli-plugin": "0.83.1", "@react-native/gradle-plugin": "0.83.1", "@react-native/js-polyfills": "0.83.1", "@react-native/normalize-colors": "0.83.1", "@react-native/virtualized-lists": "0.83.1", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "hermes-compiler": "0.14.0", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-mL1q5HPq5cWseVhWRLl+Fwvi5z1UO+3vGOpjr+sHFwcUletPRZ5Kv+d0tUfqHmvi73/53NjlQqX1Pyn4GguUfA=="], @@ -5537,6 +5232,8 @@ "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], + "recharts": ["recharts@2.15.4", "", { "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" }, "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" } }, "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw=="], "recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="], @@ -5569,7 +5266,7 @@ "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], - "regjsparser": ["regjsparser@0.13.1", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw=="], + "regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="], "rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="], @@ -5601,7 +5298,7 @@ "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], - "remark-github-blockquote-alert": ["remark-github-blockquote-alert@2.1.0", "", { "dependencies": { "unist-util-visit": "^5.0.0" } }, "sha512-J392jmIP684d7iGsENN0uguL10IGbRdc8bTUSrd/jOLzdWkwg721Fj3JPQGN8tF6fTIrE5HHOIA3nBuwuaeuPQ=="], + "remark-github-blockquote-alert": ["remark-github-blockquote-alert@1.3.1", "", { "dependencies": { "unist-util-visit": "^5.0.0" } }, "sha512-OPNnimcKeozWN1w8KVQEuHOxgN3L4rah8geMOLhA5vN9wITqU4FWD+G26tkEsCGHiOVDbISx+Se5rGZ+D1p0Jg=="], "remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="], @@ -5613,12 +5310,8 @@ "remend": ["remend@1.3.0", "", {}, "sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw=="], - "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="], - "rename-keys": ["rename-keys@1.2.0", "", {}, "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg=="], - "request-light": ["request-light@0.7.0", "", {}, "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q=="], - "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], @@ -5631,7 +5324,7 @@ "resend": ["resend@4.8.0", "", { "dependencies": { "@react-email/render": "1.1.2" } }, "sha512-R8eBOFQDO6dzRTDmaMEdpqrkmgSjPpVXt4nGfWsZdYOet0kqra0xgbvTES6HmCriZEXbmGk3e0DiGIaLFTFSHA=="], - "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], @@ -5663,7 +5356,7 @@ "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="], - "rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="], + "rollup": ["rollup@4.60.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.0", "@rollup/rollup-android-arm64": "4.60.0", "@rollup/rollup-darwin-arm64": "4.60.0", "@rollup/rollup-darwin-x64": "4.60.0", "@rollup/rollup-freebsd-arm64": "4.60.0", "@rollup/rollup-freebsd-x64": "4.60.0", "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", "@rollup/rollup-linux-arm-musleabihf": "4.60.0", "@rollup/rollup-linux-arm64-gnu": "4.60.0", "@rollup/rollup-linux-arm64-musl": "4.60.0", "@rollup/rollup-linux-loong64-gnu": "4.60.0", "@rollup/rollup-linux-loong64-musl": "4.60.0", "@rollup/rollup-linux-ppc64-gnu": "4.60.0", "@rollup/rollup-linux-ppc64-musl": "4.60.0", "@rollup/rollup-linux-riscv64-gnu": "4.60.0", "@rollup/rollup-linux-riscv64-musl": "4.60.0", "@rollup/rollup-linux-s390x-gnu": "4.60.0", "@rollup/rollup-linux-x64-gnu": "4.60.0", "@rollup/rollup-linux-x64-musl": "4.60.0", "@rollup/rollup-openbsd-x64": "4.60.0", "@rollup/rollup-openharmony-arm64": "4.60.0", "@rollup/rollup-win32-arm64-msvc": "4.60.0", "@rollup/rollup-win32-ia32-msvc": "4.60.0", "@rollup/rollup-win32-x64-gnu": "4.60.0", "@rollup/rollup-win32-x64-msvc": "4.60.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ=="], "rollup-plugin-inject-process-env": ["rollup-plugin-inject-process-env@1.3.1", "", { "dependencies": { "magic-string": "^0.25.7" } }, "sha512-kKDoL30IZr0wxbNVJjq+OS92RJSKRbKV6B5eNW4q3mZTFqoWDh6lHy+mPDYuuGuERFNKXkG+AKxvYqC9+DRpKQ=="], @@ -5697,16 +5390,12 @@ "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "saxes": ["saxes@5.0.1", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw=="], - "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="], "scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="], - "scule": ["scule@1.3.0", "", {}, "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="], - "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], "secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="], @@ -5721,9 +5410,9 @@ "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], - "seroval": ["seroval@1.5.2", "", {}, "sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q=="], + "seroval": ["seroval@1.5.1", "", {}, "sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA=="], - "seroval-plugins": ["seroval-plugins@1.5.2", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg=="], + "seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="], "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], @@ -5751,29 +5440,29 @@ "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], - "sherif": ["sherif@1.11.1", "", { "optionalDependencies": { "sherif-darwin-arm64": "1.11.1", "sherif-darwin-x64": "1.11.1", "sherif-linux-arm64": "1.11.1", "sherif-linux-arm64-musl": "1.11.1", "sherif-linux-x64": "1.11.1", "sherif-linux-x64-musl": "1.11.1", "sherif-windows-arm64": "1.11.1", "sherif-windows-x64": "1.11.1" }, "bin": { "sherif": "index.js" } }, "sha512-HBFce8NGaPuWPg5NXb6+aI7hJQFjTilhtbrgo+Y/BvtGlkuJAzLnkmC8nyD+p3v7oIAq4KQeA8qySKGga28xZg=="], + "sherif": ["sherif@1.11.0", "", { "optionalDependencies": { "sherif-darwin-arm64": "1.11.0", "sherif-darwin-x64": "1.11.0", "sherif-linux-arm64": "1.11.0", "sherif-linux-arm64-musl": "1.11.0", "sherif-linux-x64": "1.11.0", "sherif-linux-x64-musl": "1.11.0", "sherif-windows-arm64": "1.11.0", "sherif-windows-x64": "1.11.0" }, "bin": { "sherif": "index.js" } }, "sha512-JrStUXvTM4vZmeiF55/LczheOgKFvKMrtqbeTs7pCmQCKcAiD/9Jvv8/6fuhldt85clllDIJCQujijlBm72CTA=="], - "sherif-darwin-arm64": ["sherif-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VoMrUv5QY6hQ2rByNa3AAhr/KGQsCb6pvAUNKa1iCh1jvnY836hQr6zNBw9hYCDkVv6t9sITFGJljwdTCQD4xw=="], + "sherif-darwin-arm64": ["sherif-darwin-arm64@1.11.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Ok33TgwXbMjfUQo7OK6l45/x+3XS1fAC7PDHdV2HW8G5PlWQTq73tLvXWzRuGMXVlef/yz9CNGNdUr6ZddqSKQ=="], - "sherif-darwin-x64": ["sherif-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-7j3yOCBkvVbltVT3lXoiazGfG2nb36FteYT5VZPEBSf8sTn1pPTScukAQ1Fdl+MphadGyici7XlRbDrtZ/wnvA=="], + "sherif-darwin-x64": ["sherif-darwin-x64@1.11.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-aGXEfJKrY8RKjBaud5apFS/n6q16ZVBkLOxaNFAvx2zTgV6t3Nl7NH50thw7WVKIYX7ed4rE8vD3rsiKgWrfTQ=="], - "sherif-linux-arm64": ["sherif-linux-arm64@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-vCZFS7RxhZ/8g9bdj3UPNVPTcZiKiWigW+FIlVQEUKEKfG0MfSOMBJqEWPVVUniyJa3rdIxtmZKSdWkG0e1x3w=="], + "sherif-linux-arm64": ["sherif-linux-arm64@1.11.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-tdGvyBweTC3l3SdEI9g0R2IoT4Lo9grQGijoleztbb1xOFGQXulAWYSUM3CgErY72A9PGCGg2sZb04trDT8VvA=="], - "sherif-linux-arm64-musl": ["sherif-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-DCf87RFqBh8ZrYgu3y+fv0x4kFn/np84m2jAEgygznwozH/VCfrXbHFVdhxW7762JCYkXbHO9dUj/ff5fkvkvw=="], + "sherif-linux-arm64-musl": ["sherif-linux-arm64-musl@1.11.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVjwTN5y6Sj83gSqXF6JWfMolXc4tIaYdD42M8i6KPr87kGqI5m4zbx8nczHI9HgghuRVhoEpCG57hN9QFv4RA=="], - "sherif-linux-x64": ["sherif-linux-x64@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-9t+p1X3SyhU75BrJNHBbj9i/aQxHC/sF+Mdkf17V5AlokCznFgYKQUXq5EVmcmRDDhDl69RMzCTLD95EBqUSYA=="], + "sherif-linux-x64": ["sherif-linux-x64@1.11.0", "", { "os": "linux", "cpu": "x64" }, "sha512-onc7y90TKAj5h+PX4SOtLCVvziHgiRgFZ9pyUPHMb4JA7wrwcO7M9D12WIX3GDDpcimu312fIg9RT5h5CcKC4A=="], - "sherif-linux-x64-musl": ["sherif-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-f8xitqXdHObUFPZo4QVbz3o30Y4+gHA3B5ZobsOWocnSfJBaUGutBzJsUsjG6w2tccSRn6+mugiMUGKIbIPZmQ=="], + "sherif-linux-x64-musl": ["sherif-linux-x64-musl@1.11.0", "", { "os": "linux", "cpu": "x64" }, "sha512-IIQBIE+FZ0NK2Pvb8jWHeKFQh2E1tvhuTnK6Wklq7b74XlT8xKXWFA+hHS1VCvHrB8Bh9OOMcP+baSit7wV9xA=="], - "sherif-windows-arm64": ["sherif-windows-arm64@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-Dnffgcyz9zLq/8UTY2REchJzRJWcWAuMWo5Vl5O17IZGkhl71dwa7/Vi2wC3EQd8WAVK/O82yArOYggWA0dj5w=="], + "sherif-windows-arm64": ["sherif-windows-arm64@1.11.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-L6vgTAcevTRA1GoYobyqmdIz6wzj7b3EhrMZ/lbOz07a/4TxctAaDyGpSGXQmzNNUxqc9CpBH1mtcYRaFVk4dg=="], - "sherif-windows-x64": ["sherif-windows-x64@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xjfYUL/IQ65DwHkRsWIxiZWtglKtL5/E3UHpnLwOui3jqW1V2K88SMct415dnlBQiL3U9VEIVUo1i+KmToOBgQ=="], + "sherif-windows-x64": ["sherif-windows-x64@1.11.0", "", { "os": "win32", "cpu": "x64" }, "sha512-odBQs2OQn2j0OoN2B3juxC6k5FnPHaskkbZ0SGsnF/c5quxpCdlqFDXMBHE60v4yznOtWl53dxlwWmResGp8iw=="], "shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], @@ -5785,7 +5474,7 @@ "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], - "simple-git": ["simple-git@3.36.0", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "@simple-git/args-pathspec": "^1.0.3", "@simple-git/argv-parser": "^1.1.0", "debug": "^4.4.0" } }, "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q=="], + "simple-git": ["simple-git@3.33.0", "", { "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", "debug": "^4.4.0" } }, "sha512-D4V/tGC2sjsoNhoMybKyGoE+v8A60hRawKQ1iFRA1zwuDgGZCBJ4ByOzZ5J8joBbi4Oam0qiPH+GhzmSBwbJng=="], "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="], @@ -5803,7 +5492,7 @@ "slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="], - "slugify": ["slugify@1.6.9", "", {}, "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg=="], + "slugify": ["slugify@1.6.8", "", {}, "sha512-HVk9X1E0gz3mSpoi60h/saazLKXKaZThMLU3u/aNwoYn8/xQyX2MGxL0ui2eaokkD7tF+Zo+cKTHUbe1mmmGzA=="], "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], @@ -5873,13 +5562,11 @@ "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], - "string-env-interpolation": ["string-env-interpolation@1.0.1", "", {}, "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg=="], - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], @@ -5931,16 +5618,10 @@ "suspend-react": ["suspend-react@0.1.3", "", { "peerDependencies": { "react": ">=17.0" } }, "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ=="], - "svelte": ["svelte@4.2.20", "", { "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", "@jridgewell/trace-mapping": "^0.3.18", "@types/estree": "^1.0.1", "acorn": "^8.9.0", "aria-query": "^5.3.0", "axobject-query": "^4.0.0", "code-red": "^1.0.3", "css-tree": "^2.3.1", "estree-walker": "^3.0.3", "is-reference": "^3.0.1", "locate-character": "^3.0.0", "magic-string": "^0.30.4", "periscopic": "^3.1.0" } }, "sha512-eeEgGc2DtiUil5ANdtd8vPwt9AgaMdnuUFnPft9F5oMvU/FHu5IHFic+p1dR/UOB7XU2mX2yHW+NcTch4DCh5Q=="], - - "svelte2tsx": ["svelte2tsx@0.7.53", "", { "dependencies": { "dedent-js": "^1.0.1", "scule": "^1.3.0" }, "peerDependencies": { "svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0", "typescript": "^4.9.4 || ^5.0.0" } }, "sha512-ljVSwmnYRDHRm8+7ICP6QoAN7U7vgOFfPBLN6T745YWNYqRRSzHxlrzUVqMjYls2Un8MzJissfziy/38e6Deeg=="], - "svgson": ["svgson@5.3.1", "", { "dependencies": { "deep-rename-keys": "^0.2.1", "xml-reader": "2.4.3" } }, "sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA=="], "swr": ["swr@2.4.1", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA=="], - "sync-fetch": ["sync-fetch@0.6.0-2", "", { "dependencies": { "node-fetch": "^3.3.2", "timeout-signal": "^2.0.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A=="], - "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], @@ -5997,8 +5678,6 @@ "time-zone": ["time-zone@1.0.0", "", {}, "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA=="], - "timeout-signal": ["timeout-signal@2.0.0", "", {}, "sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA=="], - "tiny-async-pool": ["tiny-async-pool@1.3.0", "", { "dependencies": { "semver": "^5.5.0" } }, "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA=="], "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], @@ -6007,9 +5686,9 @@ "tiny-typed-emitter": ["tiny-typed-emitter@2.1.0", "", {}, "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="], - "tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="], + "tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="], - "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tippy.js": ["tippy.js@6.3.7", "", { "dependencies": { "@popperjs/core": "^2.9.0" } }, "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ=="], @@ -6041,8 +5720,6 @@ "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "traverse": ["traverse@0.3.9", "", {}, "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="], - "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], @@ -6117,7 +5794,7 @@ "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], - "undici": ["undici@6.25.0", "", {}, "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg=="], + "undici": ["undici@6.24.1", "", {}, "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA=="], "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], @@ -6163,16 +5840,12 @@ "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - "uniwind": ["uniwind@1.6.2", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "culori": "4.0.2", "lightningcss": "1.30.1" }, "peerDependencies": { "react": ">=19.0.0", "react-native": ">=0.81.0", "tailwindcss": ">=4" } }, "sha512-skT0I/PFGajygQPGJ20sYbqc3HxmcOMkfQWy51Ha6eXXJWRJh6vYiy7jUJvLFwdzWlfX1g+Z8oC/SpxgRB5R+g=="], - - "unixify": ["unixify@1.0.0", "", { "dependencies": { "normalize-path": "^2.1.1" } }, "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg=="], + "uniwind": ["uniwind@1.6.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "culori": "4.0.2", "lightningcss": "1.30.1" }, "peerDependencies": { "react": ">=19.0.0", "react-native": ">=0.81.0", "tailwindcss": ">=4" } }, "sha512-aR7vEGccEHDCvjyNM5BE5ZVdbdVTVL6yIffYe65mgjedzOj82TcdWrvae+A3PSHwQTuC1E3/3HbOX/Y5GqMvRQ=="], "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], "unplugin": ["unplugin@1.0.1", "", { "dependencies": { "acorn": "^8.8.1", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.5.0" } }, "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA=="], - "unzipper": ["unzipper@0.10.14", "", { "dependencies": { "big-integer": "^1.6.17", "binary": "~0.3.0", "bluebird": "~3.4.1", "buffer-indexof-polyfill": "~1.0.0", "duplexer2": "~0.1.4", "fstream": "^1.0.12", "graceful-fs": "^4.2.2", "listenercount": "~1.0.1", "readable-stream": "~2.3.6", "setimmediate": "~1.0.4" } }, "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g=="], - "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -6223,38 +5896,24 @@ "victory-vendor": ["victory-vendor@36.9.2", "", { "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" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="], - "vite": ["vite@7.3.2", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg=="], + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], "vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="], "vlq": ["vlq@1.0.1", "", {}, "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="], - "vscode-css-languageservice": ["vscode-css-languageservice@6.3.10", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA=="], - - "vscode-html-languageservice": ["vscode-html-languageservice@5.6.2", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg=="], - - "vscode-json-languageservice": ["vscode-json-languageservice@5.7.2", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "jsonc-parser": "^3.3.1", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-WtKRDtJfFEmLrgtu+ODexOHm/6/krRF0k6t+uvkKIKW1Jh9ZIyxZQwJJwB3qhrEgvAxa37zbUg+vn+UyUK/U2w=="], - "vscode-jsonrpc": ["vscode-jsonrpc@8.2.1", "", {}, "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ=="], - "vscode-langservers-extracted": ["vscode-langservers-extracted@4.10.0", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "core-js": "^3.20.1", "jsonc-parser": "^3.2.1", "regenerator-runtime": "^0.13.9", "request-light": "^0.7.0", "semver": "^7.6.1", "typescript": "^4.0.5", "vscode-css-languageservice": "^6.2.14", "vscode-html-languageservice": "^5.2.0", "vscode-json-languageservice": "^5.3.11", "vscode-languageserver": "^10.0.0-next.3", "vscode-languageserver-textdocument": "^1.0.11", "vscode-languageserver-types": "^3.17.5", "vscode-markdown-languageservice": "^0.5.0-alpha.6", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" }, "bin": { "vscode-css-language-server": "bin/vscode-css-language-server", "vscode-eslint-language-server": "bin/vscode-eslint-language-server", "vscode-html-language-server": "bin/vscode-html-language-server", "vscode-json-language-server": "bin/vscode-json-language-server", "vscode-markdown-language-server": "bin/vscode-markdown-language-server" } }, "sha512-EFf9uQI4dAKbzMQFjDvVm1xJq1DXAQvBEuEfPGrK/xzfsL5xWTfIuRr90NgfmqwO+IEt6vLZm9EOj6R66xIifg=="], - - "vscode-languageserver": ["vscode-languageserver@8.0.2", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.2" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA=="], + "vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="], "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="], - "vscode-languageserver-types": ["vscode-languageserver-types@3.17.3", "", {}, "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA=="], - - "vscode-markdown-languageservice": ["vscode-markdown-languageservice@0.5.0-alpha.11", "", { "dependencies": { "@vscode/l10n": "^0.0.10", "node-html-parser": "^6.1.5", "picomatch": "^2.3.1", "vscode-languageserver-protocol": "^3.17.1", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.7" } }, "sha512-P1uBMAD5iylgpcweWCU1kQwk8SZngktnljXsZk1vFPorXv1mrEI7BkBpOUU0fhVssKgvFlCNLkI7KmwZLC7pdA=="], - - "vscode-nls": ["vscode-nls@5.2.0", "", {}, "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng=="], + "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], - "vue": ["vue@3.5.32", "", { "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/compiler-sfc": "3.5.32", "@vue/runtime-dom": "3.5.32", "@vue/server-renderer": "3.5.32", "@vue/shared": "3.5.32" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw=="], - "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], "wait-port": ["wait-port@1.1.0", "", { "dependencies": { "chalk": "^4.1.2", "commander": "^9.3.0", "debug": "^4.3.4" }, "bin": { "wait-port": "bin/wait-port.js" } }, "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q=="], @@ -6285,7 +5944,7 @@ "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - "webpack": ["webpack@5.106.2", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.20.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "loader-runner": "^4.3.1", "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.17", "watchpack": "^2.5.1", "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA=="], + "webpack": ["webpack@5.105.4", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.20.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.17", "watchpack": "^2.5.1", "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw=="], "webpack-sources": ["webpack-sources@3.3.4", "", {}, "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q=="], @@ -6307,9 +5966,9 @@ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - "workerd": ["workerd@1.20260415.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260415.1", "@cloudflare/workerd-darwin-arm64": "1.20260415.1", "@cloudflare/workerd-linux-64": "1.20260415.1", "@cloudflare/workerd-linux-arm64": "1.20260415.1", "@cloudflare/workerd-windows-64": "1.20260415.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-phyPjRnx+mQDfkhN9ENPioL1L0SdhYs4S0YmJK/xF9Oga+ykNfdSy1MHnsOj8yqnOV96zcVQMx32dJ0r3pq0jQ=="], + "workerd": ["workerd@1.20260317.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260317.1", "@cloudflare/workerd-darwin-arm64": "1.20260317.1", "@cloudflare/workerd-linux-64": "1.20260317.1", "@cloudflare/workerd-linux-arm64": "1.20260317.1", "@cloudflare/workerd-windows-64": "1.20260317.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-ZuEq1OdrJBS+NV+L5HMYPCzVn49a2O60slQiiLpG44jqtlOo+S167fWC76kEXteXLLLydeuRrluRel7WdOUa4g=="], - "wrangler": ["wrangler@4.83.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.2", "@cloudflare/unenv-preset": "2.16.0", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260415.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260415.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260415.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-gw5g3LCiuAqVWxaoKY6+quE0HzAUEFb/FV3oAlNkE1ttd4XP3FiV91XDkkzUCcdqxS4WjhQvPhIDBNdhEi8P0A=="], + "wrangler": ["wrangler@4.78.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.2", "@cloudflare/unenv-preset": "2.16.0", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260317.3", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260317.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260317.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-He/vUhk4ih0D0eFmtNnlbT6Od8j+BEokaSR+oYjbVsH0SWIrIch+eHqfLRSBjBQaOoh6HCNxcafcIkBm2u0Hag=="], "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -6331,8 +5990,6 @@ "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], - "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="], - "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="], @@ -6343,8 +6000,6 @@ "yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="], - "yaml-language-server": ["yaml-language-server@1.22.0", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-uri": "^3.0.2", "yaml": "2.8.3" }, "bin": { "yaml-language-server": "bin/yaml-language-server" } }, "sha512-1vGi3FL1B8WiKHwNADotG+CGl4S55q8ZEqKRWIACu/slJC32MBBORWZpzBFB6r9vrmI3cXsLmD5DRAxAvgqBSw=="], - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], @@ -6359,7 +6014,7 @@ "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], - "zip-stream": ["zip-stream@4.1.1", "", { "dependencies": { "archiver-utils": "^3.0.4", "compress-commons": "^4.1.2", "readable-stream": "^3.6.0" } }, "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ=="], + "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], @@ -6381,13 +6036,13 @@ "@a2a-js/sdk/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], - "@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.74", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-1Z7142GVIF4XkcSvQpL6ij2c7J51dtm4/Z84P+O0bGBDZI1Nbvz897hXkJf2cfNhq5XdpvUYbI+oExXM7Ko8Zw=="], "@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@2.0.103", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FDwY060LV/D5th+LeaxpSKcot5eXjzNzHguDf0NU1K+v7rxYZFWbldQPZarNo/IpD/WJE9RojgrFAcZ1e8KyvQ=="], + "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@2.0.102", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tYarHJhyMioGegsnhpqz1/tKoCAJJ6zBHoIQaredNkt8V3o/JXj2647NnEOJVe7WHQXGvCfzbfnP1TADFhPmcA=="], "@ai-sdk/azure/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], @@ -6405,7 +6060,7 @@ "@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], - "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], + "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.74", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-1Z7142GVIF4XkcSvQpL6ij2c7J51dtm4/Z84P+O0bGBDZI1Nbvz897hXkJf2cfNhq5XdpvUYbI+oExXM7Ko8Zw=="], "@ai-sdk/google-vertex/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], @@ -6463,19 +6118,17 @@ "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@babel/polyfill/core-js": ["core-js@2.6.12", "", {}, "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="], - "@browserbasehq/sdk/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - "@browserbasehq/stagehand/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.77", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8n7ApEzFOxqVvT3HyqLrEQlgUx/2nUmPFLTGY3fNKwUA8KVNU3Ovd2C66Qh1Y93Iq5NkHsOWuLiTyAZpRKQhgw=="], + "@browserbasehq/stagehand/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.74", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-1Z7142GVIF4XkcSvQpL6ij2c7J51dtm4/Z84P+O0bGBDZI1Nbvz897hXkJf2cfNhq5XdpvUYbI+oExXM7Ko8Zw=="], - "@browserbasehq/stagehand/@ai-sdk/openai": ["@ai-sdk/openai@2.0.103", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FDwY060LV/D5th+LeaxpSKcot5eXjzNzHguDf0NU1K+v7rxYZFWbldQPZarNo/IpD/WJE9RojgrFAcZ1e8KyvQ=="], + "@browserbasehq/stagehand/@ai-sdk/openai": ["@ai-sdk/openai@2.0.102", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tYarHJhyMioGegsnhpqz1/tKoCAJJ6zBHoIQaredNkt8V3o/JXj2647NnEOJVe7WHQXGvCfzbfnP1TADFhPmcA=="], "@browserbasehq/stagehand/@ai-sdk/provider": ["@ai-sdk/provider@2.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng=="], "@browserbasehq/stagehand/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.39.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-eMyDIPRZbt1CCLErRCi3exlAvNkBtRe+kW5vvJyef93PmNr/clstYgHhtvmkxN82nlKgzyGPCyGxrm0JQ1ZIdg=="], - "@browserbasehq/stagehand/ai": ["ai@5.0.179", "", { "dependencies": { "@ai-sdk/gateway": "2.0.82", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tuq/r2FH/pBuY3jo0yHF3UglDV73WONGLhW80DuwgO6w0ftPIqRsAm5p9cE3Bu4LfEuCkMXpiUG/pQRzqKRRaA=="], + "@browserbasehq/stagehand/ai": ["ai@5.0.171", "", { "dependencies": { "@ai-sdk/gateway": "2.0.75", "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-c3Eczgg7wp8Y/PZ1HF5dUA5FXjJy0JmubVuHeD49++9ma9EfX8S8UNlRZ2xN3Oaep1OAt0qXXcDoR1JG31Syig=="], "@browserbasehq/stagehand/devtools-protocol": ["devtools-protocol@0.0.1464554", "", {}, "sha512-CAoP3lYfwAGQTaAXYvA6JZR0fjGUb7qec1qf4mToyoH2TZgUFeIqYcjh6f9jNuhHfuZiEdH+PONHYrLhRQX6aw=="], @@ -6483,7 +6136,7 @@ "@browserbasehq/stagehand/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], - "@code-inspector/core/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "@code-inspector/core/chalk": ["chalk@4.1.1", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg=="], "@code-inspector/core/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], @@ -6559,9 +6212,9 @@ "@expo/mcp-tunnel/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@expo/metro/metro-runtime": ["metro-runtime@0.83.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA=="], + "@expo/metro/metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="], - "@expo/metro/metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], + "@expo/metro/metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], "@expo/metro-config/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -6579,38 +6232,10 @@ "@expo/xcpretty/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "@fast-csv/format/@types/node": ["@types/node@14.18.63", "", {}, "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="], - - "@fast-csv/parse/@types/node": ["@types/node@14.18.63", "", {}, "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="], - "@fastify/otel/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.212.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.212.0", "import-in-the-middle": "^2.0.6", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg=="], "@fumadocs/ui/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], - "@graphql-tools/code-file-loader/globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - - "@graphql-tools/executor/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/executor-http/@graphql-tools/executor-common": ["@graphql-tools/executor-common@0.0.4", "", { "dependencies": { "@envelop/core": "^5.2.3", "@graphql-tools/utils": "^10.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-SEH/OWR+sHbknqZyROCFHcRrbZeUAyjCsgpVWCRjqjqRbiJiXq6TxNIIOmpXgkrXWW/2Ev4Wms6YSGJXjdCs6Q=="], - - "@graphql-tools/executor-legacy-ws/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/graphql-file-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/graphql-file-loader/globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - - "@graphql-tools/import/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/json-file-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/json-file-loader/globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - - "@graphql-tools/load/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/merge/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - - "@graphql-tools/schema/@graphql-tools/utils": ["@graphql-tools/utils@11.0.1", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pNyCOb95ab/z3zkkiPwIPYxigX7IcpyFVcgD1XACDEvg/7yGnKCESx3k/XHEeneKYx/aWKGzEh/uuf6M6Q8HOw=="], - "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], "@istanbuljs/load-nyc-config/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], @@ -6621,8 +6246,6 @@ "@jest/transform/write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="], - "@jest/types/@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="], - "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@langchain/core/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], @@ -6635,8 +6258,6 @@ "@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "@linear/sdk/graphql": ["graphql@15.10.2", "", {}, "sha512-1PRqdDPAmViWr4h1GVBT8RoPZfWSGZa7kDzleTilOfVIslsgf+cia3Nl95v1KDmR4iERPaT7WzQ+tN4MJmbg3w=="], - "@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@mariozechner/pi-tui/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], @@ -6645,15 +6266,15 @@ "@mdx-js/mdx/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - "@neondatabase/serverless/@types/node": ["@types/node@22.19.17", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q=="], + "@neondatabase/serverless/@types/node": ["@types/node@22.19.15", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg=="], "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "@opentelemetry/instrumentation/import-in-the-middle": ["import-in-the-middle@3.0.1", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA=="], + "@opentelemetry/instrumentation/import-in-the-middle": ["import-in-the-middle@3.0.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg=="], - "@opentelemetry/instrumentation-http/@opentelemetry/core": ["@opentelemetry/core@2.6.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="], + "@opentelemetry/instrumentation-http/@opentelemetry/core": ["@opentelemetry/core@2.6.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg=="], - "@pierre/diffs/diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], + "@opentelemetry/instrumentation-pg/@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="], "@poppinss/colors/kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -6711,11 +6332,11 @@ "@react-native/community-cli-plugin/@react-native/dev-middleware": ["@react-native/dev-middleware@0.83.1", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.83.1", "@react-native/debugger-shell": "0.83.1", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^7.5.10" } }, "sha512-QJaSfNRzj3Lp7MmlCRgSBlt1XZ38xaBNXypXAp/3H3OdFifnTZOeYOpFmcpjcXYnDqkxetuwZg8VL65SQhB8dg=="], - "@react-native/community-cli-plugin/metro": ["metro@0.83.6", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.35.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.6", "metro-cache": "0.83.6", "metro-cache-key": "0.83.6", "metro-config": "0.83.6", "metro-core": "0.83.6", "metro-file-map": "0.83.6", "metro-resolver": "0.83.6", "metro-runtime": "0.83.6", "metro-source-map": "0.83.6", "metro-symbolicate": "0.83.6", "metro-transform-plugins": "0.83.6", "metro-transform-worker": "0.83.6", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-pbdndsAZ2F/ceopDdhVbttpa/hfLzXPJ/husc+QvQ33R0D9UXJKzTn5+OzOXx4bpQNtAKF2bY88cCI3Zl44xDQ=="], + "@react-native/community-cli-plugin/metro": ["metro@0.83.5", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.33.3", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-config": "0.83.5", "metro-core": "0.83.5", "metro-file-map": "0.83.5", "metro-resolver": "0.83.5", "metro-runtime": "0.83.5", "metro-source-map": "0.83.5", "metro-symbolicate": "0.83.5", "metro-transform-plugins": "0.83.5", "metro-transform-worker": "0.83.5", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-BgsXevY1MBac/3ZYv/RfNFf/4iuW9X7f4H8ZNkiH+r667HD9sVujxcmu4jvEzGCAm4/WyKdZCuyhAcyhTHOucQ=="], - "@react-native/community-cli-plugin/metro-config": ["metro-config@0.83.6", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.6", "metro-cache": "0.83.6", "metro-core": "0.83.6", "metro-runtime": "0.83.6", "yaml": "^2.6.1" } }, "sha512-G5622400uNtnAMlppEA5zkFAZltEf7DSGhOu09BkisCxOlVMWfdosD/oPyh4f2YVQsc1MBYyp4w6OzbExTYarg=="], + "@react-native/community-cli-plugin/metro-config": ["metro-config@0.83.5", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.5", "metro-cache": "0.83.5", "metro-core": "0.83.5", "metro-runtime": "0.83.5", "yaml": "^2.6.1" } }, "sha512-JQ/PAASXH7yczgV6OCUSRhZYME+NU8NYjI2RcaG5ga4QfQ3T/XdiLzpSb3awWZYlDCcQb36l4Vl7i0Zw7/Tf9w=="], - "@react-native/community-cli-plugin/metro-core": ["metro-core@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.6" } }, "sha512-l+yQ2fuIgR//wszUlMrrAa9+Z+kbKazd0QOh0VQY7jC4ghb7yZBBSla/UMYRBZZ6fPg9IM+wD3+h+37a5f9etw=="], + "@react-native/community-cli-plugin/metro-core": ["metro-core@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.5" } }, "sha512-YcVcLCrf0ed4mdLa82Qob0VxYqfhmlRxUS8+TO4gosZo/gLwSvtdeOjc/Vt0pe/lvMNrBap9LlmvZM8FIsMgJQ=="], "@react-native/dev-middleware/@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], @@ -6727,7 +6348,7 @@ "@react-navigation/core/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "@react-navigation/core/react-is": ["react-is@19.2.5", "", {}, "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ=="], + "@react-navigation/core/react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="], "@react-navigation/native/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], @@ -6735,34 +6356,38 @@ "@react-three/drei/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], - "@sentry-internal/feedback/@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], + "@sentry-internal/feedback/@sentry/core": ["@sentry/core@10.42.0", "", {}, "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA=="], - "@sentry-internal/replay/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" } }, "sha512-bVFRAeJWMBcBCvJKIFCMJ1/yQToL4vPGqfmlnDZeypcxkqUDKQ/Y3ziLHXoDL2sx0lagcgU2vH1QhCQ67Aujjw=="], + "@sentry-internal/replay/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.42.0", "", { "dependencies": { "@sentry/core": "10.42.0" } }, "sha512-HCEICKvepxN4/6NYfnMMMlppcSwIEwtS66X6d1/mwaHdi2ivw0uGl52p7Nfhda/lIJArbrkWprxl0WcjZajhQA=="], - "@sentry-internal/replay/@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], + "@sentry-internal/replay/@sentry/core": ["@sentry/core@10.42.0", "", {}, "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA=="], - "@sentry-internal/replay-canvas/@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], + "@sentry-internal/replay-canvas/@sentry/core": ["@sentry/core@10.42.0", "", {}, "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA=="], - "@sentry/browser/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" } }, "sha512-bVFRAeJWMBcBCvJKIFCMJ1/yQToL4vPGqfmlnDZeypcxkqUDKQ/Y3ziLHXoDL2sx0lagcgU2vH1QhCQ67Aujjw=="], + "@sentry/browser/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.42.0", "", { "dependencies": { "@sentry/core": "10.42.0" } }, "sha512-HCEICKvepxN4/6NYfnMMMlppcSwIEwtS66X6d1/mwaHdi2ivw0uGl52p7Nfhda/lIJArbrkWprxl0WcjZajhQA=="], - "@sentry/browser/@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], + "@sentry/browser/@sentry/core": ["@sentry/core@10.42.0", "", {}, "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA=="], "@sentry/bundler-plugin-core/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], "@sentry/cli/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], - "@sentry/electron/@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], + "@sentry/cli/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "@sentry/electron/@sentry/core": ["@sentry/core@10.42.0", "", {}, "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA=="], - "@sentry/electron/@sentry/node": ["@sentry/node@10.47.0", "", { "dependencies": { "@fastify/otel": "0.18.0", "@opentelemetry/api": "^1.9.1", "@opentelemetry/context-async-hooks": "^2.6.1", "@opentelemetry/core": "^2.6.1", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/instrumentation-amqplib": "0.61.0", "@opentelemetry/instrumentation-connect": "0.57.0", "@opentelemetry/instrumentation-dataloader": "0.31.0", "@opentelemetry/instrumentation-express": "0.62.0", "@opentelemetry/instrumentation-fs": "0.33.0", "@opentelemetry/instrumentation-generic-pool": "0.57.0", "@opentelemetry/instrumentation-graphql": "0.62.0", "@opentelemetry/instrumentation-hapi": "0.60.0", "@opentelemetry/instrumentation-http": "0.214.0", "@opentelemetry/instrumentation-ioredis": "0.62.0", "@opentelemetry/instrumentation-kafkajs": "0.23.0", "@opentelemetry/instrumentation-knex": "0.58.0", "@opentelemetry/instrumentation-koa": "0.62.0", "@opentelemetry/instrumentation-lru-memoizer": "0.58.0", "@opentelemetry/instrumentation-mongodb": "0.67.0", "@opentelemetry/instrumentation-mongoose": "0.60.0", "@opentelemetry/instrumentation-mysql": "0.60.0", "@opentelemetry/instrumentation-mysql2": "0.60.0", "@opentelemetry/instrumentation-pg": "0.66.0", "@opentelemetry/instrumentation-redis": "0.62.0", "@opentelemetry/instrumentation-tedious": "0.33.0", "@opentelemetry/instrumentation-undici": "0.24.0", "@opentelemetry/resources": "^2.6.1", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@prisma/instrumentation": "7.6.0", "@sentry/core": "10.47.0", "@sentry/node-core": "10.47.0", "@sentry/opentelemetry": "10.47.0", "import-in-the-middle": "^3.0.0" } }, "sha512-R+btqPepv88o635G6HtVewLjqCLUedBg5HBs7Nq1qbbKvyti01uArUF2f+3DsLenk5B9LUNiRlE+frZA44Ahmw=="], + "@sentry/electron/@sentry/node": ["@sentry/node@10.42.0", "", { "dependencies": { "@fastify/otel": "0.16.0", "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^2.5.1", "@opentelemetry/core": "^2.5.1", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/instrumentation-amqplib": "0.58.0", "@opentelemetry/instrumentation-connect": "0.54.0", "@opentelemetry/instrumentation-dataloader": "0.28.0", "@opentelemetry/instrumentation-express": "0.59.0", "@opentelemetry/instrumentation-fs": "0.30.0", "@opentelemetry/instrumentation-generic-pool": "0.54.0", "@opentelemetry/instrumentation-graphql": "0.58.0", "@opentelemetry/instrumentation-hapi": "0.57.0", "@opentelemetry/instrumentation-http": "0.211.0", "@opentelemetry/instrumentation-ioredis": "0.59.0", "@opentelemetry/instrumentation-kafkajs": "0.20.0", "@opentelemetry/instrumentation-knex": "0.55.0", "@opentelemetry/instrumentation-koa": "0.59.0", "@opentelemetry/instrumentation-lru-memoizer": "0.55.0", "@opentelemetry/instrumentation-mongodb": "0.64.0", "@opentelemetry/instrumentation-mongoose": "0.57.0", "@opentelemetry/instrumentation-mysql": "0.57.0", "@opentelemetry/instrumentation-mysql2": "0.57.0", "@opentelemetry/instrumentation-pg": "0.63.0", "@opentelemetry/instrumentation-redis": "0.59.0", "@opentelemetry/instrumentation-tedious": "0.30.0", "@opentelemetry/instrumentation-undici": "0.21.0", "@opentelemetry/resources": "^2.5.1", "@opentelemetry/sdk-trace-base": "^2.5.1", "@opentelemetry/semantic-conventions": "^1.39.0", "@prisma/instrumentation": "7.2.0", "@sentry/core": "10.42.0", "@sentry/node-core": "10.42.0", "@sentry/opentelemetry": "10.42.0", "import-in-the-middle": "^2.0.6" } }, "sha512-ZZfU3Fnni7Aj0lTX4e3QpY3UxK4FGuzfM20316UAJycBGnripm+sDHwcekPMGfLnk/FrN9wa1atspVlHvOI0WQ=="], - "@sentry/node/import-in-the-middle": ["import-in-the-middle@3.0.1", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA=="], + "@sentry/node/import-in-the-middle": ["import-in-the-middle@3.0.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg=="], - "@sentry/node-core/import-in-the-middle": ["import-in-the-middle@3.0.1", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA=="], + "@sentry/node-core/import-in-the-middle": ["import-in-the-middle@3.0.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg=="], - "@sentry/react/@sentry/browser": ["@sentry/browser@10.49.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.49.0", "@sentry-internal/feedback": "10.49.0", "@sentry-internal/replay": "10.49.0", "@sentry-internal/replay-canvas": "10.49.0", "@sentry/core": "10.49.0" } }, "sha512-bGCHc+wK2Dx67YoSbmtlt04alqWfQ+dasD/GVipVOq50gvw/BBIDHTEWRJEjACl+LrvszeY54V+24p8z4IgysA=="], + "@sentry/react/@sentry/browser": ["@sentry/browser@10.46.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.46.0", "@sentry-internal/feedback": "10.46.0", "@sentry-internal/replay": "10.46.0", "@sentry-internal/replay-canvas": "10.46.0", "@sentry/core": "10.46.0" } }, "sha512-80DmGlTk5Z2/OxVOzLNxwolMyouuAYKqG8KUcoyintZqHbF6kO1RulI610HmyUt3OagKeBCqt9S7w0VIfCRL+Q=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core": ["@sentry/bundler-plugin-core@4.9.1", "", { "dependencies": { "@babel/core": "^7.18.5", "@sentry/babel-plugin-component-annotate": "4.9.1", "@sentry/cli": "^2.57.0", "dotenv": "^16.3.1", "find-up": "^5.0.0", "glob": "^10.5.0", "magic-string": "0.30.8", "unplugin": "1.0.1" } }, "sha512-moii+w7N8k8WdvkX7qCDY9iRBlhgHlhTHTUQwF2FNMhBHuqlNpVcSJJqJMjFUQcjYMBDrZgxhfKV18bt5ixwlQ=="], + "@sentry/webpack-plugin/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "@sindresorhus/slugify/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "@sindresorhus/transliterate/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -6773,13 +6398,13 @@ "@tailwindcss/node/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="], "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], @@ -6791,14 +6416,10 @@ "@tanstack/router-plugin/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@tanstack/router-utils/diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], - "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], "@types/three/fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], - "@uiw/react-markdown-preview/remark-github-blockquote-alert": ["remark-github-blockquote-alert@1.3.1", "", { "dependencies": { "unist-util-visit": "^5.0.0" } }, "sha512-OPNnimcKeozWN1w8KVQEuHOxgN3L4rah8geMOLhA5vN9wITqU4FWD+G26tkEsCGHiOVDbISx+Se5rGZ+D1p0Jg=="], - "@upstash/qstash/jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="], "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], @@ -6833,15 +6454,17 @@ "app-builder-lib/dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="], - "app-builder-lib/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - "app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - "archiver-utils/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "archiver/buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], + + "archiver/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + + "archiver/tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], - "archiver-utils/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + "archiver-utils/glob": ["glob@10.5.0", "", { "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" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - "asyncbox/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], + "archiver-utils/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], "ava/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -6855,8 +6478,6 @@ "ava/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="], - "axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="], - "babel-jest/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -6881,7 +6502,7 @@ "cheerio/parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="], - "cheerio/undici": ["undici@7.24.8", "", {}, "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ=="], + "cheerio/undici": ["undici@7.24.4", "", {}, "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w=="], "chromium-bidi/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -6907,7 +6528,7 @@ "code-inspector-plugin/chalk": ["chalk@4.1.1", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg=="], - "code-red/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "compress-commons/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -6921,6 +6542,8 @@ "crc/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + "crc32-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="], @@ -6935,20 +6558,18 @@ "deep-rename-keys/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], + "degenerator/ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="], + "dir-compare/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "dmg-builder/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "dmg-license/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], - "dockerfile-language-service/vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.8", "", {}, "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q=="], - - "dot-prop/type-fest": ["type-fest@5.6.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA=="], + "dot-prop/type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="], "dotenv-expand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], - "duplexer2/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - "edgedriver/decamelize": ["decamelize@6.0.1", "", {}, "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ=="], "edgedriver/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], @@ -6967,8 +6588,6 @@ "engine.io/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], - "error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - "escodegen/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -6977,8 +6596,6 @@ "estree-util-build-jsx/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - "exceljs/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "execa/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], "expo/react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], @@ -7013,11 +6630,9 @@ "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "fstream/rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="], - "fumadocs-mdx/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], - "fumadocs-mdx/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], + "fumadocs-mdx/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="], "fumadocs-ui/lucide-react": ["lucide-react@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw=="], @@ -7035,24 +6650,6 @@ "globby/slash": ["slash@4.0.0", "", {}, "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew=="], - "graphql-config/jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], - - "graphql-config/minimatch": ["minimatch@4.2.6", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-i35PeWjrW3Kv6/Jken0yeuByzK4YWer7UWba3yWg8+v+5WQQtcKiQ1GqGP7Jc3jhUdlviU3gQf89ON+69eD8RA=="], - - "graphql-language-service/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "graphql-language-service-cli/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], - - "graphql-language-service-server/dotenv": ["dotenv@10.0.0", "", {}, "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="], - - "graphql-language-service-server/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "graphql-language-service-server/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "graphql-language-service-server/source-map-js": ["source-map-js@1.0.2", "", {}, "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="], - - "graphql-language-service-server/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - "gray-matter/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -7067,8 +6664,6 @@ "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], - "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - "istanbul-lib-instrument/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "jest-haste-map/jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], @@ -7089,15 +6684,13 @@ "katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], - "langium/vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], - "langsmith/@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="], "langsmith/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "langsmith/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "launch-ide/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "launch-ide/chalk": ["chalk@4.1.1", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg=="], "launch-ide/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], @@ -7105,15 +6698,13 @@ "libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], - "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "locate-app/type-fest": ["type-fest@4.26.0", "", {}, "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw=="], "make-fetch-happen/proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="], - "mastracode/@ai-sdk/openai": ["@ai-sdk/openai@3.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Wld+Rbc05KaUn08uBt06eEuwcgalcIFtIl32Yp+GxuZXUQwOb6YeAuq+C6da4ch6BurFoqEaLemJVwjBb7x+PQ=="], + "mastracode/@ai-sdk/openai": ["@ai-sdk/openai@3.0.48", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ALmj/53EXpcRqMbGpPJPP4UOSWw0q4VGpnDo7YctvsynjkrKDmoneDG/1a7VQnSPYHnJp6tTRMf5ZdxZ5whulg=="], - "mastracode/@ast-grep/napi": ["@ast-grep/napi@0.42.1", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.42.1", "@ast-grep/napi-darwin-x64": "0.42.1", "@ast-grep/napi-linux-arm64-gnu": "0.42.1", "@ast-grep/napi-linux-arm64-musl": "0.42.1", "@ast-grep/napi-linux-x64-gnu": "0.42.1", "@ast-grep/napi-linux-x64-musl": "0.42.1", "@ast-grep/napi-win32-arm64-msvc": "0.42.1", "@ast-grep/napi-win32-ia32-msvc": "0.42.1", "@ast-grep/napi-win32-x64-msvc": "0.42.1" } }, "sha512-+YEv9ElJi9azr8AYII79NxYXQRJsrUy1kUqZfxZfvPM7rhs3174mzB+qEE9Pl3sVKAJS5cevyT4lgLNV0AZK6A=="], + "mastracode/@ast-grep/napi": ["@ast-grep/napi@0.42.0", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.42.0", "@ast-grep/napi-darwin-x64": "0.42.0", "@ast-grep/napi-linux-arm64-gnu": "0.42.0", "@ast-grep/napi-linux-arm64-musl": "0.42.0", "@ast-grep/napi-linux-x64-gnu": "0.42.0", "@ast-grep/napi-linux-x64-musl": "0.42.0", "@ast-grep/napi-win32-arm64-msvc": "0.42.0", "@ast-grep/napi-win32-ia32-msvc": "0.42.0", "@ast-grep/napi-win32-x64-msvc": "0.42.0" } }, "sha512-f3DAjeC657EqbWN2In+girgbpvnKMV77bONyhuezXK4XQtvbGCB55u3CnNvQv6EP0caIBTtDHqO5CVyO6qY4LQ=="], "mastracode/@mastra/mcp": ["@mastra/mcp@1.5.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^14.2.1", "@modelcontextprotocol/sdk": "^1.27.1", "exit-hook": "^5.1.0", "fast-deep-equal": "^3.1.3", "uuid": "^13.0.0" }, "peerDependencies": { "@mastra/core": ">=1.0.0-0 <2.0.0-0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-I+YtghjjkKdlTtqVc1TTChnRTZ0HiMKq6o5UCjZGuGdK2oHlkTYLYd2rRZI9tIcEIXjG2bQz9OzlQhAaDd+TJw=="], @@ -7127,19 +6718,21 @@ "mermaid/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "metro/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + "metro/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], - "metro/hermes-parser": ["hermes-parser@0.33.3", "", { "dependencies": { "hermes-estree": "0.33.3" } }, "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA=="], - "metro/image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="], "metro/jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], - "metro/metro-runtime": ["metro-runtime@0.83.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA=="], + "metro/metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="], + + "metro/metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], - "metro/metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], + "metro/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "metro/serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], @@ -7147,25 +6740,23 @@ "metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "metro-babel-transformer/hermes-parser": ["hermes-parser@0.33.3", "", { "dependencies": { "hermes-estree": "0.33.3" } }, "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA=="], - - "metro-config/metro-runtime": ["metro-runtime@0.83.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-f+b3ue9AWTVlZe2Xrki6TAoFtKIqw30jwfk7GQ1rDUBQaE0ZQ+NkiMEtb9uwH7uAjJ87U7Tdx1Jg1OJqUfEVlA=="], + "metro-config/metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="], "metro-file-map/jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], - "metro-source-map/metro-symbolicate": ["metro-symbolicate@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.6", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-4nvkmv9T7ozhprlPwk/+xm0SVPsxly5kYyMHdNaOlFemFz4df9BanvD46Ac6OISu/4Idinzfk2KVb++6OfzPAQ=="], + "metro-source-map/metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="], "metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], - "metro-symbolicate/metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], + "metro-symbolicate/metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], "metro-symbolicate/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], - "metro-transform-worker/metro-source-map": ["metro-source-map@0.83.5", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.5", "nullthrows": "^1.1.1", "ob1": "0.83.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-VT9bb2KO2/4tWY9Z2yeZqTUao7CicKAOps9LUg2aQzsz+04QyuXL3qgf1cLUVRjA/D6G5u1RJAlN1w9VNHtODQ=="], + "metro-transform-worker/metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "miniflare/undici": ["undici@7.24.8", "", {}, "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ=="], + "miniflare/undici": ["undici@7.24.4", "", {}, "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w=="], "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], @@ -7187,8 +6778,6 @@ "node-gyp/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - "node-simctl/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - "node-simctl/rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], "node-simctl/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], @@ -7215,18 +6804,12 @@ "p-event/p-timeout": ["p-timeout@5.1.0", "", {}, "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew=="], - "parent-module/callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], "parse5-parser-stream/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - "periscopic/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - - "periscopic/is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], - "pino-pretty/pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="], "pino-pretty/secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], @@ -7241,9 +6824,9 @@ "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "posthog-node/@posthog/core": ["@posthog/core@1.25.2", "", {}, "sha512-h2FO7ut/BbfwpAXWpwdDHTzQgUo9ibDFEs6ZO+3cI3KPWQt5XwczK1OLAuPprcjm8T/jl0SH8jSFo5XdU4RbTg=="], + "posthog-node/@posthog/core": ["@posthog/core@1.24.3", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-nTyL1R/8V5vfdH37MbjXDYWFnUoxVijb2TnfJSNHz0+RBLtNnq0hNnBDCwWLl5yh1bzeJBYTT8UF+dV7D8y03w=="], - "posthog-react-native/@posthog/core": ["@posthog/core@1.25.2", "", {}, "sha512-h2FO7ut/BbfwpAXWpwdDHTzQgUo9ibDFEs6ZO+3cI3KPWQt5XwczK1OLAuPprcjm8T/jl0SH8jSFo5XdU4RbTg=="], + "posthog-react-native/@posthog/core": ["@posthog/core@1.24.3", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-nTyL1R/8V5vfdH37MbjXDYWFnUoxVijb2TnfJSNHz0+RBLtNnq0hNnBDCwWLl5yh1bzeJBYTT8UF+dV7D8y03w=="], "postject/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], @@ -7263,6 +6846,8 @@ "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + "proxy-agent/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "react-email/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], @@ -7295,6 +6880,8 @@ "readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "rehype-attr/unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], "resq/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], @@ -7337,26 +6924,14 @@ "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "string_decoder/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "supertap/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], - "svelte/css-tree": ["css-tree@2.3.1", "", { "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" } }, "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw=="], - - "svelte/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], - - "svelte/is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], - - "sync-fetch/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - "teen_process/bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - "temp/mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], "temp/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], @@ -7371,7 +6946,7 @@ "tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - "tsx/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], + "tsx/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="], "tunnel-rat/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], @@ -7381,36 +6956,10 @@ "uniwind/@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], - "unixify/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="], - - "unzipper/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - - "verror/core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], - - "vite/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], - - "vscode-css-languageservice/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-html-languageservice/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-json-languageservice/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-langservers-extracted/typescript": ["typescript@4.9.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="], - - "vscode-langservers-extracted/vscode-languageserver": ["vscode-languageserver@10.0.0-next.17", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.6-next.17" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-/bwO/E3RUzIkQ1BQ70gcLdZeM8xvK0JS7gMvtug7yiH0dzTjciqqQTUh3H9NEXsqYEjLzGwiXgRUkt6Z8fQV0Q=="], - - "vscode-langservers-extracted/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-languageserver/vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.2", "", { "dependencies": { "vscode-jsonrpc": "8.0.2", "vscode-languageserver-types": "3.17.2" } }, "sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg=="], + "vite/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="], "vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], - "vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-markdown-languageservice/@vscode/l10n": ["@vscode/l10n@0.0.10", "", {}, "sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ=="], - - "vscode-markdown-languageservice/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "wait-port/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "wait-port/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], @@ -7419,10 +6968,10 @@ "webdriverio/@types/node": ["@types/node@20.19.39", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw=="], - "webdriverio/archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], - "webdriverio/serialize-error": ["serialize-error@12.0.0", "", { "dependencies": { "type-fest": "^4.31.0" } }, "sha512-ZYkZLAvKTKQXWuh5XpBw7CdbSzagarX39WyZ2H07CDLC5/KfsRGlIXV8d4+tfqX1M7916mRqR1QfNHSij+c9Pw=="], + "webpack/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "wrangler/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], @@ -7439,17 +6988,9 @@ "xml-reader/eventemitter3": ["eventemitter3@2.0.3", "", {}, "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="], - "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], - - "yaml-language-server/vscode-json-languageservice": ["vscode-json-languageservice@4.1.8", "", { "dependencies": { "jsonc-parser": "^3.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", "vscode-uri": "^3.0.2" } }, "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg=="], - - "yaml-language-server/vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], - - "yaml-language-server/vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - "youch/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], - "zip-stream/archiver-utils": ["archiver-utils@3.0.4", "", { "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash.defaults": "^4.2.0", "lodash.difference": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw=="], + "zip-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], "zod-from-json-schema-v3/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -7497,7 +7038,7 @@ "@browserbasehq/stagehand/@anthropic-ai/sdk/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - "@browserbasehq/stagehand/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.82", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-vtoCSEBGPcxzChI3eqe9C9AJSlc/WUZp92tzpOqVd4B6Tnu4583S+qR7TknB0tPta15TEoOIkK0ENW6D/DgRJQ=="], + "@browserbasehq/stagehand/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.75", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.23", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-5bZN8RKr/HHBbFPd0ql+5mKTe3DngsyS4y9983qUdG+AYWIoMi3VlU7Gr0J6YNYYD4sxkZdLMfAVWVpFGb5WSA=="], "@browserbasehq/stagehand/ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-60GYsRj5wIJQRcq5YwYJq4KhwLeStceXEJiZdecP1miiH+6FMmrnc7lZDOJoQ6m9lrudEb+uI4LEwddLz5+rPQ=="], @@ -7511,7 +7052,7 @@ "@develar/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], @@ -7529,7 +7070,7 @@ "@electron/rebuild/ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], @@ -7593,8 +7134,6 @@ "@expo/cli/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - "@expo/metro-config/lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "@expo/metro-config/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], "@expo/metro-config/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], @@ -7617,7 +7156,7 @@ "@expo/metro-config/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "@expo/metro/metro-source-map/ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], + "@expo/metro/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], "@expo/metro/metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], @@ -7633,12 +7172,6 @@ "@fastify/otel/@opentelemetry/instrumentation/import-in-the-middle": ["import-in-the-middle@2.0.6", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw=="], - "@graphql-tools/code-file-loader/globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "@graphql-tools/graphql-file-loader/globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "@graphql-tools/json-file-loader/globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], @@ -7651,6 +7184,8 @@ "@prisma/instrumentation/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.207.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ=="], + "@prisma/instrumentation/@opentelemetry/instrumentation/import-in-the-middle": ["import-in-the-middle@2.0.6", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw=="], + "@puppeteer/browsers/tar-fs/tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], "@react-email/preview-server/next/@next/env": ["@next/env@16.0.7", "", {}, "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw=="], @@ -7693,27 +7228,27 @@ "@react-native/community-cli-plugin/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], - "@react-native/community-cli-plugin/metro/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="], + "@react-native/community-cli-plugin/metro/hermes-parser": ["hermes-parser@0.33.3", "", { "dependencies": { "hermes-estree": "0.33.3" } }, "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA=="], "@react-native/community-cli-plugin/metro/image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="], "@react-native/community-cli-plugin/metro/jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], - "@react-native/community-cli-plugin/metro/metro-babel-transformer": ["metro-babel-transformer@0.83.6", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.35.0", "metro-cache-key": "0.83.6", "nullthrows": "^1.1.1" } }, "sha512-1AnuazBpzY3meRMr04WUw14kRBkV0W3Ez+AA75FAeNpRyWNN5S3M3PHLUbZw7IXq7ZeOzceyRsHStaFrnWd+8w=="], + "@react-native/community-cli-plugin/metro/metro-babel-transformer": ["metro-babel-transformer@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.33.3", "nullthrows": "^1.1.1" } }, "sha512-d9FfmgUEVejTiSb7bkQeLRGl6aeno2UpuPm3bo3rCYwxewj03ymvOn8s8vnS4fBqAPQ+cE9iQM40wh7nGXR+eA=="], - "@react-native/community-cli-plugin/metro/metro-cache": ["metro-cache@0.83.6", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.6" } }, "sha512-DpvZE32feNkqfZkI4Fic7YI/Kw8QP9wdl1rC4YKPrA77wQbI9vXbxjmfkCT/EGwBTFOPKqvIXo+H3BNe93YyiQ=="], + "@react-native/community-cli-plugin/metro/metro-cache": ["metro-cache@0.83.5", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.5" } }, "sha512-oH+s4U+IfZyg8J42bne2Skc90rcuESIYf86dYittcdWQtPfcaFXWpByPyTuWk3rR1Zz3Eh5HOrcVImfEhhJLng=="], - "@react-native/community-cli-plugin/metro/metro-cache-key": ["metro-cache-key@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-5gdK4PVpgNOHi7xCGrgesNP1AuOA2TiPqpcirGXZi4RLLzX1VMowpkgTVtBfpQQCqWoosQF9yrSo9/KDQg1eBg=="], + "@react-native/community-cli-plugin/metro/metro-cache-key": ["metro-cache-key@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Ycl8PBajB7bhbAI7Rt0xEyiF8oJ0RWX8EKkolV1KfCUlC++V/GStMSGpPLwnnBZXZWkCC5edBPzv1Hz1Yi0Euw=="], - "@react-native/community-cli-plugin/metro/metro-file-map": ["metro-file-map@0.83.6", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Jg3oN604C7GWbQwFAUXt8KsbMXeKfsxbZ5HFy4XFM3ggTS+ja9QgUmq9B613kgXv3G4M6rwiI6cvh9TRly4x3w=="], + "@react-native/community-cli-plugin/metro/metro-file-map": ["metro-file-map@0.83.5", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-ZEt8s3a1cnYbn40nyCD+CsZdYSlwtFh2kFym4lo+uvfM+UMMH+r/BsrC6rbNClSrt+B7rU9T+Te/sh/NL8ZZKQ=="], - "@react-native/community-cli-plugin/metro/metro-resolver": ["metro-resolver@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-lAwR/FsT1uJ5iCt4AIsN3boKfJ88aN8bjvDT5FwBS0tKeKw4/sbdSTWlFxc7W/MUTN5RekJ3nQkJRIWsvs28tA=="], + "@react-native/community-cli-plugin/metro/metro-resolver": ["metro-resolver@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-7p3GtzVUpbAweJeCcUJihJeOQl1bDuimO5ueo1K0BUpUtR41q5EilbQ3klt16UTPPMpA+tISWBtsrqU556mY1A=="], - "@react-native/community-cli-plugin/metro/metro-symbolicate": ["metro-symbolicate@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.6", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-4nvkmv9T7ozhprlPwk/+xm0SVPsxly5kYyMHdNaOlFemFz4df9BanvD46Ac6OISu/4Idinzfk2KVb++6OfzPAQ=="], + "@react-native/community-cli-plugin/metro/metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="], - "@react-native/community-cli-plugin/metro/metro-transform-plugins": ["metro-transform-plugins@0.83.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-V+zoY2Ul0v0BW6IokJkTud3raXmDdbdwkUQ/5eiSoy0jKuKMhrDjdH+H5buCS5iiJdNbykOn69Eip+Sqymkodg=="], + "@react-native/community-cli-plugin/metro/metro-transform-plugins": ["metro-transform-plugins@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-KxYKzZL+lt3Os5H2nx7YkbkWVduLZL5kPrE/Yq+Prm/DE1VLhpfnO6HtPs8vimYFKOa58ncl60GpoX0h7Wm0Vw=="], - "@react-native/community-cli-plugin/metro/metro-transform-worker": ["metro-transform-worker@0.83.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.83.6", "metro-babel-transformer": "0.83.6", "metro-cache": "0.83.6", "metro-cache-key": "0.83.6", "metro-minify-terser": "0.83.6", "metro-source-map": "0.83.6", "metro-transform-plugins": "0.83.6", "nullthrows": "^1.1.1" } }, "sha512-G5kDJ/P0ZTIf57t3iyAd5qIXbj2Wb1j7WtIDh82uTFQHe2Mq2SO9aXG9j1wI+kxZlIe58Z22XEXIKMl89z0ibQ=="], + "@react-native/community-cli-plugin/metro/metro-transform-worker": ["metro-transform-worker@0.83.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.83.5", "metro-babel-transformer": "0.83.5", "metro-cache": "0.83.5", "metro-cache-key": "0.83.5", "metro-minify-terser": "0.83.5", "metro-source-map": "0.83.5", "metro-transform-plugins": "0.83.5", "nullthrows": "^1.1.1" } }, "sha512-8N4pjkNXc6ytlP9oAM6MwqkvUepNSW39LKYl9NjUMpRDazBQ7oBpQDc8Sz4aI8jnH6AGhF7s1m/ayxkN1t04yA=="], "@react-native/community-cli-plugin/metro/serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], @@ -7721,9 +7256,9 @@ "@react-native/community-cli-plugin/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], - "@react-native/community-cli-plugin/metro-config/metro-cache": ["metro-cache@0.83.6", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.6" } }, "sha512-DpvZE32feNkqfZkI4Fic7YI/Kw8QP9wdl1rC4YKPrA77wQbI9vXbxjmfkCT/EGwBTFOPKqvIXo+H3BNe93YyiQ=="], + "@react-native/community-cli-plugin/metro-config/metro-cache": ["metro-cache@0.83.5", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.5" } }, "sha512-oH+s4U+IfZyg8J42bne2Skc90rcuESIYf86dYittcdWQtPfcaFXWpByPyTuWk3rR1Zz3Eh5HOrcVImfEhhJLng=="], - "@react-native/community-cli-plugin/metro-core/metro-resolver": ["metro-resolver@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-lAwR/FsT1uJ5iCt4AIsN3boKfJ88aN8bjvDT5FwBS0tKeKw4/sbdSTWlFxc7W/MUTN5RekJ3nQkJRIWsvs28tA=="], + "@react-native/community-cli-plugin/metro-core/metro-resolver": ["metro-resolver@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-7p3GtzVUpbAweJeCcUJihJeOQl1bDuimO5ueo1K0BUpUtR41q5EilbQ3klt16UTPPMpA+tISWBtsrqU556mY1A=="], "@react-native/dev-middleware/chrome-launcher/lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], @@ -7731,21 +7266,71 @@ "@sentry/cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], - "@sentry/electron/@sentry/node/@sentry/node-core": ["@sentry/node-core@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0", "@sentry/opentelemetry": "10.47.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/resources": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/context-async-hooks", "@opentelemetry/core", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/instrumentation", "@opentelemetry/resources", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-qv6LsqHbkQmd0aQEUox/svRSz26J+l4gGjFOUNEay2armZu9XLD+Ct89jpFgZD5oIPNAj2jraodTRqydXiwS5w=="], + "@sentry/electron/@sentry/node/@fastify/otel": ["@fastify/otel@0.16.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.208.0", "@opentelemetry/semantic-conventions": "^1.28.0", "minimatch": "^10.0.3" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.211.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.211.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-h0nrZEC/zvI994nhg7EgQ8URIHt0uDTwN90r3qQUdZORS455bbx+YebnGeEuFghUT0HlJSrLF4iHw67f+odY+Q=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-amqplib": ["@opentelemetry/instrumentation-amqplib@0.58.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-fjpQtH18J6GxzUZ+cwNhWUpb71u+DzT7rFkg5pLssDGaEber91Y2WNGdpVpwGivfEluMlNMZumzjEqfg8DeKXQ=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-connect": ["@opentelemetry/instrumentation-connect@0.54.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.38" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-43RmbhUhqt3uuPnc16cX6NsxEASEtn8z/cYV8Zpt6EP4p2h9s4FNuJ4Q9BbEQ2C0YlCCB/2crO1ruVz/hWt8fA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-dataloader": ["@opentelemetry/instrumentation-dataloader@0.28.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ExXGBp0sUj8yhm6Znhf9jmuOaGDsYfDES3gswZnKr4MCqoBWQdEFn6EoDdt5u+RdbxQER+t43FoUihEfTSqsjA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-express": ["@opentelemetry/instrumentation-express@0.59.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pMKV/qnHiW/Q6pmbKkxt0eIhuNEtvJ7sUAyee192HErlr+a1Jx+FZ3WjfmzhQL1geewyGEiPGkmjjAgNY8TgDA=="], - "@sentry/electron/@sentry/node/@sentry/opentelemetry": ["@sentry/opentelemetry@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-f6Hw2lrpCjlOksiosP0Z2jK/+l+21SIdoNglVeG/sttMyx8C8ywONKh0Ha50sFsvB1VaB8n94RKzzf3hkh9V3g=="], + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-fs": ["@opentelemetry/instrumentation-fs@0.30.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-n3Cf8YhG7reaj5dncGlRIU7iT40bxPOjsBEA5Bc1a1g6e9Qvb+JFJ7SEiMlPbUw4PBmxE3h40ltE8LZ3zVt6OA=="], - "@sentry/electron/@sentry/node/import-in-the-middle": ["import-in-the-middle@3.0.1", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA=="], + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-generic-pool": ["@opentelemetry/instrumentation-generic-pool@0.54.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-8dXMBzzmEdXfH/wjuRvcJnUFeWzZHUnExkmFJ2uPfa31wmpyBCMxO59yr8f/OXXgSogNgi/uPo9KW9H7LMIZ+g=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-graphql": ["@opentelemetry/instrumentation-graphql@0.58.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-+yWVVY7fxOs3j2RixCbvue8vUuJ1inHxN2q1sduqDB0Wnkr4vOzVKRYl/Zy7B31/dcPS72D9lo/kltdOTBM3bQ=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-hapi": ["@opentelemetry/instrumentation-hapi@0.57.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Os4THbvls8cTQTVA8ApLfZZztuuqGEeqog0XUnyRW7QVF0d/vOVBEcBCk1pazPFmllXGEdNbbat8e2fYIWdFbw=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-http": ["@opentelemetry/instrumentation-http@0.211.0", "", { "dependencies": { "@opentelemetry/core": "2.5.0", "@opentelemetry/instrumentation": "0.211.0", "@opentelemetry/semantic-conventions": "^1.29.0", "forwarded-parse": "2.1.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-n0IaQ6oVll9PP84SjbOCwDjaJasWRHi6BLsbMLiT6tNj7QbVOkuA5sk/EfZczwI0j5uTKl1awQPivO/ldVtsqA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-ioredis": ["@opentelemetry/instrumentation-ioredis@0.59.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-875UxzBHWkW+P4Y45SoFM2AR8f8TzBMD8eO7QXGCyFSCUMP5s9vtt/BS8b/r2kqLyaRPK6mLbdnZznK3XzQWvw=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-kafkajs": ["@opentelemetry/instrumentation-kafkajs@0.20.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.30.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-yJXOuWZROzj7WmYCUiyT27tIfqBrVtl1/TwVbQyWPz7rL0r1Lu7kWjD0PiVeTCIL6CrIZ7M2s8eBxsTAOxbNvw=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-knex": ["@opentelemetry/instrumentation-knex@0.55.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FtTL5DUx5Ka/8VK6P1VwnlUXPa3nrb7REvm5ddLUIeXXq4tb9pKd+/ThB1xM/IjefkRSN3z8a5t7epYw1JLBJQ=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-koa": ["@opentelemetry/instrumentation-koa@0.59.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.36.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0" } }, "sha512-K9o2skADV20Skdu5tG2bogPKiSpXh4KxfLjz6FuqIVvDJNibwSdu5UvyyBzRVp1rQMV6UmoIk6d3PyPtJbaGSg=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-lru-memoizer": ["@opentelemetry/instrumentation-lru-memoizer@0.55.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FDBfT7yDGcspN0Cxbu/k8A0Pp1Jhv/m7BMTzXGpcb8ENl3tDj/51U65R5lWzUH15GaZA15HQ5A5wtafklxYj7g=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-mongodb": ["@opentelemetry/instrumentation-mongodb@0.64.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pFlCJjweTqVp7B220mCvCld1c1eYKZfQt1p3bxSbcReypKLJTwat+wbL2YZoX9jPi5X2O8tTKFEOahO5ehQGsA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-mongoose": ["@opentelemetry/instrumentation-mongoose@0.57.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MthiekrU/BAJc5JZoZeJmo0OTX6ycJMiP6sMOSRTkvz5BrPMYDqaJos0OgsLPL/HpcgHP7eo5pduETuLguOqcg=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-mysql": ["@opentelemetry/instrumentation-mysql@0.57.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/mysql": "2.15.27" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HFS/+FcZ6Q7piM7Il7CzQ4VHhJvGMJWjx7EgCkP5AnTntSN5rb5Xi3TkYJHBKeR27A0QqPlGaCITi93fUDs++Q=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-mysql2": ["@opentelemetry/instrumentation-mysql2@0.57.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@opentelemetry/sql-common": "^0.41.2" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-nHSrYAwF7+aV1E1V9yOOP9TchOodb6fjn4gFvdrdQXiRE7cMuffyLLbCZlZd4wsspBzVwOXX8mpURdRserAhNA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-pg": ["@opentelemetry/instrumentation-pg@0.63.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.34.0", "@opentelemetry/sql-common": "^0.41.2", "@types/pg": "8.15.6", "@types/pg-pool": "2.0.7" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-dKm/ODNN3GgIQVlbD6ZPxwRc3kleLf95hrRWXM+l8wYo+vSeXtEpQPT53afEf6VFWDVzJK55VGn8KMLtSve/cg=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-redis": ["@opentelemetry/instrumentation-redis@0.59.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/redis-common": "^0.38.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-JKv1KDDYA2chJ1PC3pLP+Q9ISMQk6h5ey+99mB57/ARk0vQPGZTTEb4h4/JlcEpy7AYT8HIGv7X6l+br03Neeg=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-tedious": ["@opentelemetry/instrumentation-tedious@0.30.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.33.0", "@types/tedious": "^4.0.14" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-bZy9Q8jFdycKQ2pAsyuHYUHNmCxCOGdG6eg1Mn75RvQDccq832sU5OWOBnc12EFUELI6icJkhR7+EQKMBam2GA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-undici": ["@opentelemetry/instrumentation-undici@0.21.0", "", { "dependencies": { "@opentelemetry/core": "^2.0.0", "@opentelemetry/instrumentation": "^0.211.0", "@opentelemetry/semantic-conventions": "^1.24.0" }, "peerDependencies": { "@opentelemetry/api": "^1.7.0" } }, "sha512-gok0LPUOTz2FQ1YJMZzaHcOzDFyT64XJ8M9rNkugk923/p6lDGms/cRW1cqgqp6N6qcd6K6YdVHwPEhnx9BWbw=="], + + "@sentry/electron/@sentry/node/@prisma/instrumentation": ["@prisma/instrumentation@7.2.0", "", { "dependencies": { "@opentelemetry/instrumentation": "^0.207.0" }, "peerDependencies": { "@opentelemetry/api": "^1.8" } }, "sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g=="], + + "@sentry/electron/@sentry/node/@sentry/node-core": ["@sentry/node-core@10.42.0", "", { "dependencies": { "@sentry/core": "10.42.0", "@sentry/opentelemetry": "10.42.0", "import-in-the-middle": "^2.0.6" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/resources": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/context-async-hooks", "@opentelemetry/core", "@opentelemetry/instrumentation", "@opentelemetry/resources", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-9tf3fPV6M071aps72D+PEtdQPTuj+SuqO2+PpTfdPP5ZL4TTKYo3VK0li76SL+5wGdTFGV5qmsokHq9IRBA0iA=="], + + "@sentry/electron/@sentry/node/@sentry/opentelemetry": ["@sentry/opentelemetry@10.42.0", "", { "dependencies": { "@sentry/core": "10.42.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-5vsYz683iihzlIj3sT1+tEixf0awwXK86a+aYsnMHrTXJDrkBDq4U0ZT+yxdPfJlkaxRtYycFR08SXr2pSm7Eg=="], + + "@sentry/electron/@sentry/node/import-in-the-middle": ["import-in-the-middle@2.0.6", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw=="], "@sentry/node-core/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="], "@sentry/node/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="], - "@sentry/react/@sentry/browser/@sentry-internal/feedback": ["@sentry-internal/feedback@10.49.0", "", { "dependencies": { "@sentry/core": "10.49.0" } }, "sha512-JNsUBGv0faCFE7MeZUH99Y9lU9qq3LBALbLxpE1x7ngNrQnVYRlcFgdqaD/btNBKr8awjYL8gmcSkHBWskGqLQ=="], + "@sentry/react/@sentry/browser/@sentry-internal/feedback": ["@sentry-internal/feedback@10.46.0", "", { "dependencies": { "@sentry/core": "10.46.0" } }, "sha512-c4pI/z9nZCQXe9GYEw/hE/YTY9AxGBp8/wgKI+T8zylrN35SGHaXv63szzE1WbI8lacBY8lBF7rstq9bQVCaHw=="], - "@sentry/react/@sentry/browser/@sentry-internal/replay": ["@sentry-internal/replay@10.49.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.49.0", "@sentry/core": "10.49.0" } }, "sha512-IEy4lwHVMiRE3JAcn+kFKjsTgalDOCSTf20SoFd+nkt6rN/k1RDyr4xpdfF//Kj3UdeTmbuibYjK5H/FLhhnGg=="], + "@sentry/react/@sentry/browser/@sentry-internal/replay": ["@sentry-internal/replay@10.46.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.46.0", "@sentry/core": "10.46.0" } }, "sha512-JBsWeXG6bRbxBFK8GzWymWGOB9QE7Kl57BeF3jzgdHTuHSWZ2mRnAmb1K05T4LU+gVygk6yW0KmdC8Py9Qzg9A=="], - "@sentry/react/@sentry/browser/@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.49.0", "", { "dependencies": { "@sentry-internal/replay": "10.49.0", "@sentry/core": "10.49.0" } }, "sha512-7D/NrgH1Qwx5trDYaaTSSJmCb1yVQQLqFG4G/S9x2ltzl9876lSGJL8UeW8ReNQgF3CDAcwbmm/9aXaVSBUNZA=="], + "@sentry/react/@sentry/browser/@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.46.0", "", { "dependencies": { "@sentry-internal/replay": "10.46.0", "@sentry/core": "10.46.0" } }, "sha512-ub314MWUsekVCuoH0/HJbbimlI24SkV745UW2pj9xRbxOAEf1wjkmIzxKrMDbTgJGuEunug02XZVdJFJUzOcDw=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/@sentry/babel-plugin-component-annotate": ["@sentry/babel-plugin-component-annotate@4.9.1", "", {}, "sha512-0gEoi2Lb54MFYPOmdTfxlNKxI7kCOvNV7gP8lxMXJ7nCazF5OqOOZIVshfWjDLrc0QrSV6XdVvwPV9GDn4wBMg=="], @@ -7755,8 +7340,6 @@ "@sentry/vite-plugin/@sentry/bundler-plugin-core/magic-string": ["magic-string@0.30.8", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ=="], - "@tailwindcss/node/lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], @@ -7795,9 +7378,11 @@ "app-builder-lib/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], - "archiver-utils/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "archiver-utils/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "archiver-utils/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "archiver-utils/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], "ava/figures/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -7845,12 +7430,10 @@ "deep-rename-keys/kind-of/is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], - "dir-compare/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "dir-compare/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "dmg-license/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "duplexer2/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - "edgedriver/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], "electron-winstaller/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], @@ -7867,7 +7450,7 @@ "fastembed/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], - "filelist/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -7897,69 +7480,59 @@ "friendly-words/express/type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - "fstream/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "fumadocs-mdx/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], - "fumadocs-mdx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], - - "fumadocs-mdx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], - - "fumadocs-mdx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], - - "fumadocs-mdx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], - - "fumadocs-mdx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + "fumadocs-mdx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="], - "fumadocs-mdx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + "fumadocs-mdx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="], - "fumadocs-mdx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + "fumadocs-mdx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="], - "fumadocs-mdx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + "fumadocs-mdx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="], - "fumadocs-mdx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + "fumadocs-mdx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="], - "fumadocs-mdx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + "fumadocs-mdx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="], - "fumadocs-mdx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + "fumadocs-mdx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="], - "fumadocs-mdx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + "fumadocs-mdx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="], - "fumadocs-mdx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + "fumadocs-mdx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="], - "fumadocs-mdx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + "fumadocs-mdx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="], - "fumadocs-mdx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + "fumadocs-mdx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="], - "fumadocs-mdx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + "fumadocs-mdx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="], - "fumadocs-mdx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + "fumadocs-mdx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="], - "fumadocs-mdx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + "fumadocs-mdx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="], - "fumadocs-mdx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + "fumadocs-mdx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="], - "fumadocs-mdx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + "fumadocs-mdx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="], - "fumadocs-mdx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + "fumadocs-mdx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="], - "fumadocs-mdx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + "fumadocs-mdx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="], - "fumadocs-mdx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + "fumadocs-mdx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="], - "fumadocs-mdx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + "fumadocs-mdx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="], - "fumadocs-mdx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + "fumadocs-mdx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="], - "fumadocs-mdx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "fumadocs-mdx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="], - "graphql-config/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "fumadocs-mdx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="], - "graphql-language-service-cli/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + "fumadocs-mdx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="], - "graphql-language-service-cli/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], + "fumadocs-mdx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="], - "graphql-language-service-server/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "fumadocs-mdx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="], "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], @@ -7973,41 +7546,45 @@ "jszip/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "jszip/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.42.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VtO4DX20ODCfRBwv1I71lZx+qlrhlMbt9Rpo3LozoaUpHnLmyFMBSgpUal5KTd1SCKUK8ekJGgxpKWo27H4AVQ=="], + "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.42.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-V2uaKP6QZLb60iFHK0IiXAcwSoUliiDJ3c1zLLzHnBFyCbTKC4b3L3XtkiyKsnpET+uzY7hQLpTIAhW5aOCX4w=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.42.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HOPvjsrsASvfkRJGCd/++KZvfDCtBx6v8DKTEzzlc6fQJlhiRMPKe8T4d5I2T2rgV5pHsyJLSBLqEK7m346NTw=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-linux-arm64-gnu": ["@ast-grep/napi-linux-arm64-gnu@0.42.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-wmt59yzvcZT4Z5XpxB1B1FoFrc32l0vmy2G7yrY2lG9qP2M157mWdp1T50h2XoYrotyRhCyLDXP70SiTZHZkaQ=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.42.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-q3jt+a6kDbXgbCSuIqaxjgLbTCDYGE2yb1o6metpsGbW+xVZR4ATYMJ8izyYhn2sQungTfUNn2/vo/2Bhbvpxg=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-linux-arm64-musl": ["@ast-grep/napi-linux-arm64-musl@0.42.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cnU+H0drvdkApQDJEcBsYGlPq2gk3l2Xxq0y8EmcxAXYXDNkz+Gc2vfvyM7ib2jD9Y51+cQIsb0RFzA2g9VnZQ=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-linux-arm64-gnu": ["@ast-grep/napi-linux-arm64-gnu@0.42.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-+e2ThyRiBZATlcdgfrD7uYy9oWVS6/AdUTnC3xOwR+lCz80lr87kmcmeK6XN6hBwaqncBBkKV3ECMA8ibZPUZA=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-linux-x64-gnu": ["@ast-grep/napi-linux-x64-gnu@0.42.1", "", { "os": "linux", "cpu": "x64" }, "sha512-gY+PtqbFtFlR8rCL9F6GEPuymqLhh2eG/e8Ly01Z/S5x3e357nNaF69xAvNRpYi/HnEUZ5cE1MzshDCjubqE1A=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-linux-arm64-musl": ["@ast-grep/napi-linux-arm64-musl@0.42.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-f/oW3KaHuOMuBkCcvI6R71xM9SvkdUVKHhbJEtBFo5D1j6CjY9ipWdjlk9mOJ2KLLM6uYdjjvkJkBPlPuFTukg=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-linux-x64-musl": ["@ast-grep/napi-linux-x64-musl@0.42.1", "", { "os": "linux", "cpu": "x64" }, "sha512-yDTlIgFOzglpzs3Ua9w43uVeEW4csf80F5/n2FqCK5pip4Iyfu21Q+M8iC9AmTRl/OGHVI48ieuPwOD9i1i6hA=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-linux-x64-gnu": ["@ast-grep/napi-linux-x64-gnu@0.42.0", "", { "os": "linux", "cpu": "x64" }, "sha512-y9T/Tm6V6zkmcAJlWXUO0ACYLSlk5o5NVU+AYun7NzDWIM86Y3lnoDF5WxeZKonVoaGAnkCXVlNH8Tsr/NTQWw=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-win32-arm64-msvc": ["@ast-grep/napi-win32-arm64-msvc@0.42.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-6WQhKEfZmtfMSIOzluMoBaQhNqfRKXzj5y2YA2U0Y3x7HxNAZBO067y8xlSMddKFN/FtCwft8GFktFxqSYWl1w=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-linux-x64-musl": ["@ast-grep/napi-linux-x64-musl@0.42.0", "", { "os": "linux", "cpu": "x64" }, "sha512-t1PwL6YweDL63QDK3TC9QTKROcVgN4XoMxlp/zN2NYvCUM90mSvqh/Py/ouchzluHaqCzEeEp9089WFEDWwQOA=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-win32-ia32-msvc": ["@ast-grep/napi-win32-ia32-msvc@0.42.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-ET2vRrsHo0e4JJbCrejzDcDPsfTmRaYK9VIpq1MqXXAUvLoiMly+cQYZ64MWdXTlgITKMXCYxhCbFPTn/9XZaQ=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-win32-arm64-msvc": ["@ast-grep/napi-win32-arm64-msvc@0.42.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-bxKLXF1JmU33BoJKrbWcGsG7Xmk2zCQaUjmeHrxhgBhg2w2zo3CSf5S6DOyOp13hefgLXBLn6oXNzXgqpX/+lA=="], - "mastracode/@ast-grep/napi/@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.42.1", "", { "os": "win32", "cpu": "x64" }, "sha512-NAeA2Q6jp7F9uXtSuG12c1xjTzipXFCTvuAcEBnsTwBXq0kdPV6H6Y4GZJVcDhsHk3TX4sGlQGkuV/6FT2Ngig=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-win32-ia32-msvc": ["@ast-grep/napi-win32-ia32-msvc@0.42.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-+/XbHDN+558rXwB2BylWPHj/cczRGDKivToHS2120TGQePmUetspu93wltqzAD7SVJnBILc2sEK1T1/jutZEvw=="], - "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], + "mastracode/@ast-grep/napi/@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.42.0", "", { "os": "win32", "cpu": "x64" }, "sha512-/5PTpk7EFuqwdJyKleX2gPztL5j73Nq/cdkEJQq1Fbx+ze+UM75JniW3D7J7WZygN58+EN9DAxpc2QOlK32urQ=="], "metro-file-map/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "metro-symbolicate/metro-source-map/ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], + "metro-symbolicate/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], - "metro-transform-worker/metro-source-map/ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], + "metro-transform-worker/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], "metro-transform-worker/metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], - "metro/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], + "metro/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "metro/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "metro/metro-source-map/ob1": ["ob1@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-vNKPYC8L5ycVANANpF/S+WZHpfnRWKx/F3AYP4QMn6ZJTh+l2HOrId0clNkEmua58NB9vmI9Qh7YOoV/4folYg=="], + "metro/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="], + + "metro/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], @@ -8041,7 +7618,7 @@ "react-native/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "shell-env/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], @@ -8065,63 +7642,61 @@ "supertap/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "svelte/css-tree/mdn-data": ["mdn-data@2.0.30", "", {}, "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="], - "temp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], - "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="], - "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="], - "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="], - "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="], - "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="], - "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="], - "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="], - "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="], - "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="], - "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="], - "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="], - "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="], - "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="], - "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="], - "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="], - "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="], - "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="], - "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="], - "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="], - "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="], - "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="], - "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="], - "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="], - "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="], - "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="], - "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="], "uniwind/@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], @@ -8153,82 +7728,66 @@ "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], - "unzipper/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], - - "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], + "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="], - "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="], - "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.4", "", { "os": "android", "cpu": "arm64" }, "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw=="], - "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.4", "", { "os": "android", "cpu": "x64" }, "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw=="], - "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ=="], - "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw=="], - "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw=="], - "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ=="], - "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.4", "", { "os": "linux", "cpu": "arm" }, "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg=="], - "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA=="], - "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA=="], - "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA=="], - "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw=="], - "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA=="], - "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.4", "", { "os": "linux", "cpu": "none" }, "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw=="], - "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA=="], - "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.4", "", { "os": "linux", "cpu": "x64" }, "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA=="], - "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q=="], - "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.4", "", { "os": "none", "cpu": "x64" }, "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg=="], - "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow=="], - "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ=="], - "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.4", "", { "os": "none", "cpu": "arm64" }, "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg=="], - "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g=="], - "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg=="], - "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw=="], - "vscode-langservers-extracted/vscode-languageserver/vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.6-next.17", "", { "dependencies": { "vscode-jsonrpc": "9.0.0-next.11", "vscode-languageserver-types": "3.17.6-next.6" } }, "sha512-HW72YcFsuckfK6oPVuysRXhKiIFJoUvXgspPHvCMWpwe2x9aq2oGZDUSvKx4m/qUGB27+iu8ijAxsFlljYl2IQ=="], - - "vscode-languageserver/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.0.2", "", {}, "sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ=="], - - "vscode-languageserver/vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.2", "", {}, "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA=="], + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="], "webdriver/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "webdriverio/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - "webdriverio/archiver/archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], - - "webdriverio/archiver/buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], - - "webdriverio/archiver/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], - - "webdriverio/archiver/tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], - - "webdriverio/archiver/zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], - "webdriverio/serialize-error/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + "webpack/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], @@ -8285,8 +7844,6 @@ "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "zip-stream/archiver-utils/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "@a2a-js/sdk/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "@a2a-js/sdk/express/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], @@ -8307,8 +7864,6 @@ "@browserbasehq/stagehand/@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - "@browserbasehq/stagehand/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="], - "@browserbasehq/stagehand/puppeteer-core/@puppeteer/browsers/tar-fs": ["tar-fs@3.1.2", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw=="], "@browserbasehq/stagehand/puppeteer-core/chromium-bidi/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="], @@ -8349,21 +7904,23 @@ "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "@prisma/instrumentation/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="], + "@react-email/preview-server/next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "@react-native/babel-plugin-codegen/@react-native/codegen/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "@react-native/community-cli-plugin/@react-native/dev-middleware/chrome-launcher/lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="], "@react-native/community-cli-plugin/@react-native/dev-middleware/serve-static/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "@react-native/community-cli-plugin/metro/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="], + "@react-native/community-cli-plugin/metro/hermes-parser/hermes-estree": ["hermes-estree@0.33.3", "", {}, "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg=="], "@react-native/community-cli-plugin/metro/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "@react-native/community-cli-plugin/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.6", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Vx3/Ne9Q+EIEDLfKzZUOtn/rxSNa/QjlYxc42nvK4Mg8mB6XUgd3LXX5ZZVq7lzQgehgEqLrbgShJPGfeF8PnQ=="], + "@react-native/community-cli-plugin/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-Toe4Md1wS1PBqbvB0cFxBzKEVyyuYTUb0sgifAZh/mSvLH84qA1NAWik9sISWatzvfWf3rOGoUoO5E3f193a3Q=="], "@react-native/dev-middleware/chrome-launcher/lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -8373,6 +7930,16 @@ "@react-native/dev-middleware/serve-static/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + "@sentry/electron/@sentry/node/@fastify/otel/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.211.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-swFdZq8MCdmdR22jTVGQDhwqDzcI4M10nhjXkLr1EsIzXgZBqm4ZlmmcWsg3TSNf+3mzgOiqveXmBLZuDi2Lgg=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-http/@opentelemetry/core": ["@opentelemetry/core@2.5.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ=="], + + "@sentry/electron/@sentry/node/@opentelemetry/instrumentation-pg/@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="], + + "@sentry/electron/@sentry/node/@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.207.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.207.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA=="], + "@sentry/electron/@sentry/node/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], @@ -8383,7 +7950,7 @@ "@wdio/config/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - "@wdio/config/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "@wdio/config/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "@wdio/config/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -8391,11 +7958,15 @@ "app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - "archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "archiver-utils/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], + + "archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "cacache/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "chromium-edge-launcher/lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -8427,14 +7998,6 @@ "friendly-words/express/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "fstream/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - - "graphql-config/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "graphql-language-service-cli/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "graphql-language-service-server/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "node-simctl/rimraf/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "node-simctl/rimraf/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], @@ -8443,7 +8006,7 @@ "pkg-conf/find-up/locate-path/p-locate": ["p-locate@6.0.0", "", { "dependencies": { "p-limit": "^4.0.0" } }, "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw=="], - "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "readdir-glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -8477,30 +8040,18 @@ "uniwind/@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], - "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], - "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], - "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], - "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="], "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "uniwind/@tailwindcss/oxide/@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "vscode-langservers-extracted/vscode-languageserver/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@9.0.0-next.11", "", {}, "sha512-u6LElQNbSiE9OugEEmrUKwH6+8BpPz2S5MDHvQUqHL//I4Q8GPikKLOUf856UnbLkZdhxaPrExac1lA3XwpIPA=="], - - "vscode-langservers-extracted/vscode-languageserver/vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.17.6-next.6", "", {}, "sha512-aiJY5/yW+xzw7KPNlwi3gQtddq/3EIn5z8X8nCgJfaiAij2R1APKePngv+MUdLdYJBVTLu+Qa0ODsT+pHgYguQ=="], - - "webdriverio/archiver/archiver-utils/glob": ["glob@10.5.0", "", { "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" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "webdriverio/archiver/readable-stream/string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "webdriverio/archiver/zip-stream/compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="], - - "zip-stream/archiver-utils/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - "@a2a-js/sdk/express/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "@a2a-js/sdk/express/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -8527,7 +8078,7 @@ "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - "@react-native/babel-plugin-codegen/@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "@react-native/babel-plugin-codegen/@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "@react-native/codegen/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -8543,9 +8094,13 @@ "@react-native/dev-middleware/serve-static/send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "@sentry/electron/@sentry/node/@fastify/otel/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg=="], + + "@sentry/electron/@sentry/node/@prisma/instrumentation/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.207.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ=="], + "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -8555,6 +8110,10 @@ "@wdio/config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -8563,7 +8122,7 @@ "cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -8571,15 +8130,9 @@ "friendly-words/express/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "fstream/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - - "graphql-language-service-cli/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "graphql-language-service-server/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - "node-simctl/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "node-simctl/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], "node-simctl/rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -8587,17 +8140,7 @@ "react-native/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - - "webdriverio/archiver/archiver-utils/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "webdriverio/archiver/zip-stream/compress-commons/crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], - - "zip-stream/archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "@expo/cli/ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], @@ -8623,14 +8166,16 @@ "@wdio/config/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "fstream/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], @@ -8641,14 +8186,6 @@ "temp/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "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" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - - "webdriverio/archiver/archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "zip-stream/archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "@sentry/vite-plugin/@sentry/bundler-plugin-core/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -8656,15 +8193,5 @@ "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "node-simctl/rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "webdriverio/archiver/archiver-utils/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "webdriverio/archiver/archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], } } diff --git a/docs/V2_WORKSPACE_DIFF_VIEWS.md b/docs/V2_WORKSPACE_DIFF_VIEWS.md new file mode 100644 index 00000000000..e58bc632cd7 --- /dev/null +++ b/docs/V2_WORKSPACE_DIFF_VIEWS.md @@ -0,0 +1,190 @@ +# How v2 workspace diff views work + +An explainer for every place the UI shows "what changed" for a workspace, what comparison runs under the hood, and why. + +Written for people who don't know git. If you do know git: this doc maps each UI surface to the specific git command and explains why we picked that comparison over the alternatives. + +Each surface below has a matching `describe` block in `packages/host-service/src/trpc/router/git/v2-diff-surfaces.integration.test.ts` (titled `Surface A`, `Surfaces B/C`, etc.) that spins up a real on-disk repo and verifies the behavior described here. + +--- + +## The setup (what git is actually doing) + +Git tracks your project as a chain of **snapshots**. Every time you commit, you add a new snapshot. The chain the whole team agrees is "the real version" is usually called **main**. + +When you start work, you don't modify main directly. You make a parallel chain starting from main โ€” add your own snapshots to it โ€” and later merge them back. The spot on main where your parallel chain started is your **fork point**. + +(Unrelated to "fork a GitHub repo." Confusingly the same word. Different meaning.) + +A picture of what's on disk after you've made some commits: + +```text +main: A โ€” B โ€” C โ€” D โ€” E โ† main keeps advancing because + \ other people merge their stuff +your branch: X โ€” Y โ€” Z โ† you added X, Y, Z +``` + +- Your **fork point** is `C`. +- Your branch's latest snapshot is `Z`. +- Main's latest snapshot is `E` (it moved forward while you worked). + +### Local vs. "real" + +Your laptop has its own copy of main. GitHub has the actual main. These drift: your laptop's main might still think the latest is `C` while GitHub already has `E`. When your laptop is out of date we call that **stale**. The up-to-date version (on GitHub or wherever) is the **source of truth**. + +A complication: some people contribute to someone else's project by first copying the whole project onto their own GitHub account (this IS what "fork a GitHub repo" means). In that case, the project on their own GitHub account goes out of date the moment they stop syncing it, and the actual source of truth is someone else's GitHub account entirely. So we can't just assume "the remote called `origin` is fresh main" โ€” for those users, it isn't. + +**The old code assumed `origin` was always the real main.** That was wrong for anyone contributing from a fork. The code now reads git's configured "which remote is this branch actually tracking" setting, which is always correct. + +--- + +## The three ways we compare + +When we show you "what changed," we pick one of three comparison flavors under the hood. + +### Flavor 1 โ€” "current main vs. current me" +Compare main's latest snapshot directly to your branch's latest snapshot, and show every line that differs between them. + +**Problem:** if someone else merged to main while you were working, their changes show up as if *you* deleted them (because their changes are on main but not on your branch). Your "I changed X files" number would grow every time someone else merged, even though you did nothing. + +This is what v2 used before the fix. That's why users saw the number creep up. + +### Flavor 2 โ€” "me since I forked" +Compare the snapshot at your fork point to your branch's latest snapshot. Ignore everything main did after you forked. + +This is what GitHub shows on a pull request's "Files changed" tab. It's stable โ€” the number only changes when *you* change things. + +**This is what v2 uses now.** + +### Flavor 3 โ€” "list of my new commits" +Not a line-level diff โ€” just a list of your new snapshots. "Show me the commits I added that aren't on main." + +--- + +## Where each flavor shows up + +### A. Creating a new workspace + +**What you see:** You hit "Create" in the new workspace modal. A new folder appears on disk. + +**What git does:** Starts your new branch from a specific point. + +**Before:** We used your laptop's copy of main, which might be days behind the real main. + +**Now:** We use the real, up-to-date main from the server. For most people that's just `origin/main`. For people contributing from a GitHub fork, it's the actual source repo (not their outdated copy). + +**Why it matters:** Starting from a stale version means your workspace begins behind before you do anything. You'll hit merge conflicts later because main has moved on while you were "behind" the whole time. + +**Code:** `packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts` `create` procedure. + +--- + +### B. The small number badge next to each workspace in the left sidebar (and "+N โˆ’N" on hover) + +**What you see:** A count of changed files in the left nav, and on hover a breakdown of added/removed lines. + +**Flavor:** "Me since I forked" (Flavor 2), against real main. + +**Before:** Flavor 1 against your laptop's copy of main. The number drifted upward as main advanced, and for fork-a-repo users it was comparing against their own stale fork, not the real project. + +**Now:** Stable. Only changes when you change things. + +**Code path:** `apps/desktop/src/renderer/hooks/host-service/useDiffStats/useDiffStats.ts` โ†’ `git.getStatus` โ†’ reads `againstBase` response field. + +--- + +### C. The "Changes" tab inside a workspace (file list + totals at the top) + +**What you see:** Inside a workspace, the Changes tab: list of files, each with "+N โˆ’N," and a header showing totals. + +**What git does:** Three separate comparisons merged into one list: + +1. **Files different from main, since you forked** (Flavor 2) โ€” same as B. +2. **Staged** โ€” files you've told git you're ready to commit but haven't yet (you ran `git add` on them). +3. **Unstaged** โ€” files you've edited but haven't told git about yet. + +If the same file appears in multiple buckets, the most recent reality wins. + +**Code path:** `apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/hooks/useChangeset/useChangeset.ts` โ†’ `git.getStatus` โ†’ merges `againstBase`, `staged`, `unstaged`. + +--- + +### D. Clicking a file in Changes tab to see the actual diff + +**What you see:** Click a file โ†’ side-by-side or inline view of the old and new content. + +**Flavor:** Flavor 2 โ€” the "original" side is the file's content at your fork point, not at main's current tip. + +**Why:** Matches what the file list (C) already filters by. If main happened to also modify that same file in some unrelated way after you forked, we don't show those unrelated changes as part of your diff. (This differs from the pre-fix version which used Flavor 1 โ€” sometimes noisy for files both branches had touched.) + +**Code:** `git.getDiff` with category `against-base` โ†’ runs `git merge-base HEAD` to find the fork-point commit, then shows `:` against `HEAD:`. + +--- + +### E. The "Commits" section inside a workspace + +**What you see:** A list of commits you've added on this branch since forking. + +**Flavor:** Flavor 3 (list of my new commits), against real main. + +**Code:** `git.listCommits` โ†’ `git log ..HEAD`. + +--- + +### F. Ahead/behind counts in branch lists + +**What you see:** Branch rows in the picker sometimes show "3 ahead, 1 behind main." + +**What git does:** Counts commits on each side of the fork point that the other doesn't have. + +**Fix:** Same story as everywhere else โ€” the "main" in "ahead/behind main" is now the real main, not the hardcoded `origin` copy. + +**Code:** `git.listBranches` โ†’ `buildBranch` โ†’ `git rev-list --left-right --count`. + +--- + +### G. Clicking a specific commit to see its files + +**What you see:** Click a commit in the list โ†’ see which files that one commit changed. + +**What git does:** Compares the commit to the one immediately before it. Not a branch-vs-branch comparison, so no "which main?" question. + +**Status:** Already correct before this PR. Untouched. + +**Code:** `git.getCommitFiles`. + +--- + +## Separately: renamed files + +Unrelated to the main/upstream stuff above. If you renamed a file (e.g. `foo.ts` โ†’ `bar.ts`) and changed some lines during the rename, the sidebar used to show `+0 โˆ’0` for that file. + +**Why it was wrong:** Git has two output formats for line counts. The text format represents renames as a single entry labeled `foo.ts => bar.ts`. The old code was trying to look up "bar.ts" in a map whose key was literally `foo.ts => bar.ts`, so it never matched and we'd get zero. + +**Fix:** Switched to git's binary-safe output format (`--numstat -z`), which separates the old and new names into distinct fields. The parser now records line counts under both names. Renamed files show their real line counts. + +**Code:** `parseNumstat` in `packages/host-service/src/trpc/router/git/utils/git-helpers.ts`. + +--- + +## Edge cases + +- **No configured upstream on local main** (very rare โ€” someone manually untracked the branch). We fall back to `origin/` โ€” same behavior as before the fix. These users are no worse off than before, but also don't benefit from fork-aware comparisons. +- **Disconnected histories** (local main and upstream main share no commits). `git merge-base` returns nothing; the per-file diff (D) falls back to comparing against the base tip directly. Would only happen in broken repos. +- **Workspace branch name matches a remote branch incidentally** (e.g. you named your workspace branch `main`). The workspace creation path guards against this by keying on the picker's "is this a local branch or remote-only" hint. + +--- + +## Summary table + +| Surface | What git does | Base ref | +| --- | --- | --- | +| A. New workspace start-point | `git worktree add` from a specific commit | Real main (branch's configured upstream) | +| B. Sidebar badge + hover totals | Flavor 2 file-level diff | Real main | +| C. Changes tab list + totals | Flavor 2 + staged + unstaged, merged | Real main | +| D. Per-file diff view | Flavor 2 content comparison (via merge-base) | Real main | +| E. Commits section | Flavor 3 commit listing | Real main | +| F. Ahead/behind counts | Symmetric commit count | Real main | +| G. Per-commit file list | Parent-to-commit content comparison | N/A (commit-to-commit) | + +"Real main" throughout means: the remote-tracking branch that your local default branch is configured to track (e.g. `upstream/main` for fork contributors, `origin/main` for everyone else). diff --git a/fly.toml b/fly.toml deleted file mode 100644 index 30322bcb42f..00000000000 --- a/fly.toml +++ /dev/null @@ -1,32 +0,0 @@ -app = "superset-electric" -primary_region = "iad" - -[build] -image = "electricsql/electric:1.4.13" - -[[vm]] -memory = "512mb" -cpu_kind = "shared" -cpus = 2 - -[env] -ELECTRIC_DATABASE_USE_IPV6 = "true" -ELECTRIC_MAX_CONCURRENT_REQUESTS = '{"initial": 3000, "existing": 10000}' - -[http_service] -internal_port = 3000 -force_https = true -auto_stop_machines = "off" -auto_start_machines = true -min_machines_running = 1 - -[[http_service.checks]] -interval = "10s" -timeout = "2s" -grace_period = "20s" -method = "GET" -path = "/v1/health" - -[mounts] -source = "electric_data" -destination = "/var/lib/electric" diff --git a/packages/auth/package.json b/packages/auth/package.json index 8d67ae5b058..f773870d635 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -27,10 +27,10 @@ "typecheck": "tsc --noEmit --emitDeclarationOnly false" }, "dependencies": { - "@better-auth/api-key": "1.5.6", - "@better-auth/expo": "1.5.6", - "@better-auth/oauth-provider": "1.5.6", - "@better-auth/stripe": "1.5.6", + "@better-auth/api-key": "1.6.5", + "@better-auth/expo": "1.6.5", + "@better-auth/oauth-provider": "1.6.5", + "@better-auth/stripe": "1.6.5", "@superset/db": "workspace:*", "@superset/email": "workspace:*", "@superset/shared": "workspace:*", @@ -39,9 +39,9 @@ "@upstash/qstash": "^2.8.4", "@upstash/ratelimit": "^2.0.4", "@upstash/redis": "^1.34.3", - "better-auth": "1.5.6", + "better-auth": "1.6.5", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "resend": "^4.0.1", "stripe": "^20.2.0", "zod": "^4.3.5" diff --git a/packages/chat/src/client/hooks/use-chat-display/use-chat-display.ts b/packages/chat/src/client/hooks/use-chat-display/use-chat-display.ts index 84d112bdfc7..90a8bbf1b2a 100644 --- a/packages/chat/src/client/hooks/use-chat-display/use-chat-display.ts +++ b/packages/chat/src/client/hooks/use-chat-display/use-chat-display.ts @@ -113,7 +113,7 @@ function getLegacyImagePayload( } export function useChatDisplay(options: UseChatDisplayOptions) { - const { sessionId, cwd, enabled = true, fps = 60 } = options; + const { sessionId, cwd, enabled = true, fps = 4 } = options; const utils = chatRuntimeServiceTrpc.useUtils(); const [commandError, setCommandError] = useState(null); const sessionCommandInput = @@ -126,8 +126,6 @@ export function useChatDisplay(options: UseChatDisplayOptions) { refetchInterval: refetchIntervalMs, refetchIntervalInBackground: true, refetchOnWindowFocus: false, - staleTime: 0, - gcTime: 0, } as const; const displayQuery = chatRuntimeServiceTrpc.session.getDisplayState.useQuery( diff --git a/packages/chat/src/server/desktop/auth/provider-ids.ts b/packages/chat/src/server/desktop/auth/provider-ids.ts index 35d90973686..dca854f3d2e 100644 --- a/packages/chat/src/server/desktop/auth/provider-ids.ts +++ b/packages/chat/src/server/desktop/auth/provider-ids.ts @@ -1,7 +1,5 @@ -export const ANTHROPIC_AUTH_PROVIDER_ID = "anthropic"; -export const INCEPTION_AUTH_PROVIDER_ID = "inception"; -export const OPENAI_AUTH_PROVIDER_ID = "openai-codex"; -export const OPENAI_AUTH_PROVIDER_IDS = [ +export { + ANTHROPIC_AUTH_PROVIDER_ID, OPENAI_AUTH_PROVIDER_ID, - "openai", -] as const; + OPENAI_AUTH_PROVIDER_IDS, +} from "../../shared/auth-provider-ids"; diff --git a/packages/chat/src/server/shared/auth-provider-ids.ts b/packages/chat/src/server/shared/auth-provider-ids.ts new file mode 100644 index 00000000000..373408bd24e --- /dev/null +++ b/packages/chat/src/server/shared/auth-provider-ids.ts @@ -0,0 +1,8 @@ +export const ANTHROPIC_AUTH_PROVIDER_ID = "anthropic"; +export const OPENAI_AUTH_PROVIDER_ID = "openai-codex"; +// Mastracode historically wrote OpenAI under "openai" before the Codex split. +// Read both when resolving credentials. +export const OPENAI_AUTH_PROVIDER_IDS = [ + OPENAI_AUTH_PROVIDER_ID, + "openai", +] as const; diff --git a/packages/chat/src/server/shared/small-model/get-small-model.test.ts b/packages/chat/src/server/shared/small-model/get-small-model.test.ts new file mode 100644 index 00000000000..f6c278fa64e --- /dev/null +++ b/packages/chat/src/server/shared/small-model/get-small-model.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from "bun:test"; +import { isAnthropicApiKey, isOpenAIApiKey } from "./get-small-model"; + +describe("isAnthropicApiKey", () => { + it("accepts a real-shaped key", () => { + expect( + isAnthropicApiKey( + "sk-ant-api03-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ), + ).toBe(true); + }); + + it("rejects dev placeholders", () => { + expect(isAnthropicApiKey("dummy")).toBe(false); + expect(isAnthropicApiKey("placeholder")).toBe(false); + expect(isAnthropicApiKey("")).toBe(false); + }); + + it("rejects OAuth access tokens (sk-ant-oatโ€ฆ) sent as api keys", () => { + // OAuth tokens fail when sent via x-api-key. Filter them so we fall + // through to the OAuth path which sends them via Authorization Bearer. + expect( + isAnthropicApiKey("sk-ant-oat-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + ).toBe(false); + }); + + it("rejects keys with the prefix but absurd lengths", () => { + expect(isAnthropicApiKey("sk-ant-api")).toBe(false); + }); + + it("rejects unrelated provider keys", () => { + expect(isAnthropicApiKey("sk-proj-foo")).toBe(false); + }); +}); + +describe("isOpenAIApiKey", () => { + it("accepts legacy, project, and service-account key shapes", () => { + expect( + isOpenAIApiKey("sk-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + ).toBe(true); + expect( + isOpenAIApiKey("sk-proj-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + ).toBe(true); + expect( + isOpenAIApiKey("sk-svcacct-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + ).toBe(true); + }); + + it("rejects dev placeholders and obviously-fake values", () => { + expect(isOpenAIApiKey("dummy")).toBe(false); + expect(isOpenAIApiKey("sk-")).toBe(false); + expect(isOpenAIApiKey("")).toBe(false); + }); + + it("rejects values without the sk- prefix", () => { + expect(isOpenAIApiKey("api-key-aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")).toBe(false); + }); +}); diff --git a/packages/chat/src/server/shared/small-model/get-small-model.ts b/packages/chat/src/server/shared/small-model/get-small-model.ts index 8810b06fe95..58cb4837fa1 100644 --- a/packages/chat/src/server/shared/small-model/get-small-model.ts +++ b/packages/chat/src/server/shared/small-model/get-small-model.ts @@ -1,349 +1,177 @@ -import { existsSync, readFileSync } from "node:fs"; -import { homedir } from "node:os"; -import { join } from "node:path"; import { createAnthropic } from "@ai-sdk/anthropic"; import { createOpenAI } from "@ai-sdk/openai"; import { createAuthStorage } from "mastracode"; import { - type ClaudeCredentials, - getCredentialsFromConfig as getAnthropicCredentialsFromConfig, - getCredentialsFromKeychain as getAnthropicCredentialsFromKeychain, - getAnthropicProviderOptions, - isClaudeCredentialExpired, -} from "../../desktop/auth/anthropic"; -import { - getOpenAICredentialsFromAnySource, - isOpenAICredentialExpired, - type OpenAICredentials, -} from "../../desktop/auth/openai"; -import { OPENAI_AUTH_PROVIDER_ID } from "../../desktop/auth/provider-ids"; -import { parseAnthropicEnvText } from "../../desktop/chat-service/anthropic-env-config"; + ANTHROPIC_AUTH_PROVIDER_ID, + OPENAI_AUTH_PROVIDER_IDS, +} from "../auth-provider-ids"; const ANTHROPIC_SMALL_MODEL_ID = "claude-haiku-4-5-20251001"; -const OPENAI_API_SMALL_MODEL_ID = "gpt-4o-mini"; -const OPENAI_CODEX_SMALL_MODEL_ID = "gpt-5.1-codex-mini"; -const OPENAI_CODEX_API_ENDPOINT = - "https://chatgpt.com/backend-api/codex/responses"; - -export type SmallModelProviderId = "anthropic" | "openai"; - -export interface SmallModelCandidate { - providerId: SmallModelProviderId; - providerName: string; - credentialKind: "apiKey" | "oauth"; - credentialSource: string; - createModel: () => unknown; -} - -/** - * FORK NOTE: ported from upstream #3517's `getSmallModel()` but rebuilt - * on top of fork's credential resolvers so it still honors: - * - Anthropic OAuth (claude-code-20250219 / oauth-2025-04-20 headers via - * getAnthropicProviderOptions โ€” upstream lost this when it switched to - * apiKey-only resolution) - * - Anthropic managed env config (~/.superset/chat-anthropic-env.json - * with ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN; AUTH_TOKEN is - * routed through the OAuth header path, not apiKey) - * - OpenAI Codex OAuth (custom fetch that rewrites to the Codex - * backend endpoint and refreshes access tokens via mastracode) - * - OpenAI API key in mastracode AuthStorage's `openai-codex` slot - * - * Upstream's version collapsed credentials to apiKey-only. We keep the - * simpler `getSmallModel()` export for upstream-compatible callers - * (runtime.ts title generation) and add `getSmallModelCandidates()` so - * the fork callSmallModel shim can iterate providers in order and - * record attempts properly (restoring provider fallback behavior). - */ -function buildCandidates(): SmallModelCandidate[] { - const candidates: SmallModelCandidate[] = []; +const OPENAI_SMALL_MODEL_ID = "gpt-4o-mini"; - const envApiKey = process.env.ANTHROPIC_API_KEY?.trim(); - if (envApiKey) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: "apiKey", - credentialSource: "env:ANTHROPIC_API_KEY", - createModel: () => - createAnthropic({ apiKey: envApiKey })(ANTHROPIC_SMALL_MODEL_ID), - }); - } +const MIN_API_KEY_LENGTH = 30; - const anthropicStored = resolveAnthropicCredentialsSync(); - if (anthropicStored) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: anthropicStored.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: anthropicStored.source, - createModel: () => - createAnthropic(getAnthropicProviderOptions(anthropicStored))( - ANTHROPIC_SMALL_MODEL_ID, - ), - }); - } +// OAuth tokens issued through the Claude Code flow are accepted by the +// Anthropic API only when these companion headers are sent alongside the +// `Authorization: Bearer` header. Mastracode hands us the token; we own +// the wiring into createAnthropic and the request-time headers. +const ANTHROPIC_OAUTH_HEADERS = { + "anthropic-beta": "claude-code-20250219,oauth-2025-04-20", + "user-agent": "claude-cli/2.1.2 (external, cli)", + "x-app": "cli", +} as const; - const anthropicEnvConfigCred = resolveAnthropicEnvConfigCredential(); - if (anthropicEnvConfigCred) { - candidates.push({ - providerId: "anthropic", - providerName: "Anthropic", - credentialKind: - anthropicEnvConfigCred.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: anthropicEnvConfigCred.source, - createModel: () => - createAnthropic(getAnthropicProviderOptions(anthropicEnvConfigCred))( - ANTHROPIC_SMALL_MODEL_ID, - ), - }); - } +type AuthStorage = ReturnType; - const envOpenAIKey = process.env.OPENAI_API_KEY?.trim(); - if (envOpenAIKey) { - candidates.push({ - providerId: "openai", - providerName: "OpenAI", - credentialKind: "apiKey", - credentialSource: "env:OPENAI_API_KEY", - createModel: () => - createOpenAI({ apiKey: envOpenAIKey }).chat(OPENAI_API_SMALL_MODEL_ID), - }); - } +let cachedAuthStorage: AuthStorage | null = null; - const openaiCreds = getOpenAICredentialsFromAnySource(); - if (openaiCreds && !isOpenAICredentialExpired(openaiCreds)) { - candidates.push({ - providerId: "openai", - providerName: "OpenAI", - credentialKind: openaiCreds.kind === "oauth" ? "oauth" : "apiKey", - credentialSource: openaiCreds.source, - createModel: () => - openaiCreds.kind === "oauth" - ? createOpenAICodexOAuthModel(openaiCreds) - : createOpenAI({ apiKey: openaiCreds.apiKey }).chat( - OPENAI_API_SMALL_MODEL_ID, - ), - }); +function getAuthStorage(): AuthStorage { + if (!cachedAuthStorage) { + cachedAuthStorage = createAuthStorage(); } - - return candidates; + cachedAuthStorage.reload(); + return cachedAuthStorage; } -export function getSmallModelCandidates(): SmallModelCandidate[] { - return buildCandidates(); +/** + * Anthropic API keys are issued in the form `sk-ant-apiโ€ฆ` (currently + * `sk-ant-api03-โ€ฆ`). Reject anything else โ€” most importantly OAuth access + * tokens (`sk-ant-oatโ€ฆ`), which Anthropic rejects when sent as `x-api-key`, + * and dev placeholders like `dummy`. + */ +export function isAnthropicApiKey(key: string): boolean { + return key.startsWith("sk-ant-api") && key.length >= MIN_API_KEY_LENGTH; } /** - * Returns the first viable small-model AI-SDK LanguageModel or null. - * Upstream-compatible surface for simple single-model callers - * (runtime.ts title generation, ai-name.ts workspace naming). - * - * Iterates every candidate and returns the first one whose - * `createModel()` does not throw, so a broken-but-listed credential - * (e.g. stale cached account id) doesn't block the next provider. - * Runtime-level failures (expired OAuth 401, rate limits) still need - * to be handled by the caller โ€” those surface when the returned - * model is actually invoked, not when it's constructed. + * OpenAI keys all start with `sk-` (legacy `sk-โ€ฆ`, project `sk-proj-โ€ฆ`, + * service-account `sk-svcacct-โ€ฆ`). The length floor catches placeholders. */ -export function getSmallModel(): unknown | null { - for (const candidate of buildCandidates()) { - try { - return candidate.createModel(); - } catch { - // Try the next candidate. - } - } - return null; +export function isOpenAIApiKey(key: string): boolean { + return key.startsWith("sk-") && key.length >= MIN_API_KEY_LENGTH; } -// ---- Anthropic credential resolution helpers ------------------------------- +function isObjectRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} -/** - * Synchronous Anthropic credential resolver. Fork's - * `getCredentialsFromAnySource` is async because it may kick a - * mastracode token refresh. For the small-model candidate list we need - * a sync decision, so we stick to synchronous sources (config file, - * keychain, auth-storage main slot). If the resulting OAuth token is - * actually expired, createAnthropic will 401 and the shim falls - * through to the next candidate. - */ -function resolveAnthropicCredentialsSync(): ClaudeCredentials | null { - // Walk the sync sources in priority order and return the first - // non-expired credential. Unlike getCredentialsFromAnySource() we do - // NOT fall back to a known-expired credential at the end โ€” expired - // OAuth tokens would poison buildCandidates() and block the later - // env-config / OpenAI candidates, which matter for getSmallModel()'s - // direct callers where we can't retry after a 401. - const sources: Array<() => ClaudeCredentials | null> = [ - () => { - try { - return getAnthropicCredentialsFromConfig(); - } catch { - return null; - } - }, - () => { - try { - return getAnthropicCredentialsFromKeychain(); - } catch { - return null; - } - }, - () => resolveAnthropicFromStoreSync(), - ]; - for (const resolve of sources) { - const credential = resolve(); - if (!credential) continue; - if (!isClaudeCredentialExpired(credential)) return credential; +type AnthropicResolved = + | { kind: "apiKey"; key: string } + | { kind: "oauth"; accessToken: string }; + +async function resolveAnthropic(): Promise { + const env = process.env.ANTHROPIC_API_KEY?.trim(); + if (env && isAnthropicApiKey(env)) { + return { kind: "apiKey", key: env }; } - return null; -} -function resolveAnthropicFromStoreSync(): ClaudeCredentials | null { try { - const storage = createAuthStorage(); - storage.reload(); - const raw = storage.get("anthropic"); - if (!raw || typeof raw !== "object") return null; - const value = raw as Record; - if ( - value.type === "api_key" && - typeof value.key === "string" && - value.key.trim().length > 0 - ) { - return { - apiKey: value.key.trim(), - source: "auth-storage", - kind: "apiKey", - }; + const authStorage = getAuthStorage(); + + // Settings-saved API keys are stored at `apikey:`. Prefer + // these over whatever sits in the main slot โ€” otherwise an OAuth + // login (which writes to the main slot) would mask a stored API key + // the user explicitly added. + const storedApiKey = authStorage + .getStoredApiKey(ANTHROPIC_AUTH_PROVIDER_ID) + ?.trim(); + if (storedApiKey && isAnthropicApiKey(storedApiKey)) { + return { kind: "apiKey", key: storedApiKey }; } + + const credential = authStorage.get(ANTHROPIC_AUTH_PROVIDER_ID); + if (!isObjectRecord(credential)) return null; + if ( - value.type === "oauth" && - typeof value.access === "string" && - value.access.trim().length > 0 + credential.type === "api_key" && + typeof credential.key === "string" && + isAnthropicApiKey(credential.key.trim()) ) { - return { - apiKey: value.access.trim(), - source: "auth-storage", - kind: "oauth", - expiresAt: - typeof value.expires === "number" ? value.expires : undefined, - }; + return { kind: "apiKey", key: credential.key.trim() }; } - } catch { - // Fall through to null. - } - return null; -} -function resolveAnthropicEnvConfigCredential(): ClaudeCredentials | null { - try { - const supersetHome = - process.env.SUPERSET_HOME_DIR?.trim() || join(homedir(), ".superset"); - const path = join(supersetHome, "chat-anthropic-env.json"); - if (!existsSync(path)) return null; - const parsed = JSON.parse(readFileSync(path, "utf-8")) as { - envText?: string; - }; - if (typeof parsed.envText !== "string") return null; - const variables = parseAnthropicEnvText(parsed.envText); - const apiKey = variables.ANTHROPIC_API_KEY?.trim(); - if (apiKey) { - // `source: "config"` keeps us inside fork's ClaudeCredentials - // union; the actual display label comes from - // SmallModelCandidate.credentialSource below. - return { apiKey, source: "config", kind: "apiKey" }; - } - const authToken = variables.ANTHROPIC_AUTH_TOKEN?.trim(); - if (authToken) { - // FORK NOTE: AUTH_TOKEN must flow through the OAuth path - // (authToken + anthropic-beta / x-app headers) โ€” routing it - // through `apiKey` was the original PR #313 regression. - return { apiKey: authToken, source: "config", kind: "oauth" }; + if (credential.type === "oauth") { + // Mastracode's getApiKey returns a fresh access token, refreshing + // via the Claude Code OAuth flow when expired and persisting the + // new credential back to auth.json. This replaces the custom + // refresh dance we used to maintain in this package. + const accessToken = await authStorage.getApiKey( + ANTHROPIC_AUTH_PROVIDER_ID, + ); + if (typeof accessToken === "string" && accessToken.trim().length > 0) { + return { kind: "oauth", accessToken: accessToken.trim() }; + } } - } catch { - // Swallow โ€” missing / malformed config falls back to other sources. + } catch (error) { + console.warn("[get-small-model] anthropic auth resolution failed:", error); } + return null; } -// ---- OpenAI Codex OAuth model ---------------------------------------------- +async function resolveOpenAIApiKey(): Promise { + const env = process.env.OPENAI_API_KEY?.trim(); + if (env && isOpenAIApiKey(env)) return env; -function createOpenAICodexOAuthModel(credentials: OpenAICredentials) { - const authStorage = createAuthStorage(); - const openAIAuthProviderId = - credentials.providerId ?? OPENAI_AUTH_PROVIDER_ID; - const oauthFetchImpl = async ( - url: Parameters[0], - init?: Parameters[1], - ): Promise => { - authStorage.reload(); - const storedCredential = authStorage.get(openAIAuthProviderId); - if (!storedCredential || storedCredential.type !== "oauth") { - throw new Error("Not logged in to OpenAI Codex. Reconnect OpenAI."); - } - - let accessToken = storedCredential.access; - if ( - typeof storedCredential.expires === "number" && - Date.now() >= storedCredential.expires - ) { - const refreshedToken = await authStorage.getApiKey(openAIAuthProviderId); - if (!refreshedToken) { - throw new Error( - "Failed to refresh OpenAI Codex token. Please reconnect OpenAI.", - ); + try { + const authStorage = getAuthStorage(); + for (const providerId of OPENAI_AUTH_PROVIDER_IDS) { + // Same precedence reasoning as Anthropic: dedicated apikey: slot + // before the main slot. + const stored = authStorage.getStoredApiKey(providerId)?.trim(); + if (stored && isOpenAIApiKey(stored)) return stored; + + const credential = authStorage.get(providerId); + if ( + isObjectRecord(credential) && + credential.type === "api_key" && + typeof credential.key === "string" && + isOpenAIApiKey(credential.key.trim()) + ) { + return credential.key.trim(); } - accessToken = refreshedToken; - authStorage.reload(); } + } catch (error) { + console.warn("[get-small-model] openai auth resolution failed:", error); + } - const refreshedCredential = authStorage.get(openAIAuthProviderId); - const accountId = - refreshedCredential && - typeof refreshedCredential === "object" && - "accountId" in refreshedCredential && - typeof refreshedCredential.accountId === "string" && - refreshedCredential.accountId.trim().length > 0 - ? refreshedCredential.accountId.trim() - : credentials.accountId?.trim() || undefined; + return null; +} - // biome-ignore-start lint/suspicious/noExplicitAny: fetch signature varies across runtimes (bun vs. node vs. electron) and the cross-package typecheck context loses the DOM Request type overloads. - const baseRequest = new Request(url as any, init as any); - // biome-ignore-end lint/suspicious/noExplicitAny: matching pair - const parsedUrl = new URL(baseRequest.url); - const shouldRewrite = - parsedUrl.pathname.includes("/v1/responses") || - parsedUrl.pathname.includes("/chat/completions"); - const outgoingRequest = new Request( - shouldRewrite ? OPENAI_CODEX_API_ENDPOINT : baseRequest.url, - baseRequest, - ); - const headers = new Headers(outgoingRequest.headers); - headers.delete("authorization"); - headers.set("Authorization", `Bearer ${accessToken}`); - if (accountId) { - headers.set("ChatGPT-Account-Id", accountId); - } +/** + * Returns an AI-SDK `LanguageModel` for small-model tasks (branch naming, + * title generation). Returns `null` if no usable credentials are available. + * + * Resolution order: + * 1. ANTHROPIC_API_KEY env var (validated) + * 2. mastracode auth storage โ€” Anthropic api key + * 3. mastracode auth storage โ€” Anthropic OAuth (refreshed on the fly) + * 4. OPENAI_API_KEY env var (validated) + * 5. mastracode auth storage โ€” OpenAI api key (`openai-codex` / `openai`) + * + * API keys are validated by prefix + minimum length so dev placeholders + * (e.g. `ANTHROPIC_API_KEY=dummy` from a sample .env) fall through to the + * next path instead of being sent to the API and failing 401. + */ +export async function getSmallModel(): Promise { + const anthropic = await resolveAnthropic(); + if (anthropic?.kind === "apiKey") { + return createAnthropic({ apiKey: anthropic.key })(ANTHROPIC_SMALL_MODEL_ID); + } + if (anthropic?.kind === "oauth") { + return createAnthropic({ + authToken: anthropic.accessToken, + headers: ANTHROPIC_OAUTH_HEADERS, + })(ANTHROPIC_SMALL_MODEL_ID); + } - return fetch( - new Request(outgoingRequest, { - headers, - }), - ); - }; - const bunFetch = globalThis.fetch as typeof fetch & { - preconnect?: typeof globalThis.fetch; - }; - const oauthFetch = Object.assign( - oauthFetchImpl, - typeof bunFetch.preconnect === "function" - ? { preconnect: bunFetch.preconnect.bind(globalThis.fetch) } - : {}, - ) as typeof fetch; + const openaiKey = await resolveOpenAIApiKey(); + if (openaiKey) { + return createOpenAI({ apiKey: openaiKey }).chat(OPENAI_SMALL_MODEL_ID); + } - return createOpenAI({ - apiKey: "oauth-dummy-key", - fetch: oauthFetch, - }).responses(OPENAI_CODEX_SMALL_MODEL_ID); + console.warn( + "[get-small-model] no credentials found โ€” naming will fall back", + ); + return null; } diff --git a/packages/cli/CLI_SPEC.md b/packages/cli/CLI_SPEC.md index 87596c27add..41016cfa4ad 100644 --- a/packages/cli/CLI_SPEC.md +++ b/packages/cli/CLI_SPEC.md @@ -22,7 +22,6 @@ All device commands use this as the default. `--device` overrides it for remote --quiet IDs only (for piping) --device Override device (default: auto-detected from ~/.superset/device.json) --api-url Override API URL ---org Override active org ``` --- @@ -1082,9 +1081,9 @@ Extensible โ€” new providers (Linear, Notion, calendar, etc.) can be added as bl --- -## `superset org` (cloud) +## `superset organization` (cloud) -### `superset org list` +### `superset organization list` List organizations you belong to. **Human output:** @@ -1106,7 +1105,7 @@ Acme Corp member } ``` -### `superset org switch ` +### `superset organization switch ` Switch active organization. **Human output:** diff --git a/packages/cli/src/commands/auth/login/command.ts b/packages/cli/src/commands/auth/login/command.ts index bda8cbea767..8433ec0b4d2 100644 --- a/packages/cli/src/commands/auth/login/command.ts +++ b/packages/cli/src/commands/auth/login/command.ts @@ -32,14 +32,44 @@ export default command({ spinner.stop("Authorized!"); + const api = createApiClient(config, { bearer: result.accessToken }); + try { - const api = createApiClient(config, { bearer: result.accessToken }); const user = await api.user.me.query(); - const organization = await api.user.myOrganization.query(); p.log.info(`${user.name} (${user.email})`); - if (organization) p.log.info(`Organization: ${organization.name}`); - } catch { - // Non-fatal + } catch (error) { + p.log.warn( + `Could not fetch user profile: ${error instanceof Error ? error.message : String(error)}`, + ); + } + + const organizations = await api.user.myOrganizations.query(); + + let chosenId: string | undefined; + if (organizations.length === 1) { + chosenId = organizations[0]?.id; + } else if (organizations.length > 1 && process.stdout.isTTY) { + const sessionActive = await api.user.myOrganization.query(); + const selection = await p.select({ + message: "Select organization for this CLI", + initialValue: sessionActive?.id ?? organizations[0]?.id, + options: organizations.map((organization) => ({ + value: organization.id, + label: `${organization.name} (${organization.slug})`, + })), + }); + if (p.isCancel(selection)) { + p.cancel("Login cancelled"); + return { data: { apiUrl } }; + } + chosenId = selection as string; + } + + if (chosenId) { + config.organizationId = chosenId; + writeConfig(config); + const chosen = organizations.find((o) => o.id === chosenId); + if (chosen) p.log.info(`Organization: ${chosen.name}`); } p.outro("Logged in successfully."); diff --git a/packages/cli/src/commands/org/list/command.ts b/packages/cli/src/commands/organization/list/command.ts similarity index 100% rename from packages/cli/src/commands/org/list/command.ts rename to packages/cli/src/commands/organization/list/command.ts diff --git a/packages/cli/src/commands/org/meta.ts b/packages/cli/src/commands/organization/meta.ts similarity index 100% rename from packages/cli/src/commands/org/meta.ts rename to packages/cli/src/commands/organization/meta.ts diff --git a/packages/cli/src/commands/organization/switch/command.ts b/packages/cli/src/commands/organization/switch/command.ts new file mode 100644 index 00000000000..0d2b2658c61 --- /dev/null +++ b/packages/cli/src/commands/organization/switch/command.ts @@ -0,0 +1,32 @@ +import { CLIError, positional } from "@superset/cli-framework"; +import { command } from "../../../lib/command"; +import { readConfig, writeConfig } from "../../../lib/config"; + +export default command({ + description: "Switch the active organization for this CLI", + args: [positional("idOrSlug").required().desc("Organization id or slug")], + run: async ({ ctx, args }) => { + const idOrSlug = args.idOrSlug as string; + const organizations = await ctx.api.user.myOrganizations.query(); + + const match = organizations.find( + (organization) => + organization.id === idOrSlug || organization.slug === idOrSlug, + ); + if (!match) { + throw new CLIError( + `Organization not found: ${idOrSlug}`, + "Run: superset organization list", + ); + } + + const config = readConfig(); + config.organizationId = match.id; + writeConfig(config); + + return { + data: { id: match.id, name: match.name, slug: match.slug }, + message: `Switched to ${match.name}`, + }; + }, +}); diff --git a/packages/cli/src/lib/api-client.ts b/packages/cli/src/lib/api-client.ts index d52d358e4f5..8d5aafb1878 100644 --- a/packages/cli/src/lib/api-client.ts +++ b/packages/cli/src/lib/api-client.ts @@ -1,3 +1,4 @@ +import { ORGANIZATION_HEADER } from "@superset/shared/constants"; import type { AppRouter } from "@superset/trpc"; import type { TRPCClient } from "@trpc/client"; import { createTRPCClient, httpBatchLink } from "@trpc/client"; @@ -8,7 +9,7 @@ export type ApiClient = TRPCClient; export function createApiClient( config: SupersetConfig, - opts: { bearer: string }, + opts: { bearer: string; organizationId?: string }, ): ApiClient { return createTRPCClient({ links: [ @@ -16,7 +17,13 @@ export function createApiClient( url: `${getApiUrl(config)}/api/trpc`, transformer: SuperJSON, headers() { - return { Authorization: `Bearer ${opts.bearer}` }; + const headers: Record = { + Authorization: `Bearer ${opts.bearer}`, + }; + if (opts.organizationId) { + headers[ORGANIZATION_HEADER] = opts.organizationId; + } + return headers; }, }), ], diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index 1102cae2265..d5bbfbb34c1 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -15,6 +15,7 @@ export type SupersetConfig = { expiresAt: number; }; apiUrl?: string; + organizationId?: string; }; export type DeviceConfig = { diff --git a/packages/cli/src/lib/host/spawn.ts b/packages/cli/src/lib/host/spawn.ts index 5ef58afb8b5..38f02d91e08 100644 --- a/packages/cli/src/lib/host/spawn.ts +++ b/packages/cli/src/lib/host/spawn.ts @@ -108,6 +108,7 @@ export async function spawnHostService( AUTH_TOKEN: options.sessionToken, CLOUD_API_URL: env.CLOUD_API_URL, RELAY_URL: env.RELAY_URL, + PORT: String(port), HOST_SERVICE_PORT: String(port), HOST_SERVICE_SECRET: secret, HOST_DB_PATH: hostDbPath(options.organizationId), diff --git a/packages/cli/src/lib/resolve-auth.ts b/packages/cli/src/lib/resolve-auth.ts index ba954291dfc..d31e319cc05 100644 --- a/packages/cli/src/lib/resolve-auth.ts +++ b/packages/cli/src/lib/resolve-auth.ts @@ -36,6 +36,9 @@ export async function resolveAuth( bearer = config.auth.accessToken; } - const api = createApiClient(config, { bearer }); + const api = createApiClient(config, { + bearer, + organizationId: config.organizationId, + }); return { config, api, bearer, authSource }; } diff --git a/packages/db/package.json b/packages/db/package.json index 73b6001cbfa..e2776ef8bda 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -44,7 +44,7 @@ "@neondatabase/serverless": "1.0.2", "@t3-oss/env-core": "^0.13.8", "dotenv": "^17.3.1", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "zod": "^4.3.5" }, "devDependencies": { diff --git a/packages/host-service/drizzle/0003_workspace_upstream_ref.sql b/packages/host-service/drizzle/0003_workspace_upstream_ref.sql new file mode 100644 index 00000000000..f6c95acf5ba --- /dev/null +++ b/packages/host-service/drizzle/0003_workspace_upstream_ref.sql @@ -0,0 +1,5 @@ +DROP INDEX `workspaces_branch_idx`;--> statement-breakpoint +ALTER TABLE `workspaces` ADD `upstream_owner` text;--> statement-breakpoint +ALTER TABLE `workspaces` ADD `upstream_repo` text;--> statement-breakpoint +ALTER TABLE `workspaces` ADD `upstream_branch` text;--> statement-breakpoint +CREATE INDEX `workspaces_upstream_ref_idx` ON `workspaces` (`upstream_owner`,`upstream_repo`,`upstream_branch`); \ No newline at end of file diff --git a/packages/host-service/drizzle/meta/0003_snapshot.json b/packages/host-service/drizzle/meta/0003_snapshot.json new file mode 100644 index 00000000000..b3b8a6302f4 --- /dev/null +++ b/packages/host-service/drizzle/meta/0003_snapshot.json @@ -0,0 +1,493 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "d4171f78-422d-48d1-97c4-b803ed17fea9", + "prevId": "a2434e05-3865-4783-9247-7bda589c8806", + "tables": { + "projects": { + "name": "projects", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "repo_path": { + "name": "repo_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "repo_provider": { + "name": "repo_provider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "repo_owner": { + "name": "repo_owner", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "repo_name": { + "name": "repo_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "repo_url": { + "name": "repo_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "remote_name": { + "name": "remote_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "projects_repo_path_idx": { + "name": "projects_repo_path_idx", + "columns": [ + "repo_path" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "pull_requests": { + "name": "pull_requests", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "repo_provider": { + "name": "repo_provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "repo_owner": { + "name": "repo_owner", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "repo_name": { + "name": "repo_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "pr_number": { + "name": "pr_number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_draft": { + "name": "is_draft", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "head_branch": { + "name": "head_branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "head_sha": { + "name": "head_sha", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "review_decision": { + "name": "review_decision", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "checks_status": { + "name": "checks_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'none'" + }, + "checks_json": { + "name": "checks_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'[]'" + }, + "last_fetched_at": { + "name": "last_fetched_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "pull_requests_project_id_idx": { + "name": "pull_requests_project_id_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "pull_requests_repo_branch_idx": { + "name": "pull_requests_repo_branch_idx", + "columns": [ + "repo_provider", + "repo_owner", + "repo_name", + "head_branch" + ], + "isUnique": false + }, + "pull_requests_repo_pr_unique": { + "name": "pull_requests_repo_pr_unique", + "columns": [ + "repo_provider", + "repo_owner", + "repo_name", + "pr_number" + ], + "isUnique": true + } + }, + "foreignKeys": { + "pull_requests_project_id_projects_id_fk": { + "name": "pull_requests_project_id_projects_id_fk", + "tableFrom": "pull_requests", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "terminal_sessions": { + "name": "terminal_sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "origin_workspace_id": { + "name": "origin_workspace_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_attached_at": { + "name": "last_attached_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ended_at": { + "name": "ended_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "terminal_sessions_origin_workspace_id_idx": { + "name": "terminal_sessions_origin_workspace_id_idx", + "columns": [ + "origin_workspace_id" + ], + "isUnique": false + }, + "terminal_sessions_status_idx": { + "name": "terminal_sessions_status_idx", + "columns": [ + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "terminal_sessions_origin_workspace_id_workspaces_id_fk": { + "name": "terminal_sessions_origin_workspace_id_workspaces_id_fk", + "tableFrom": "terminal_sessions", + "tableTo": "workspaces", + "columnsFrom": [ + "origin_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "workspaces": { + "name": "workspaces", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "worktree_path": { + "name": "worktree_path", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "head_sha": { + "name": "head_sha", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_owner": { + "name": "upstream_owner", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_repo": { + "name": "upstream_repo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "upstream_branch": { + "name": "upstream_branch", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_request_id": { + "name": "pull_request_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "workspaces_project_id_idx": { + "name": "workspaces_project_id_idx", + "columns": [ + "project_id" + ], + "isUnique": false + }, + "workspaces_upstream_ref_idx": { + "name": "workspaces_upstream_ref_idx", + "columns": [ + "upstream_owner", + "upstream_repo", + "upstream_branch" + ], + "isUnique": false + }, + "workspaces_pull_request_id_idx": { + "name": "workspaces_pull_request_id_idx", + "columns": [ + "pull_request_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "workspaces_project_id_projects_id_fk": { + "name": "workspaces_project_id_projects_id_fk", + "tableFrom": "workspaces", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspaces_pull_request_id_pull_requests_id_fk": { + "name": "workspaces_pull_request_id_pull_requests_id_fk", + "tableFrom": "workspaces", + "tableTo": "pull_requests", + "columnsFrom": [ + "pull_request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/packages/host-service/drizzle/meta/_journal.json b/packages/host-service/drizzle/meta/_journal.json index 348757a3259..a54b39dfebf 100644 --- a/packages/host-service/drizzle/meta/_journal.json +++ b/packages/host-service/drizzle/meta/_journal.json @@ -22,6 +22,13 @@ "when": 1775239013772, "tag": "0002_add_terminal_sessions", "breakpoints": true + }, + { + "idx": 3, + "version": "6", + "when": 1776814372609, + "tag": "0003_workspace_upstream_ref", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/host-service/package.json b/packages/host-service/package.json index 79d5371e02a..3eb590e8b2f 100644 --- a/packages/host-service/package.json +++ b/packages/host-service/package.json @@ -53,7 +53,7 @@ "@trpc/client": "^11.7.1", "@trpc/server": "^11.7.1", "better-sqlite3": "12.6.2", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "hono": "^4.8.5", "mastracode": "0.14.0", "node-pty": "1.1.0", diff --git a/packages/host-service/src/db/schema.ts b/packages/host-service/src/db/schema.ts index 4ae289694fd..416af39df73 100644 --- a/packages/host-service/src/db/schema.ts +++ b/packages/host-service/src/db/schema.ts @@ -102,6 +102,9 @@ export const workspaces = sqliteTable( worktreePath: text("worktree_path").notNull(), branch: text().notNull(), headSha: text("head_sha"), + upstreamOwner: text("upstream_owner"), + upstreamRepo: text("upstream_repo"), + upstreamBranch: text("upstream_branch"), pullRequestId: text("pull_request_id").references(() => pullRequests.id, { onDelete: "set null", }), @@ -111,7 +114,11 @@ export const workspaces = sqliteTable( }, (table) => [ index("workspaces_project_id_idx").on(table.projectId), - index("workspaces_branch_idx").on(table.branch), + index("workspaces_upstream_ref_idx").on( + table.upstreamOwner, + table.upstreamRepo, + table.upstreamBranch, + ), index("workspaces_pull_request_id_idx").on(table.pullRequestId), ], ); diff --git a/packages/host-service/src/runtime/git/index.ts b/packages/host-service/src/runtime/git/index.ts index 0995b6e6bfd..7676fa7d808 100644 --- a/packages/host-service/src/runtime/git/index.ts +++ b/packages/host-service/src/runtime/git/index.ts @@ -5,5 +5,6 @@ export { asRemoteRef, resolveDefaultBranchName, resolveRef, + resolveUpstream, } from "./refs"; export type { GitCredentialProvider, GitFactory } from "./types"; diff --git a/packages/host-service/src/runtime/git/refs.ts b/packages/host-service/src/runtime/git/refs.ts index fe0be38deb4..015e7e593d5 100644 --- a/packages/host-service/src/runtime/git/refs.ts +++ b/packages/host-service/src/runtime/git/refs.ts @@ -143,3 +143,25 @@ export async function resolveDefaultBranchName( return "main"; } } + +/** + * Resolve a local branch's upstream tracking info (`branch..remote` + * / `branch..merge`). Returns `null` if no upstream is configured. + */ +export async function resolveUpstream( + git: SimpleGit, + branch: string, +): Promise<{ remote: string; remoteBranch: string } | null> { + try { + const [remote, merge] = await Promise.all([ + git.raw(["config", "--get", `branch.${branch}.remote`]), + git.raw(["config", "--get", `branch.${branch}.merge`]), + ]); + const remoteBranch = merge.trim().replace(/^refs\/heads\//, ""); + const remoteName = remote.trim(); + if (!remoteName || !remoteBranch) return null; + return { remote: remoteName, remoteBranch }; + } catch { + return null; + } +} diff --git a/packages/host-service/src/runtime/pull-requests/pull-requests.ts b/packages/host-service/src/runtime/pull-requests/pull-requests.ts index 92a76047a62..0a33bed5740 100644 --- a/packages/host-service/src/runtime/pull-requests/pull-requests.ts +++ b/packages/host-service/src/runtime/pull-requests/pull-requests.ts @@ -1,11 +1,11 @@ import { randomUUID } from "node:crypto"; import type { Octokit } from "@octokit/rest"; +import { parseGitHubRemote } from "@superset/shared/github-remote"; import { and, eq, inArray } from "drizzle-orm"; import type { HostDb } from "../../db"; import { projects, pullRequests, workspaces } from "../../db/schema"; import type { GitFactory } from "../git"; import { fetchRepositoryPullRequests } from "./utils/github-query"; -import { parseGitHubRemote } from "./utils/parse-github-remote"; import { type ChecksStatus, coerceChecksStatus, @@ -67,6 +67,96 @@ async function getHeadSha(git: Awaited>) { } } +// `pushRemote` / `branch.remote` accept a remote name or a URL. +async function resolveRemoteValueToUrl( + git: Awaited>, + value: string, +): Promise { + if (/^(https?:|git@|ssh:)/.test(value)) return value; + try { + const url = await git.remote(["get-url", value]); + return typeof url === "string" ? url.trim() || null : null; + } catch { + return null; + } +} + +async function resolveWorkspaceUpstream( + git: Awaited>, + localBranch: string, +): Promise<{ owner: string; name: string; branch: string } | null> { + // `@{push}` resolves remote+branch respecting all config precedence in one call. + const pushRef = await tryRaw(git, [ + "rev-parse", + "--abbrev-ref", + `${localBranch}@{push}`, + ]); + if (pushRef) { + const slash = pushRef.indexOf("/"); + if (slash > 0) { + const url = await resolveRemoteValueToUrl(git, pushRef.slice(0, slash)); + const parsed = url ? parseGitHubRemote(url) : null; + if (parsed) { + return { + owner: parsed.owner, + name: parsed.name, + branch: pushRef.slice(slash + 1), + }; + } + } + } + + // Fallback when `@{push}` isn't configured โ€” mirrors gh's config chain. + // Require `branch..merge`; without it, `remote.pushDefault` alone would + // re-open the same-name collision hole on untracked branches. + const mergeRef = await tryConfig(git, `branch.${localBranch}.merge`); + const trackedBranch = mergeRef?.replace(/^refs\/heads\//, ""); + if (!trackedBranch) return null; + + const remoteValue = + (await tryConfig(git, `branch.${localBranch}.pushRemote`)) ?? + (await tryConfig(git, "remote.pushDefault")) ?? + (await tryConfig(git, `branch.${localBranch}.remote`)); + if (!remoteValue) return null; + + const url = await resolveRemoteValueToUrl(git, remoteValue); + const parsed = url ? parseGitHubRemote(url) : null; + if (!parsed) return null; + + // `gh pr checkout` renames the local branch on collision (`main` โ†’ + // `quueli-main`) but the PR's headRefName stays `main`, so we key on the + // tracked remote branch, not the local name. + return { owner: parsed.owner, name: parsed.name, branch: trackedBranch }; +} + +async function tryRaw( + git: Awaited>, + args: string[], +): Promise { + try { + return (await git.raw(args)).trim() || null; + } catch { + return null; + } +} + +async function tryConfig( + git: Awaited>, + key: string, +): Promise { + return tryRaw(git, ["config", "--get", key]); +} + +function upstreamKey( + owner: string | null, + repo: string | null, + branch: string, +): string | null { + if (!owner || !repo) return null; + // GitHub owner/repo are case-insensitive; branch names are case-sensitive. + return `${owner.toLowerCase()}/${repo.toLowerCase()}#${branch}`; +} + type RepoProvider = "github"; export interface PullRequestStateSnapshot { @@ -100,77 +190,6 @@ interface NormalizedRepoIdentity { remoteName: string; } -interface PullRequestMatchCandidate { - id: string; - node: Awaited>[number]; -} - -function getRepoKey( - repo: Pick, -) { - return `${repo.provider}:${repo.owner}/${repo.name}`; -} - -function getPullRequestStatePriority(state: "OPEN" | "CLOSED" | "MERGED") { - switch (state) { - case "OPEN": - return 3; - case "MERGED": - return 2; - default: - return 1; - } -} - -function comparePullRequestCandidates( - a: PullRequestMatchCandidate, - b: PullRequestMatchCandidate, - headSha: string | null, -) { - const aHeadShaMatches = Boolean(headSha && a.node.headRefOid === headSha); - const bHeadShaMatches = Boolean(headSha && b.node.headRefOid === headSha); - if (aHeadShaMatches !== bHeadShaMatches) { - return aHeadShaMatches ? -1 : 1; - } - - const stateDelta = - getPullRequestStatePriority(b.node.state) - - getPullRequestStatePriority(a.node.state); - if (stateDelta !== 0) { - return stateDelta; - } - - return ( - new Date(b.node.updatedAt).getTime() - new Date(a.node.updatedAt).getTime() - ); -} - -function getTrackingRemoteName(upstreamRef: string | null) { - if (!upstreamRef) return null; - - const trimmed = upstreamRef.trim(); - if (!trimmed) return null; - - const slashIndex = trimmed.indexOf("/"); - return slashIndex >= 0 ? trimmed.slice(0, slashIndex) : trimmed; -} - -function branchMatchesPullRequestHead( - branch: string, - headRefName: string, - headRepositoryOwner: string | null, -) { - if (branch === headRefName) { - return true; - } - - if (!headRepositoryOwner) { - return false; - } - - return branch === `${headRepositoryOwner}/${headRefName}`; -} - export class PullRequestRuntimeManager { private readonly db: HostDb; private readonly git: GitFactory; @@ -284,8 +303,18 @@ export class PullRequestRuntimeManager { continue; } const headSha = await getHeadSha(git); - - if (branch === workspace.branch && headSha === workspace.headSha) { + const upstream = await resolveWorkspaceUpstream(git, branch); + const upstreamOwner = upstream?.owner ?? null; + const upstreamRepo = upstream?.name ?? null; + const upstreamBranch = upstream?.branch ?? null; + + if ( + branch === workspace.branch && + headSha === workspace.headSha && + upstreamOwner === workspace.upstreamOwner && + upstreamRepo === workspace.upstreamRepo && + upstreamBranch === workspace.upstreamBranch + ) { continue; } @@ -294,6 +323,9 @@ export class PullRequestRuntimeManager { .set({ branch, headSha, + upstreamOwner, + upstreamRepo, + upstreamBranch, }) .where(eq(workspaces.id, workspace.id)) .run(); @@ -370,6 +402,9 @@ export class PullRequestRuntimeManager { } private async performProjectRefresh(projectId: string): Promise { + const repo = await this.getProjectRepository(projectId); + if (!repo) return; + const projectWorkspaces = this.db .select() .from(workspaces) @@ -377,133 +412,37 @@ export class PullRequestRuntimeManager { .all(); if (projectWorkspaces.length === 0) return; - const projectRepo = await this.getProjectRepository(projectId); - const branchNames = [ - ...new Set(projectWorkspaces.map((workspace) => workspace.branch)), - ]; - - const workspaceRepos = await Promise.all( - projectWorkspaces.map(async (workspace) => { - try { - return { - workspace, - repos: await this.getWorkspaceRepositories( - workspace.worktreePath, - projectRepo, - ), - }; - } catch (error) { - console.warn( - "[host-service:pull-request-runtime] Failed to resolve workspace repositories", - { - workspaceId: workspace.id, - worktreePath: workspace.worktreePath, - error, - }, - ); - - return { - workspace, - repos: projectRepo ? [projectRepo] : [], - }; - } - }), - ); - - const repos = [ - ...new Map( - workspaceRepos - .flatMap(({ repos }) => repos) - .map((repo) => [getRepoKey(repo), repo]), - ).values(), - ]; - if (repos.length === 0) return; - - const repoToPullRequests = new Map(); - for (const repo of repos) { - repoToPullRequests.set( - getRepoKey(repo), - await this.fetchRepoPullRequests(projectId, repo, branchNames), + const wantedKeys = new Set(); + for (const workspace of projectWorkspaces) { + const key = upstreamKey( + workspace.upstreamOwner, + workspace.upstreamRepo, + workspace.upstreamBranch ?? workspace.branch, ); + if (key) wantedKeys.add(key); } - for (const { workspace, repos: candidateRepos } of workspaceRepos) { - const match = this.findBestPullRequestMatch( - workspace.branch, - workspace.headSha, - candidateRepos, - repoToPullRequests, + const keyToPullRequest = await this.fetchRepoPullRequests( + projectId, + repo, + wantedKeys, + ); + + for (const workspace of projectWorkspaces) { + const key = upstreamKey( + workspace.upstreamOwner, + workspace.upstreamRepo, + workspace.upstreamBranch ?? workspace.branch, ); + const match = key ? keyToPullRequest.get(key) : undefined; this.db .update(workspaces) - .set({ - pullRequestId: match?.id ?? null, - }) + .set({ pullRequestId: match?.id ?? null }) .where(eq(workspaces.id, workspace.id)) .run(); } } - private async getWorkspaceRepositories( - worktreePath: string, - projectRepo: NormalizedRepoIdentity | null, - ): Promise { - const git = await this.git(worktreePath); - const repos: NormalizedRepoIdentity[] = []; - const pushRepo = (repo: NormalizedRepoIdentity | null) => { - if (!repo) return; - if (repos.some((existing) => getRepoKey(existing) === getRepoKey(repo))) { - return; - } - repos.push(repo); - }; - - let trackingRemoteName: string | null = null; - try { - trackingRemoteName = getTrackingRemoteName( - await git.raw([ - "rev-parse", - "--abbrev-ref", - "--symbolic-full-name", - "@{upstream}", - ]), - ); - } catch {} - - pushRepo( - trackingRemoteName - ? await this.getRemoteRepository(git, trackingRemoteName) - : null, - ); - pushRepo(await this.getRemoteRepository(git, "origin")); - pushRepo(await this.getRemoteRepository(git, "upstream")); - pushRepo(projectRepo); - - return repos; - } - - private async getRemoteRepository( - git: Awaited>, - remoteName: string, - ): Promise { - try { - const remoteUrl = await git.remote(["get-url", remoteName]); - if (typeof remoteUrl !== "string") { - return null; - } - - const parsedRemote = parseGitHubRemote(remoteUrl); - if (!parsedRemote) return null; - - return { - ...parsedRemote, - remoteName, - }; - } catch { - return null; - } - } - private async getProjectRepository( projectId: string, ): Promise { @@ -565,20 +504,39 @@ export class PullRequestRuntimeManager { private async fetchRepoPullRequests( projectId: string, repo: NormalizedRepoIdentity, - branches: string[], - ): Promise { + wantedKeys: Set, + ): Promise> { + if (wantedKeys.size === 0) return new Map(); + const octokit = await this.github(); const nodes = await fetchRepositoryPullRequests(octokit, { owner: repo.owner, name: repo.name, }); - const wantedBranches = new Set(branches); - const matches: PullRequestMatchCandidate[] = []; - const now = Date.now(); + const latestByKey = new Map(); for (const node of nodes) { - if (!wantedBranches.has(node.headRefName)) continue; + const key = upstreamKey( + node.headRepositoryOwner?.login ?? null, + node.headRepository?.name ?? null, + node.headRefName, + ); + if (!key || !wantedKeys.has(key)) continue; + const existing = latestByKey.get(key); + if ( + !existing || + new Date(node.updatedAt).getTime() > + new Date(existing.updatedAt).getTime() + ) { + latestByKey.set(key, node); + } + } + + const keyToRow = new Map(); + const now = Date.now(); + + for (const [key, node] of latestByKey) { const existing = this.db.query.pullRequests .findFirst({ where: and( @@ -631,37 +589,9 @@ export class PullRequestRuntimeManager { .run(); } - matches.push({ id: rowId, node }); + keyToRow.set(key, { id: rowId }); } - return matches; - } - - private findBestPullRequestMatch( - branch: string, - headSha: string | null, - repos: NormalizedRepoIdentity[], - repoToPullRequests: Map, - ): PullRequestMatchCandidate | null { - for (const repo of repos) { - const candidates = - repoToPullRequests - .get(getRepoKey(repo)) - ?.filter((candidate) => - branchMatchesPullRequestHead( - branch, - candidate.node.headRefName, - candidate.node.headRepositoryOwner?.login ?? null, - ), - ) ?? []; - if (candidates.length === 0) { - continue; - } - - candidates.sort((a, b) => comparePullRequestCandidates(a, b, headSha)); - return candidates[0] ?? null; - } - - return null; + return keyToRow; } } diff --git a/packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts b/packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts index 7d73bfdce25..bf579dae8d4 100644 --- a/packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts +++ b/packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts @@ -10,9 +10,9 @@ export const PULL_REQUESTS_QUERY = ` isDraft headRefName headRefOid - headRepositoryOwner { - login - } + isCrossRepository + headRepositoryOwner { login } + headRepository { name } reviewDecision updatedAt statusCheckRollup { diff --git a/packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts b/packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts index c6b08f01958..02201ae66e4 100644 --- a/packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts +++ b/packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts @@ -34,9 +34,9 @@ export interface GraphQLPullRequestNode { isDraft: boolean; headRefName: string; headRefOid: string; - headRepositoryOwner: { - login: string | null; - } | null; + isCrossRepository: boolean; + headRepositoryOwner: { login: string } | null; + headRepository: { name: string } | null; reviewDecision: "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED" | null; updatedAt: string; statusCheckRollup: { diff --git a/packages/host-service/src/trpc/router/git/git.ts b/packages/host-service/src/trpc/router/git/git.ts index 4a0a0f9e4d5..fbb20996515 100644 --- a/packages/host-service/src/trpc/router/git/git.ts +++ b/packages/host-service/src/trpc/router/git/git.ts @@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; import { z } from "zod"; -import { pullRequests, workspaces } from "../../../db/schema"; +import { projects, pullRequests, workspaces } from "../../../db/schema"; import { protectedProcedure, router } from "../../index"; import type { ChangedFile, @@ -19,9 +19,9 @@ import type { import { buildBranch, getChangedFilesForDiff, - getDefaultBranchName, mapGitStatus, parseNumstat, + resolveBaseComparison, } from "./utils/git-helpers"; import { type GraphQLThreadsResult, @@ -32,13 +32,7 @@ import { resolveWorktreePath } from "./utils/resolve-worktree"; export const gitRouter = router({ listBranches: protectedProcedure - .input( - z.object({ - workspaceId: z.string(), - sortOrder: z.enum(["committerdate", "alphabetical"]).optional(), - pinDefault: z.boolean().optional(), - }), - ) + .input(z.object({ workspaceId: z.string() })) .query(async ({ ctx, input }) => { const worktreePath = resolveWorktreePath(ctx, input.workspaceId); const git = await ctx.git(worktreePath); @@ -46,110 +40,24 @@ export const gitRouter = router({ const currentBranchName = ( await git.revparse(["--abbrev-ref", "HEAD"]).catch(() => "") ).trim(); - const defaultBranchName = await getDefaultBranchName(git); - - const sortOrder = input.sortOrder ?? "committerdate"; - const pinDefault = input.pinDefault ?? true; - // `git branch` supports `--sort` directly (falls back to git default - // if the flag is rejected by a very old git). committerdate is - // descending via a leading `-`; alphabetical uses refname. - const sortArg = - sortOrder === "committerdate" - ? "--sort=-committerdate" - : "--sort=refname"; - - const readRefs = async ( - extraArgs: string[], - stripPrefix?: string, - ): Promise => { - try { - const raw = await git.raw([ - "branch", - "--list", - sortArg, - "--format=%(refname:short)", - ...extraArgs, - ]); - return ( - raw - .trim() - .split("\n") - .map((line) => line.trim()) - .filter(Boolean) - .filter((line) => !line.includes("->")) - // When a prefix filter is given (e.g. "origin/") only keep - // entries that start with that prefix. Lines from non-origin - // remotes (e.g. "upstream/main") would survive the map step - // unchanged and then cause buildBranch to construct invalid - // refs like "origin/upstream/main". - .filter((line) => !stripPrefix || line.startsWith(stripPrefix)) - .map((line) => - stripPrefix && line.startsWith(stripPrefix) - ? line.slice(stripPrefix.length) - : line, - ) - ); - } catch { - return []; - } - }; - - const localNames = await readRefs([]); - const remoteNames = await readRefs(["-r"], "origin/"); + const base = await resolveBaseComparison(git); - const localSet = new Set(localNames); - // Deduplicate: a remote-only branch is one that has no local - // counterpart. Local branches always win. - const remoteOnlyNames = remoteNames.filter( - (name) => !localSet.has(name) && name !== "HEAD", - ); + let branchNames: string[] = []; + try { + const raw = await git.raw([ + "branch", + "--list", + "--format=%(refname:short)", + ]); + branchNames = raw.trim().split("\n").filter(Boolean); + } catch {} - // For alphabetical sort we re-sort in JS with case-insensitive - // comparison so that `Feat-a` and `feat-b` interleave the way - // users expect. committerdate already comes back ordered by git. - const sortAlphabetical = (names: string[]): string[] => - sortOrder === "alphabetical" - ? [...names].sort((a, b) => - a.localeCompare(b, undefined, { sensitivity: "base" }), - ) - : names; - - const sortedLocal = sortAlphabetical(localNames); - const sortedRemoteOnly = sortAlphabetical(remoteOnlyNames); - - const compareRef = defaultBranchName - ? `origin/${defaultBranchName}` - : undefined; - - const localBranches = await Promise.all( - sortedLocal.map((name) => - buildBranch(git, name, name === currentBranchName, compareRef), - ), - ); - const remoteBranches = await Promise.all( - sortedRemoteOnly.map((name) => - buildBranch(git, name, false, compareRef, { isRemote: true }), + const branches = await Promise.all( + branchNames.map((name) => + buildBranch(git, name, name === currentBranchName, base?.baseRef), ), ); - let branches = [...localBranches, ...remoteBranches]; - - // Optionally pin the default branch (main / master / trunk / etc) - // at the top of the list regardless of sort order. Only looks at - // local branches โ€” if the default exists only remotely we leave - // it where the sort put it. - if (pinDefault && defaultBranchName) { - const defaultIdx = branches.findIndex( - (b) => !b.isRemote && b.name === defaultBranchName, - ); - if (defaultIdx > 0) { - const [defaultBranch] = branches.splice(defaultIdx, 1); - if (defaultBranch) { - branches = [defaultBranch, ...branches]; - } - } - } - return { branches }; }), @@ -167,11 +75,9 @@ export const gitRouter = router({ const currentBranchName = ( await git.revparse(["--abbrev-ref", "HEAD"]).catch(() => "") ).trim(); - const defaultBranchName = - input.baseBranch ?? (await getDefaultBranchName(git)); - const baseRef = defaultBranchName - ? `origin/${defaultBranchName}` - : "HEAD"; + const base = await resolveBaseComparison(git, input.baseBranch); + const defaultBranchName = base?.branchName ?? null; + const baseRef = base?.baseRef ?? "HEAD"; const [currentBranch, defaultBranch, status, ignoredRaw] = await Promise.all([ @@ -199,11 +105,13 @@ export const gitRouter = router({ .map((line) => line.trim().replace(/\/$/, "")) .filter(Boolean); - const againstBase = await getChangedFilesForDiff(git, [baseRef, "HEAD"]); + const againstBase = await getChangedFilesForDiff(git, [ + `${baseRef}...HEAD`, + ]); // Staged โ€” use status.files index character for correct status const stagedNumstat = parseNumstat( - await git.raw(["diff", "--numstat", "--cached"]).catch(() => ""), + await git.raw(["diff", "--numstat", "-z", "--cached"]).catch(() => ""), ); const staged: ChangedFile[] = []; for (const file of status.files) { @@ -224,7 +132,7 @@ export const gitRouter = router({ // Unstaged โ€” use status.files working_dir character const unstagedNumstat = parseNumstat( - await git.raw(["diff", "--numstat"]).catch(() => ""), + await git.raw(["diff", "--numstat", "-z"]).catch(() => ""), ); const unstaged: ChangedFile[] = []; for (const file of status.files) { @@ -271,11 +179,8 @@ export const gitRouter = router({ const worktreePath = resolveWorktreePath(ctx, input.workspaceId); const git = await ctx.git(worktreePath); - const defaultBranchName = - input.baseBranch ?? (await getDefaultBranchName(git)); - const baseRef = defaultBranchName - ? `origin/${defaultBranchName}` - : "HEAD"; + const base = await resolveBaseComparison(git, input.baseBranch); + const baseRef = base?.baseRef ?? "HEAD"; const commits: Commit[] = []; try { @@ -424,11 +329,17 @@ export const gitRouter = router({ let modifiedContent = ""; if (input.category === "against-base") { - const baseBranch = - input.baseBranch ?? (await getDefaultBranchName(git)); - const baseRef = baseBranch ? `origin/${baseBranch}` : "HEAD"; + const base = await resolveBaseComparison(git, input.baseBranch); + const baseRef = base?.baseRef ?? "HEAD"; + // Use the merge base so the diff excludes unrelated changes + // landed on the base branch after we forked โ€” matches what the + // file list (3-dot diff) is already filtered by. + const originRef = await git + .raw(["merge-base", baseRef, "HEAD"]) + .then((s) => s.trim()) + .catch(() => baseRef); try { - originalContent = await git.show([`${baseRef}:${input.path}`]); + originalContent = await git.show([`${originRef}:${input.path}`]); } catch {} try { modifiedContent = await git.show([`HEAD:${input.path}`]); @@ -560,7 +471,16 @@ export const gitRouter = router({ }); } - if (!pr.repoOwner || !pr.repoName) { + const project = ctx.db.query.projects + .findFirst({ where: eq(projects.id, workspace.projectId) }) + .sync(); + if (!project) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: `Project ${workspace.projectId} not found in database`, + }); + } + if (!project.repoOwner || !project.repoName) { return { reviewThreads: [], conversationComments: [] }; } @@ -571,8 +491,8 @@ export const gitRouter = router({ const result: GraphQLThreadsResult = await octokit.graphql( REVIEW_THREADS_QUERY, { - owner: pr.repoOwner, - name: pr.repoName, + owner: project.repoOwner, + name: project.repoName, prNumber: pr.prNumber, }, ); @@ -590,8 +510,8 @@ export const gitRouter = router({ let hasMore = true; while (hasMore) { const { data: comments } = await octokit.issues.listComments({ - owner: pr.repoOwner, - repo: pr.repoName, + owner: project.repoOwner, + repo: project.repoName, issue_number: pr.prNumber, per_page: 100, page, diff --git a/packages/host-service/src/trpc/router/git/utils/git-helpers.integration.test.ts b/packages/host-service/src/trpc/router/git/utils/git-helpers.integration.test.ts new file mode 100644 index 00000000000..eeda0d0352b --- /dev/null +++ b/packages/host-service/src/trpc/router/git/utils/git-helpers.integration.test.ts @@ -0,0 +1,351 @@ +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import { mkdtempSync, rmSync } from "node:fs"; +import { writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import simpleGit, { type SimpleGit } from "simple-git"; +import { resolveUpstream } from "../../../../runtime/git/refs"; +import { + getChangedFilesForDiff, + getDefaultBranchName, + resolveBaseComparison, +} from "./git-helpers"; + +/** + * Integration tests that exercise the git-correctness fixes against real + * on-disk repositories. Validates the exact scenarios the user-facing + * fixes are meant to handle โ€” stale local default branches, fork + * workflows with a distinct upstream remote, non-ASCII filenames, etc. + */ + +async function initRepo(path: string): Promise { + const git = simpleGit(path); + await git.init(); + await git.raw(["config", "user.email", "test@example.com"]); + await git.raw(["config", "user.name", "test"]); + await git.raw(["config", "commit.gpgsign", "false"]); + await git.raw(["symbolic-ref", "HEAD", "refs/heads/main"]); + return git; +} + +async function commitFile( + git: SimpleGit, + cwd: string, + name: string, + content: string, + message: string, +): Promise { + await writeFile(join(cwd, name), content); + await git.raw(["add", "--", name]); + await git.raw(["commit", "-m", message]); +} + +function mkTmp(): string { + return mkdtempSync(join(tmpdir(), "superset-git-integration-")); +} + +// โ”€โ”€ resolveUpstream โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("resolveUpstream (integration)", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + await commitFile(git, repo, "README.md", "hello", "initial"); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("returns null when no upstream configured", async () => { + expect(await resolveUpstream(git, "main")).toBeNull(); + }); + + test("returns origin/ when tracking origin", async () => { + await git.raw(["config", "branch.main.remote", "origin"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + expect(await resolveUpstream(git, "main")).toEqual({ + remote: "origin", + remoteBranch: "main", + }); + }); + + test("returns upstream/ for fork workflow", async () => { + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + expect(await resolveUpstream(git, "main")).toEqual({ + remote: "upstream", + remoteBranch: "main", + }); + }); + + test("handles local-tracking (remote = '.')", async () => { + await git.raw(["checkout", "-b", "feature"]); + await git.raw(["config", "branch.feature.remote", "."]); + await git.raw(["config", "branch.feature.merge", "refs/heads/main"]); + expect(await resolveUpstream(git, "feature")).toEqual({ + remote: ".", + remoteBranch: "main", + }); + }); + + test("handles tracking a differently-named remote branch", async () => { + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/master"]); + expect(await resolveUpstream(git, "main")).toEqual({ + remote: "upstream", + remoteBranch: "master", + }); + }); + + test("returns null for nonexistent branch", async () => { + expect(await resolveUpstream(git, "does-not-exist")).toBeNull(); + }); +}); + +// โ”€โ”€ resolveBaseComparison โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("resolveBaseComparison (integration)", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + await commitFile(git, repo, "README.md", "hello", "initial"); + // Simulate a remote so origin/HEAD can be set. We don't need an + // actual remote to fetch from โ€” `symbolic-ref` on the remote HEAD + // is all getDefaultBranchName reads. + await git.raw(["update-ref", "refs/remotes/origin/main", "HEAD"]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/main", + ]); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("falls back to origin/ when no upstream configured", async () => { + const result = await resolveBaseComparison(git); + expect(result).toEqual({ branchName: "main", baseRef: "origin/main" }); + }); + + test("honors configured upstream remote (fork workflow)", async () => { + await git.raw(["update-ref", "refs/remotes/upstream/main", "HEAD"]); + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + expect(await resolveBaseComparison(git)).toEqual({ + branchName: "main", + baseRef: "upstream/main", + }); + }); + + test("local-tracking branch resolves to bare branch name (not ./name)", async () => { + await git.raw(["checkout", "-b", "integration"]); + await git.raw(["config", "branch.integration.remote", "."]); + await git.raw(["config", "branch.integration.merge", "refs/heads/main"]); + expect(await resolveBaseComparison(git, "integration")).toEqual({ + branchName: "integration", + baseRef: "main", + }); + }); + + test("explicit branch with upstream uses upstream remote", async () => { + await git.raw(["update-ref", "refs/remotes/upstream/main", "HEAD"]); + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + expect(await resolveBaseComparison(git, "main")).toEqual({ + branchName: "main", + baseRef: "upstream/main", + }); + }); + + test("returns null when no default branch can be resolved", async () => { + const emptyRepo = mkTmp(); + try { + const emptyGit = await initRepo(emptyRepo); + await commitFile(emptyGit, emptyRepo, "a.txt", "a", "init"); + expect(await resolveBaseComparison(emptyGit)).toBeNull(); + } finally { + rmSync(emptyRepo, { recursive: true, force: true }); + } + }); +}); + +// โ”€โ”€ getDefaultBranchName โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("getDefaultBranchName (integration)", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + await commitFile(git, repo, "README.md", "hello", "initial"); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("returns null when origin/HEAD not set", async () => { + expect(await getDefaultBranchName(git)).toBeNull(); + }); + + test("returns 'main' when origin/HEAD points at origin/main", async () => { + await git.raw(["update-ref", "refs/remotes/origin/main", "HEAD"]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/main", + ]); + expect(await getDefaultBranchName(git)).toBe("main"); + }); + + test("returns 'master' when origin/HEAD points at origin/master", async () => { + await git.raw(["branch", "master"]); + await git.raw(["update-ref", "refs/remotes/origin/master", "HEAD"]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/master", + ]); + expect(await getDefaultBranchName(git)).toBe("master"); + }); +}); + +// โ”€โ”€ getChangedFilesForDiff โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("getChangedFilesForDiff (integration)", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("returns adds/modifies/deletes correctly", async () => { + await commitFile(git, repo, "keep.ts", "a\nb\nc\n", "base"); + await commitFile(git, repo, "drop.ts", "x\n", "base2"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "new.ts", "hello\nworld\n", "add"); + await writeFile(join(repo, "keep.ts"), "a\nB\nc\n"); + await git.raw(["add", "keep.ts"]); + await git.raw(["commit", "-m", "modify"]); + await git.raw(["rm", "drop.ts"]); + await git.raw(["commit", "-m", "delete"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const byPath = new Map(files.map((f) => [f.path, f])); + expect(byPath.get("new.ts")?.status).toBe("added"); + expect(byPath.get("new.ts")?.additions).toBe(2); + expect(byPath.get("keep.ts")?.status).toBe("modified"); + expect(byPath.get("keep.ts")?.additions).toBe(1); + expect(byPath.get("keep.ts")?.deletions).toBe(1); + expect(byPath.get("drop.ts")?.status).toBe("deleted"); + }); + + test("rename with line changes reports correct additions/deletions", async () => { + await commitFile( + git, + repo, + "old.ts", + "one\ntwo\nthree\nfour\nfive\n", + "base", + ); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await git.raw(["mv", "old.ts", "new.ts"]); + // Change a couple of lines inside the rename. + await writeFile(join(repo, "new.ts"), "one\nTWO\nthree\nfour\nFIVE\n"); + await git.raw(["add", "new.ts"]); + await git.raw(["commit", "-m", "rename+edit"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const rename = files.find((f) => f.path === "new.ts"); + expect(rename?.status).toBe("renamed"); + expect(rename?.oldPath).toBe("old.ts"); + // With 2 line edits we should see non-zero add/del โ€” the bug + // before this PR was that these came back as 0/0. + expect(rename?.additions).toBeGreaterThan(0); + expect(rename?.deletions).toBeGreaterThan(0); + }); + + test("pure rename (no edits) reports 0/0 correctly", async () => { + await commitFile(git, repo, "old.ts", "stable\n", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await git.raw(["mv", "old.ts", "new.ts"]); + await git.raw(["commit", "-m", "rename"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const rename = files.find((f) => f.path === "new.ts"); + expect(rename?.status).toBe("renamed"); + expect(rename?.additions).toBe(0); + expect(rename?.deletions).toBe(0); + }); + + test("non-ASCII filename reports correct additions/deletions", async () => { + await commitFile(git, repo, "README.md", "a", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "ๆ—ฅๆœฌ่ชž.ts", "hello\nworld\n", "add ja"); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const ja = files.find((f) => f.path.includes("ๆ—ฅๆœฌ่ชž")); + expect(ja).toBeDefined(); + expect(ja?.status).toBe("added"); + // Pre-fix: additions would be 0 because --name-status quoted the + // path as "\346\227\245\346\234\254\350\252\236.ts" while + // --numstat -z emitted it raw โ€” the lookup never matched. + expect(ja?.additions).toBe(2); + }); + + test("binary file reports 0/0", async () => { + await commitFile(git, repo, "README.md", "a", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + // A NUL byte forces git's "binary" classification. + const bin = Buffer.from([0x00, 0x01, 0x02, 0x03]); + await writeFile(join(repo, "img.bin"), bin); + await git.raw(["add", "img.bin"]); + await git.raw(["commit", "-m", "add binary"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const bin2 = files.find((f) => f.path === "img.bin"); + expect(bin2?.status).toBe("added"); + expect(bin2?.additions).toBe(0); + expect(bin2?.deletions).toBe(0); + }); + + test("3-dot diff excludes changes on base after divergence", async () => { + // base: A โ€” B + // \ + // branch: X + // Then advance base with commit C that branch doesn't know about. + // A 2-dot diff origin-main HEAD would include C as a delete. + // Our 3-dot baseSha...HEAD pins to the merge base and excludes C. + await commitFile(git, repo, "shared.ts", "a\n", "A"); + await git.raw(["checkout", "-b", "branch"]); + await commitFile(git, repo, "branch-only.ts", "x\n", "X"); + const branchSha = (await git.revparse(["HEAD"])).trim(); + + await git.raw(["checkout", "main"]); + await commitFile(git, repo, "main-only.ts", "c\n", "C"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + + await git.raw(["checkout", branchSha]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const paths = files.map((f) => f.path).sort(); + // Only our branch's file should show โ€” C on main is excluded by 3-dot. + expect(paths).toEqual(["branch-only.ts"]); + }); +}); diff --git a/packages/host-service/src/trpc/router/git/utils/git-helpers.test.ts b/packages/host-service/src/trpc/router/git/utils/git-helpers.test.ts new file mode 100644 index 00000000000..4ce2ecc6b12 --- /dev/null +++ b/packages/host-service/src/trpc/router/git/utils/git-helpers.test.ts @@ -0,0 +1,139 @@ +import { describe, expect, test } from "bun:test"; +import { parseNameStatus, parseNumstat } from "./git-helpers"; + +describe("parseNumstat", () => { + test("regular file entry", () => { + const raw = "5\t2\tsrc/foo.ts\0"; + const result = parseNumstat(raw); + expect(result.get("src/foo.ts")).toEqual({ additions: 5, deletions: 2 }); + }); + + test("multiple regular entries", () => { + const raw = "5\t2\tsrc/foo.ts\x003\t0\tsrc/bar.ts\x00"; + const result = parseNumstat(raw); + expect(result.get("src/foo.ts")).toEqual({ additions: 5, deletions: 2 }); + expect(result.get("src/bar.ts")).toEqual({ additions: 3, deletions: 0 }); + }); + + test("exact rename with edits indexes both paths", () => { + const raw = "4\t3\t\x00src/old.ts\x00src/new.ts\x00"; + const result = parseNumstat(raw); + expect(result.get("src/new.ts")).toEqual({ additions: 4, deletions: 3 }); + expect(result.get("src/old.ts")).toEqual({ additions: 4, deletions: 3 }); + }); + + test("pure rename with zero line changes", () => { + const raw = "0\t0\t\x00src/old.ts\x00src/new.ts\x00"; + const result = parseNumstat(raw); + expect(result.get("src/new.ts")).toEqual({ additions: 0, deletions: 0 }); + expect(result.get("src/old.ts")).toEqual({ additions: 0, deletions: 0 }); + }); + + test("binary file with dash markers", () => { + const raw = "-\t-\tassets/image.png\0"; + const result = parseNumstat(raw); + expect(result.get("assets/image.png")).toEqual({ + additions: 0, + deletions: 0, + }); + }); + + test("mixed regular, rename, and binary", () => { + const raw = + "5\t2\tsrc/foo.ts\x00" + + "4\t3\t\x00src/old.ts\x00src/new.ts\x00" + + "-\t-\tassets/image.png\x00"; + const result = parseNumstat(raw); + expect(result.get("src/foo.ts")).toEqual({ additions: 5, deletions: 2 }); + expect(result.get("src/new.ts")).toEqual({ additions: 4, deletions: 3 }); + expect(result.get("src/old.ts")).toEqual({ additions: 4, deletions: 3 }); + expect(result.get("assets/image.png")).toEqual({ + additions: 0, + deletions: 0, + }); + }); + + test("empty input returns empty map", () => { + expect(parseNumstat("")).toEqual(new Map()); + }); + + test("path containing tab is preserved as-is", () => { + const raw = "1\t1\tweird\tpath.ts\0"; + const result = parseNumstat(raw); + expect(result.get("weird\tpath.ts")).toEqual({ + additions: 1, + deletions: 1, + }); + }); + + test("rename where both paths contain tabs", () => { + const raw = "2\t1\t\x00weird\told.ts\x00weird\tnew.ts\x00"; + const result = parseNumstat(raw); + expect(result.get("weird\told.ts")).toEqual({ additions: 2, deletions: 1 }); + expect(result.get("weird\tnew.ts")).toEqual({ additions: 2, deletions: 1 }); + }); + + test("non-ASCII path (raw UTF-8)", () => { + const raw = "3\t1\tsrc/ๆ—ฅๆœฌ่ชž.ts\0"; + const result = parseNumstat(raw); + expect(result.get("src/ๆ—ฅๆœฌ่ชž.ts")).toEqual({ additions: 3, deletions: 1 }); + }); +}); + +describe("parseNameStatus", () => { + test("regular modification", () => { + const raw = "M\x00src/foo.ts\x00"; + expect(parseNameStatus(raw)).toEqual([{ status: "M", path: "src/foo.ts" }]); + }); + + test("multiple regular entries", () => { + const raw = "M\x00src/foo.ts\x00A\x00src/bar.ts\x00D\x00src/baz.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "M", path: "src/foo.ts" }, + { status: "A", path: "src/bar.ts" }, + { status: "D", path: "src/baz.ts" }, + ]); + }); + + test("rename with similarity score", () => { + const raw = "R100\x00src/old.ts\x00src/new.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "R", path: "src/new.ts", oldPath: "src/old.ts" }, + ]); + }); + + test("copy with similarity score", () => { + const raw = "C85\x00src/src.ts\x00src/copy.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "C", path: "src/copy.ts", oldPath: "src/src.ts" }, + ]); + }); + + test("non-ASCII path stays raw (matches numstat -z)", () => { + const raw = "M\x00src/ๆ—ฅๆœฌ่ชž.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "M", path: "src/ๆ—ฅๆœฌ่ชž.ts" }, + ]); + }); + + test("path containing tab is preserved", () => { + const raw = "M\x00weird\tpath.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "M", path: "weird\tpath.ts" }, + ]); + }); + + test("mixed regular and rename", () => { + const raw = + "M\x00src/foo.ts\x00R85\x00src/old.ts\x00src/new.ts\x00A\x00src/bar.ts\x00"; + expect(parseNameStatus(raw)).toEqual([ + { status: "M", path: "src/foo.ts" }, + { status: "R", path: "src/new.ts", oldPath: "src/old.ts" }, + { status: "A", path: "src/bar.ts" }, + ]); + }); + + test("empty input returns empty array", () => { + expect(parseNameStatus("")).toEqual([]); + }); +}); diff --git a/packages/host-service/src/trpc/router/git/utils/git-helpers.ts b/packages/host-service/src/trpc/router/git/utils/git-helpers.ts index 022ea30bc3f..7fc4cbe80a1 100644 --- a/packages/host-service/src/trpc/router/git/utils/git-helpers.ts +++ b/packages/host-service/src/trpc/router/git/utils/git-helpers.ts @@ -1,4 +1,5 @@ import type { SimpleGit } from "simple-git"; +import { resolveUpstream } from "../../../../runtime/git/refs"; import type { Branch, ChangedFile, FileStatus } from "../types"; /** Map git's single-letter status codes to GitHub-aligned FileStatus */ @@ -23,38 +24,64 @@ export function mapGitStatus(code: string): FileStatus { } } +/** + * Parse the NUL-delimited output of `git diff --numstat -z`. Renames + * appear as `\t\t\0\0\0` โ€” three NUL-separated + * cells โ€” and are indexed under both source and destination paths so + * callers keyed by either get a hit. + */ export function parseNumstat( raw: string, ): Map { const result = new Map(); - for (const line of raw.trim().split("\n")) { - if (!line) continue; - const [add, del, ...pathParts] = line.split("\t"); - const path = pathParts.join("\t"); - result.set(path, { - additions: add === "-" ? 0 : Number.parseInt(add ?? "0", 10), - deletions: del === "-" ? 0 : Number.parseInt(del ?? "0", 10), - }); + const entries = raw.split("\0"); + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + if (!entry) continue; + const t1 = entry.indexOf("\t"); + const t2 = t1 >= 0 ? entry.indexOf("\t", t1 + 1) : -1; + if (t1 < 0 || t2 < 0) continue; + const add = entry.slice(0, t1); + const del = entry.slice(t1 + 1, t2); + const pathMaybe = entry.slice(t2 + 1); + const stats = { + additions: add === "-" ? 0 : Number.parseInt(add || "0", 10), + deletions: del === "-" ? 0 : Number.parseInt(del || "0", 10), + }; + if (pathMaybe === "") { + const oldPath = entries[++i] ?? ""; + const newPath = entries[++i] ?? ""; + if (newPath) result.set(newPath, stats); + if (oldPath) result.set(oldPath, stats); + } else { + result.set(pathMaybe, stats); + } } return result; } +/** + * Parse `git diff --name-status -z`. Each record is the status letter + * followed by one path (regular) or two paths (rename/copy), with NUL + * separators. Using -z avoids path quoting mismatches with numstat -z + * for non-ASCII filenames. + */ export function parseNameStatus( raw: string, ): Array<{ status: string; path: string; oldPath?: string }> { const results: Array<{ status: string; path: string; oldPath?: string }> = []; - for (const line of raw.trim().split("\n")) { - if (!line) continue; - const parts = line.split("\t"); - const statusCode = parts[0]?.[0] ?? "?"; + const fields = raw.split("\0"); + for (let i = 0; i < fields.length; i++) { + const head = fields[i]; + if (!head) continue; + const statusCode = head[0] ?? "?"; if (statusCode === "R" || statusCode === "C") { - results.push({ - status: statusCode, - path: parts[2] ?? "", - oldPath: parts[1], - }); + const oldPath = fields[++i] ?? ""; + const newPath = fields[++i] ?? ""; + results.push({ status: statusCode, path: newPath, oldPath }); } else { - results.push({ status: statusCode, path: parts[1] ?? "" }); + const path = fields[++i] ?? ""; + results.push({ status: statusCode, path }); } } return results; @@ -75,43 +102,55 @@ export async function getDefaultBranchName( } } +/** + * Resolve the base comparison for "this branch vs its upstream default" + * views. Honors the local default branch's configured upstream + * (e.g. `upstream/main`) before falling back to `origin/`. Returns + * null when no default branch can be determined. + */ +export async function resolveBaseComparison( + git: SimpleGit, + explicitBranch?: string, +): Promise<{ branchName: string; baseRef: string } | null> { + const branchName = explicitBranch ?? (await getDefaultBranchName(git)); + if (!branchName) return null; + const upstream = await resolveUpstream(git, branchName); + // Git encodes a branch tracking another local branch as + // `branch..remote = .` โ€” in that case the merge target is + // already a bare branch name in this repo, not `./`. + const baseRef = upstream + ? upstream.remote === "." + ? upstream.remoteBranch + : `${upstream.remote}/${upstream.remoteBranch}` + : `origin/${branchName}`; + return { branchName, baseRef }; +} + export async function buildBranch( git: SimpleGit, name: string, isHead: boolean, compareRef?: string, - options?: { isRemote?: boolean }, ): Promise { - const isRemote = options?.isRemote ?? false; let upstream: string | null = null; let aheadCount = 0; let behindCount = 0; let lastCommitHash = ""; let lastCommitDate = ""; - // Remote-tracking branches don't have `branch..remote` config - // entries, so skip the upstream probe entirely for them. - if (!isRemote) { - try { - const remote = ( - await git.raw(["config", `branch.${name}.remote`]).catch(() => "") - ).trim(); - const merge = ( - await git.raw(["config", `branch.${name}.merge`]).catch(() => "") - ).trim(); - upstream = - remote && merge - ? `${remote}/${merge.replace("refs/heads/", "")}` - : null; - } catch { - upstream = null; - } + try { + const remote = ( + await git.raw(["config", `branch.${name}.remote`]).catch(() => "") + ).trim(); + const merge = ( + await git.raw(["config", `branch.${name}.merge`]).catch(() => "") + ).trim(); + upstream = + remote && merge ? `${remote}/${merge.replace("refs/heads/", "")}` : null; + } catch { + upstream = null; } - // The ref used for git commands โ€” remote branches must be read via - // `origin/` even though we store the short name in the Branch. - const ref = isRemote ? `origin/${name}` : name; - if (compareRef) { try { const counts = ( @@ -119,7 +158,7 @@ export async function buildBranch( "rev-list", "--left-right", "--count", - `${compareRef}...${ref}`, + `${compareRef}...${name}`, ]) ).trim(); const [behind, ahead] = counts.split("\t").map(Number); @@ -129,7 +168,7 @@ export async function buildBranch( } try { - const log = (await git.raw(["log", "-1", "--format=%H\t%aI", ref])).trim(); + const log = (await git.raw(["log", "-1", "--format=%H\t%aI", name])).trim(); const [hash, date] = log.split("\t"); lastCommitHash = hash ?? ""; lastCommitDate = date ?? ""; @@ -138,7 +177,6 @@ export async function buildBranch( return { name, isHead, - isRemote, upstream, aheadCount, behindCount, @@ -153,8 +191,8 @@ export async function getChangedFilesForDiff( ): Promise { try { const [nameStatusRaw, numstatRaw] = await Promise.all([ - git.raw(["diff", "--name-status", ...diffArgs]), - git.raw(["diff", "--numstat", ...diffArgs]), + git.raw(["diff", "--name-status", "-z", ...diffArgs]), + git.raw(["diff", "--numstat", "-z", ...diffArgs]), ]); const nameStatus = parseNameStatus(nameStatusRaw); const numstat = parseNumstat(numstatRaw); diff --git a/packages/host-service/src/trpc/router/git/v2-diff-surfaces.integration.test.ts b/packages/host-service/src/trpc/router/git/v2-diff-surfaces.integration.test.ts new file mode 100644 index 00000000000..7894b6daa18 --- /dev/null +++ b/packages/host-service/src/trpc/router/git/v2-diff-surfaces.integration.test.ts @@ -0,0 +1,413 @@ +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import { mkdtempSync, rmSync } from "node:fs"; +import { writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import simpleGit, { type SimpleGit } from "simple-git"; +import { resolveUpstream } from "../../../runtime/git/refs"; +import { + buildBranch, + getChangedFilesForDiff, + resolveBaseComparison, +} from "./utils/git-helpers"; + +/** + * End-to-end tests organized to mirror docs/V2_WORKSPACE_DIFF_VIEWS.md. + * Each describe block maps to one UI surface in that doc, so a reviewer + * can trace "this surface works as described" to a specific test. + */ + +async function initRepo(path: string): Promise { + const git = simpleGit(path); + await git.init(); + await git.raw(["config", "user.email", "test@example.com"]); + await git.raw(["config", "user.name", "test"]); + await git.raw(["config", "commit.gpgsign", "false"]); + await git.raw(["symbolic-ref", "HEAD", "refs/heads/main"]); + return git; +} + +async function commitFile( + git: SimpleGit, + cwd: string, + name: string, + content: string, + message: string, +): Promise { + await writeFile(join(cwd, name), content); + await git.raw(["add", "--", name]); + await git.raw(["commit", "-m", message]); +} + +function mkTmp(): string { + return mkdtempSync(join(tmpdir(), "superset-v2-surfaces-")); +} + +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Surface A โ€” Creating a new workspace +// Doc: new worktree starts at the real upstream tip, not at a stale +// local copy of main. Fork users branch from `upstream/main`, not +// `origin/main`. +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("Surface A โ€” new workspace creation", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("stale local main: new branch starts at origin/main tip", async () => { + await commitFile(git, repo, "a.txt", "1", "A"); + const oldMainSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "b.txt", "2", "B"); + const freshMainSha = (await git.revparse(["HEAD"])).trim(); + + // Set origin/main to fresh; reset local main to stale. + await git.raw(["update-ref", "refs/remotes/origin/main", freshMainSha]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/main", + ]); + await git.raw(["config", "branch.main.remote", "origin"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + await git.raw(["reset", "--hard", oldMainSha]); + + // Execute the workspace-creation upgrade: when the resolved start + // point is local default, we swap to the configured upstream ref. + const upstream = await resolveUpstream(git, "main"); + expect(upstream).toEqual({ remote: "origin", remoteBranch: "main" }); + const startRef = `${upstream?.remote}/${upstream?.remoteBranch}`; + + const worktreePath = join(repo, "..", `${repo.split("/").pop()}-wt`); + await git.raw([ + "worktree", + "add", + "--no-track", + "-b", + "feature", + worktreePath, + startRef, + ]); + + const wtGit = simpleGit(worktreePath); + const wtHead = (await wtGit.revparse(["HEAD"])).trim(); + expect(wtHead).toBe(freshMainSha); + expect(wtHead).not.toBe(oldMainSha); + + rmSync(worktreePath, { recursive: true, force: true }); + }); + + test("fork workflow: local main tracks upstream/main, not origin/main", async () => { + await commitFile(git, repo, "a.txt", "1", "A"); + const originSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "b.txt", "2", "B"); + const upstreamSha = (await git.revparse(["HEAD"])).trim(); + + // origin/main = fork (older), upstream/main = canonical (newer). + await git.raw(["update-ref", "refs/remotes/origin/main", originSha]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/main", + ]); + await git.raw(["update-ref", "refs/remotes/upstream/main", upstreamSha]); + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + await git.raw(["reset", "--hard", originSha]); + + const upstream = await resolveUpstream(git, "main"); + expect(upstream).toEqual({ remote: "upstream", remoteBranch: "main" }); + const startRef = `${upstream?.remote}/${upstream?.remoteBranch}`; + + const worktreePath = join(repo, "..", `${repo.split("/").pop()}-wt`); + await git.raw([ + "worktree", + "add", + "--no-track", + "-b", + "feature", + worktreePath, + startRef, + ]); + + const wtGit = simpleGit(worktreePath); + const wtHead = (await wtGit.revparse(["HEAD"])).trim(); + expect(wtHead).toBe(upstreamSha); // canonical tip, not fork's + expect(wtHead).not.toBe(originSha); + + rmSync(worktreePath, { recursive: true, force: true }); + }); + + test("no upstream configured: falls back to local ref (no regression)", async () => { + await commitFile(git, repo, "a.txt", "1", "A"); + const sha = (await git.revparse(["HEAD"])).trim(); + + // No `branch.main.remote` / `.merge` configured. + const upstream = await resolveUpstream(git, "main"); + expect(upstream).toBeNull(); + + const worktreePath = join(repo, "..", `${repo.split("/").pop()}-wt`); + await git.raw([ + "worktree", + "add", + "--no-track", + "-b", + "feature", + worktreePath, + "main", + ]); + + const wtGit = simpleGit(worktreePath); + expect((await wtGit.revparse(["HEAD"])).trim()).toBe(sha); + + rmSync(worktreePath, { recursive: true, force: true }); + }); +}); + +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Surfaces B/C โ€” Dashboard sidebar badge & Changes tab counts +// Doc: counts reflect "me since I forked," stable as main advances, +// correct for fork workflows and non-ASCII filenames. +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("Surfaces B/C โ€” sidebar badge + Changes tab counts", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("count is stable as main advances after you forked", async () => { + await commitFile(git, repo, "shared.ts", "a\n", "A"); + await git.raw(["checkout", "-b", "feature"]); + await commitFile(git, repo, "mine.ts", "x\n", "my work"); + + await git.raw(["checkout", "main"]); + const beforeFiles = await getChangedFilesForDiff(git, ["main...feature"]); + expect(beforeFiles.map((f) => f.path).sort()).toEqual(["mine.ts"]); + + // Advance main with an unrelated commit. + await commitFile(git, repo, "unrelated.ts", "z\n", "unrelated main work"); + + const afterFilesLocal = await getChangedFilesForDiff(git, [ + "main...feature", + ]); + // Count must remain the same โ€” three-dot pins to the fork point. + expect(afterFilesLocal.map((f) => f.path).sort()).toEqual(["mine.ts"]); + // Also verify the pre-fix two-dot behavior WOULD have drifted: + const twoDot = await getChangedFilesForDiff(git, ["main", "feature"]); + expect(twoDot.map((f) => f.path).sort()).toContain("unrelated.ts"); + }); + + test("fork workflow: counts compare against upstream/main, not origin/main", async () => { + await commitFile(git, repo, "shared.ts", "a\n", "A"); + const originSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "upstream-only.ts", "u\n", "B"); + const upstreamSha = (await git.revparse(["HEAD"])).trim(); + + await git.raw(["update-ref", "refs/remotes/origin/main", originSha]); + await git.raw([ + "symbolic-ref", + "refs/remotes/origin/HEAD", + "refs/remotes/origin/main", + ]); + await git.raw(["update-ref", "refs/remotes/upstream/main", upstreamSha]); + await git.raw(["config", "branch.main.remote", "upstream"]); + await git.raw(["config", "branch.main.merge", "refs/heads/main"]); + await git.raw(["reset", "--hard", originSha]); + + const base = await resolveBaseComparison(git); + expect(base).toEqual({ branchName: "main", baseRef: "upstream/main" }); + }); + + test("non-ASCII filename reports correct additions (was +0 -0 before fix)", async () => { + await commitFile(git, repo, "README.md", "a", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "ๆ—ฅๆœฌ่ชž.ts", "line1\nline2\n", "add ja"); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const ja = files.find((f) => f.path.includes("ๆ—ฅๆœฌ่ชž")); + expect(ja?.additions).toBe(2); + expect(ja?.deletions).toBe(0); + }); + + test("three buckets (againstBase, staged, unstaged) stay distinct", async () => { + // This surface exercises more than just getChangedFilesForDiff โ€” + // the renderer merges three buckets. We verify that each bucket + // can be computed independently with the expected semantics. + await commitFile(git, repo, "a.txt", "1\n", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await commitFile(git, repo, "b.txt", "2\n", "committed on branch"); + + // Staged change: + await writeFile(join(repo, "a.txt"), "1 STAGED\n"); + await git.raw(["add", "a.txt"]); + + // Unstaged change: + await writeFile(join(repo, "c.txt"), "3\n"); + + const againstBase = await getChangedFilesForDiff(git, [ + `${baseSha}...HEAD`, + ]); + // against-base only sees committed work on this branch. + expect(againstBase.map((f) => f.path).sort()).toEqual(["b.txt"]); + }); +}); + +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Surface D โ€” Per-file diff view (merge-base content comparison) +// Doc: clicking a file shows content at fork point vs HEAD, so +// unrelated edits on main don't appear as your changes. +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("Surface D โ€” per-file diff uses merge-base", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("unrelated base-side edit to same file is hidden from per-file diff", async () => { + await commitFile(git, repo, "shared.ts", "line1\nline2\nline3\n", "A"); + const forkSha = (await git.revparse(["HEAD"])).trim(); + + await git.raw(["checkout", "-b", "feature"]); + await writeFile(join(repo, "shared.ts"), "line1\nBRANCH CHANGED\nline3\n"); + await git.raw(["commit", "-am", "branch edit"]); + + await git.raw(["checkout", "main"]); + await writeFile(join(repo, "shared.ts"), "line1\nMAIN CHANGED\nline3\n"); + await git.raw(["commit", "-am", "main edit"]); + + // The per-file diff under the new behavior shows content at the + // merge-base vs content at HEAD of feature โ€” not main's tip vs + // feature's tip. So main's unrelated edit doesn't leak in. + const mergeBase = (await git.raw(["merge-base", "main", "feature"])).trim(); + expect(mergeBase).toBe(forkSha); + + const baseContent = await git.show([`${mergeBase}:shared.ts`]); + const headContent = await git.show(["feature:shared.ts"]); + expect(baseContent).toBe("line1\nline2\nline3\n"); + expect(headContent).toBe("line1\nBRANCH CHANGED\nline3\n"); + + // And confirm the pre-fix behavior (tip-to-tip) would have shown + // main's edit as a reversal: + const mainTipContent = await git.show(["main:shared.ts"]); + expect(mainTipContent).toBe("line1\nMAIN CHANGED\nline3\n"); + // If we had diffed main:shared.ts vs feature:shared.ts the diff + // would include both edits โ€” proving merge-base is the right + // origin for a "your changes only" view. + expect(mainTipContent).not.toBe(baseContent); + }); +}); + +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Surface F โ€” Ahead/behind counts in branch lists +// Doc: 3-dot symmetric count via `rev-list --left-right --count base...branch`. +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("Surface F โ€” ahead/behind counts", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("counts are correct against a base ref", async () => { + await commitFile(git, repo, "a.txt", "A", "A"); + await git.raw(["checkout", "-b", "feature"]); + await commitFile(git, repo, "b.txt", "B", "B"); + await commitFile(git, repo, "c.txt", "C", "C"); + + await git.raw(["checkout", "main"]); + await commitFile(git, repo, "d.txt", "D", "D"); + + const branch = await buildBranch(git, "feature", false, "main"); + expect(branch.aheadCount).toBe(2); // B, C + expect(branch.behindCount).toBe(1); // D + }); + + test("feature branch not yet behind main reports behind=0", async () => { + await commitFile(git, repo, "a.txt", "A", "A"); + await git.raw(["checkout", "-b", "feature"]); + await commitFile(git, repo, "b.txt", "B", "B"); + + const branch = await buildBranch(git, "feature", true, "main"); + expect(branch.aheadCount).toBe(1); + expect(branch.behindCount).toBe(0); + }); +}); + +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Renames (separate section in the doc) +// Doc: renamed files now show correct line counts โ€” the bug was +0 -0. +// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +describe("Rename files โ€” line counts", () => { + let repo: string; + let git: SimpleGit; + + beforeEach(async () => { + repo = mkTmp(); + git = await initRepo(repo); + }); + + afterEach(() => { + rmSync(repo, { recursive: true, force: true }); + }); + + test("rename with in-file edits shows non-zero additions/deletions", async () => { + await commitFile(git, repo, "old.ts", "one\ntwo\nthree\nfour\n", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await git.raw(["mv", "old.ts", "new.ts"]); + await writeFile(join(repo, "new.ts"), "one\nTWO\nthree\nFOUR\n"); + await git.raw(["add", "new.ts"]); + await git.raw(["commit", "-m", "rename+edit"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const r = files.find((f) => f.path === "new.ts"); + expect(r?.status).toBe("renamed"); + expect(r?.oldPath).toBe("old.ts"); + expect(r?.additions).toBeGreaterThan(0); + expect(r?.deletions).toBeGreaterThan(0); + }); + + test("pure rename shows 0/0", async () => { + await commitFile(git, repo, "old.ts", "stable\n", "base"); + const baseSha = (await git.revparse(["HEAD"])).trim(); + await git.raw(["mv", "old.ts", "new.ts"]); + await git.raw(["commit", "-m", "rename"]); + + const files = await getChangedFilesForDiff(git, [`${baseSha}...HEAD`]); + const r = files.find((f) => f.path === "new.ts"); + expect(r?.status).toBe("renamed"); + expect(r?.additions).toBe(0); + expect(r?.deletions).toBe(0); + }); +}); diff --git a/packages/host-service/src/trpc/router/host/host.ts b/packages/host-service/src/trpc/router/host/host.ts index ca3ec0f757a..922854f0c92 100644 --- a/packages/host-service/src/trpc/router/host/host.ts +++ b/packages/host-service/src/trpc/router/host/host.ts @@ -14,19 +14,23 @@ let cachedOrganization: { async function getOrganization( api: ApiClient, + organizationId: string, ): Promise<{ id: string; name: string; slug: string }> { if ( cachedOrganization && + cachedOrganization.data.id === organizationId && Date.now() - cachedOrganization.cachedAt < ORGANIZATION_CACHE_TTL_MS ) { return cachedOrganization.data; } - const organization = await api.organization.getActiveFromJwt.query(); + const organization = await api.organization.getByIdFromJwt.query({ + id: organizationId, + }); if (!organization) { throw new TRPCError({ code: "PRECONDITION_FAILED", - message: "No active organization", + message: "Organization not found or not accessible from JWT", }); } @@ -36,8 +40,7 @@ async function getOrganization( export const hostRouter = router({ info: protectedProcedure.query(async ({ ctx }) => { - const api = (ctx as { api: ApiClient }).api; - const organization = await getOrganization(api); + const organization = await getOrganization(ctx.api, ctx.organizationId); return { hostId: getHashedDeviceId(), diff --git a/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts b/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts index b2bbec615af..7a236e8d037 100644 --- a/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts +++ b/packages/host-service/src/trpc/router/workspace-creation/utils/ai-branch-name.ts @@ -3,7 +3,7 @@ import { getSmallModel } from "@superset/chat/server/shared"; import { deduplicateBranchName } from "./sanitize-branch"; const BRANCH_NAME_INSTRUCTIONS = - "Generate a concise git branch name (2-4 words, kebab-case, descriptive). Return ONLY the branch name, nothing else."; + "Generate a concise git branch name (2-4 words, kebab-case, descriptive, 20 characters or less). Return ONLY the branch name, nothing else."; const MAX_BRANCH_LENGTH = 100; @@ -30,7 +30,7 @@ export async function generateBranchNameFromPrompt( prompt: string, existingBranches: string[], ): Promise { - const model = getSmallModel(); + const model = await getSmallModel(); if (!model) return null; let generated: string | null; diff --git a/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts b/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts index 1f00c99608f..daa9bb677d2 100644 --- a/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts +++ b/packages/host-service/src/trpc/router/workspace-creation/workspace-creation.ts @@ -1,5 +1,5 @@ -import { existsSync, mkdirSync } from "node:fs"; -import { dirname, join, resolve, sep } from "node:path"; +import { existsSync } from "node:fs"; +import { join, resolve, sep } from "node:path"; import { getDeviceName, getHashedDeviceId } from "@superset/shared/device-info"; import { TRPCError } from "@trpc/server"; import { and, eq } from "drizzle-orm"; @@ -11,10 +11,11 @@ import { type ResolvedRef, resolveDefaultBranchName, resolveRef, + resolveUpstream, } from "../../../runtime/git/refs"; -import { createSimpleGitWithEnv } from "../../../runtime/git/simple-git"; import { createTerminalSessionInternal } from "../../../terminal/terminal"; import type { HostServiceContext } from "../../../types"; +import type { ProjectNotSetupCause } from "../../error-types"; import { protectedProcedure, router } from "../../index"; import { generateBranchNameFromPrompt } from "./utils/ai-branch-name"; import { execGh } from "./utils/exec-gh"; @@ -71,6 +72,17 @@ function sweepStaleProgress(): void { // โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +function projectNotSetupError(projectId: string): TRPCError { + return new TRPCError({ + code: "PRECONDITION_FAILED", + message: "Project is not set up on this host", + cause: { + kind: "PROJECT_NOT_SETUP", + projectId, + } satisfies ProjectNotSetupCause, + }); +} + function safeResolveWorktreePath(repoPath: string, branchName: string): string { const worktreesRoot = resolve(repoPath, ".worktrees"); const worktreePath = resolve(worktreesRoot, branchName); @@ -709,40 +721,11 @@ export const workspaceCreationRouter = router({ const deviceName = getDeviceName(); setProgress(input.pendingId, "ensuring_repo"); - // 1. Resolve / ensure project locally - let localProject = ctx.db.query.projects + const localProject = ctx.db.query.projects .findFirst({ where: eq(projects.id, input.projectId) }) .sync(); - if (!localProject) { - const cloudProject = await ctx.api.v2Project.get.query({ - organizationId: ctx.organizationId, - id: input.projectId, - }); - - if (!cloudProject.repoCloneUrl) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Project has no linked GitHub repository โ€” cannot clone", - }); - } - - const homeDir = process.env.HOME || process.env.USERPROFILE || "/tmp"; - const repoPath = join(homeDir, ".superset", "repos", input.projectId); - - if (!existsSync(repoPath)) { - mkdirSync(dirname(repoPath), { recursive: true }); - await createSimpleGitWithEnv().clone( - cloudProject.repoCloneUrl, - repoPath, - ); - } - - localProject = ctx.db - .insert(projects) - .values({ id: input.projectId, repoPath }) - .returning() - .get(); + throw projectNotSetupError(input.projectId); } setProgress(input.pendingId, "creating_worktree"); @@ -780,13 +763,48 @@ export const workspaceCreationRouter = router({ // races against stale cached refs (a workspace branch with an // incidental `refs/remotes/origin/` cache would silently win). // Falls back to probing for callers that don't pass the hint. - const startPoint = + let startPoint: ResolvedRef = input.composer.baseBranch && input.composer.baseBranchSource ? buildStartPointFromHint( input.composer.baseBranch, input.composer.baseBranchSource, ) : await resolveStartPoint(git, input.composer.baseBranch); + + // Local default branches are rarely fast-forwarded; swap to the + // branch's configured upstream so we fork from the real tip, not a + // stale local ref. Non-default branches stay local-first by design. + if (startPoint.kind === "local") { + const defaultBranchName = await resolveDefaultBranchName(git); + if (startPoint.shortName === defaultBranchName) { + const upstream = await resolveUpstream(git, defaultBranchName); + if (upstream) { + const remoteRef = asRemoteRef( + upstream.remote, + upstream.remoteBranch, + ); + const remoteExists = await git + .raw([ + "rev-parse", + "--verify", + "--quiet", + `${remoteRef}^{commit}`, + ]) + .then(() => true) + .catch(() => false); + if (remoteExists) { + startPoint = { + kind: "remote-tracking", + fullRef: remoteRef, + shortName: upstream.remoteBranch, + remote: upstream.remote, + remoteShortName: `${upstream.remote}/${upstream.remoteBranch}`, + }; + } + } + } + } + console.log( `[workspaceCreation.create] start point: ${startPoint.kind} (${ input.composer.baseBranchSource ? "from hint" : "resolved" @@ -817,21 +835,8 @@ export const workspaceCreationRouter = router({ // --no-track keeps `git pull` / ahead-behind counts from treating // the start point as the branch's home. Push targeting is handled // separately by push.autoSetupRemote (set below). - // - // FORK NOTE: use fullRef for remote-tracking refs instead of - // shortName. The short form `origin/foo` is still ambiguous - // with a local branch literally named `origin/foo` โ€” which is the - // exact edge case this refactor was supposed to address. Passing - // `refs/remotes/origin/foo` removes the ambiguity at the - // `git worktree add` boundary too. - let startPointArg: string; - if (startPoint.kind === "head") { - startPointArg = "HEAD"; - } else if (startPoint.kind === "remote-tracking") { - startPointArg = startPoint.fullRef; - } else { - startPointArg = startPoint.fullRef; - } + const startPointArg = + startPoint.kind === "head" ? "HEAD" : startPoint.shortName; await git.raw([ "worktree", "add", @@ -839,7 +844,9 @@ export const workspaceCreationRouter = router({ "-b", branchName, worktreePath, - startPointArg, + startPoint.kind === "remote-tracking" + ? startPoint.remoteShortName + : startPointArg, ]); // Enable autoSetupRemote so the first terminal `git push` creates @@ -867,16 +874,10 @@ export const workspaceCreationRouter = router({ }); // Record the base branch in git config so the Changes tab knows what - // to compare against on first open. - // - // FORK NOTE: only write for remote-tracking start points. Downstream - // (git.getStatus / listCommits / getDiff) always rebuilds the compare - // ref as `origin/${baseBranch}`, so a local-only branch name would - // resolve to a non-existent `origin/` and the Changes tab - // would silently break (upstream bug reported in PR #204 review). - // Skipping the write leaves baseBranch null for local-only bases โ€” - // downstream falls back to the default branch behavior. - if (startPoint.kind === "remote-tracking") { + // to compare against on first open. startPoint.shortName is the ref + // we actually forked from (user selection, resolved against local / + // remote). Skipped for "head" start point โ€” no meaningful base. + if (startPoint.kind !== "head") { await git .raw(["config", `branch.${branchName}.base`, startPoint.shortName]) .catch((err) => { @@ -1056,36 +1057,11 @@ export const workspaceCreationRouter = router({ .mutation(async ({ ctx, input }) => { setProgress(input.pendingId, "ensuring_repo"); - // Ensure project locally (clone if missing) โ€” shared across both paths. - let localProject = ctx.db.query.projects + const localProject = ctx.db.query.projects .findFirst({ where: eq(projects.id, input.projectId) }) .sync(); - if (!localProject) { - const cloudProject = await ctx.api.v2Project.get.query({ - organizationId: ctx.organizationId, - id: input.projectId, - }); - if (!cloudProject.repoCloneUrl) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Project has no linked GitHub repository โ€” cannot clone", - }); - } - const homeDir = process.env.HOME || process.env.USERPROFILE || "/tmp"; - const repoPath = join(homeDir, ".superset", "repos", input.projectId); - if (!existsSync(repoPath)) { - mkdirSync(dirname(repoPath), { recursive: true }); - await createSimpleGitWithEnv().clone( - cloudProject.repoCloneUrl, - repoPath, - ); - } - localProject = ctx.db - .insert(projects) - .values({ id: input.projectId, repoPath }) - .returning() - .get(); + throw projectNotSetupError(input.projectId); } setProgress(input.pendingId, "creating_worktree"); @@ -1366,10 +1342,7 @@ export const workspaceCreationRouter = router({ .findFirst({ where: eq(projects.id, input.projectId) }) .sync(); if (!localProject) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "Project is not set up locally", - }); + throw projectNotSetupError(input.projectId); } const branch = input.branch.trim(); diff --git a/packages/host-service/test/pull-requests.test.ts b/packages/host-service/test/pull-requests.test.ts index 685eda3ed30..206fd050b44 100644 --- a/packages/host-service/test/pull-requests.test.ts +++ b/packages/host-service/test/pull-requests.test.ts @@ -64,6 +64,9 @@ describe("PullRequestRuntimeManager branch sync", () => { expect(setMock).toHaveBeenCalledWith({ branch: "feature/unborn", headSha: null, + upstreamOwner: null, + upstreamRepo: null, + upstreamBranch: null, }); expect(refreshProjectMock).toHaveBeenCalledWith("project-1", true); }); diff --git a/packages/local-db/drizzle/0040_agent_preset_permissions_migrated_at.sql b/packages/local-db/drizzle/0040_agent_preset_permissions_migrated_at.sql new file mode 100644 index 00000000000..4b67e263d8b --- /dev/null +++ b/packages/local-db/drizzle/0040_agent_preset_permissions_migrated_at.sql @@ -0,0 +1 @@ +ALTER TABLE `settings` ADD `agent_preset_permissions_migrated_at` integer; \ No newline at end of file diff --git a/packages/local-db/drizzle/meta/0040_snapshot.json b/packages/local-db/drizzle/meta/0040_snapshot.json index 1a8e0526f2a..331200d6956 100644 --- a/packages/local-db/drizzle/meta/0040_snapshot.json +++ b/packages/local-db/drizzle/meta/0040_snapshot.json @@ -1,8 +1,8 @@ { "version": "6", "dialect": "sqlite", - "id": "edba1e1b-a5d4-4398-ac58-dd28d5d9ba90", - "prevId": "7c9e72d5-9be6-4be5-b6f1-4a32591d30cb", + "id": "ecc4c8b8-883e-4e25-8ae4-d4d6298d1030", + "prevId": "5a8d1776-f90b-4bf8-b6a0-c6142deecfc2", "tables": { "browser_history": { "name": "browser_history", @@ -80,75 +80,6 @@ "uniqueConstraints": {}, "checkConstraints": {} }, - "browser_site_permissions": { - "name": "browser_site_permissions", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true, - "autoincrement": false - }, - "origin": { - "name": "origin", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "kind": { - "name": "kind", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "value": { - "name": "value", - "type": "text", - "primaryKey": false, - "notNull": true, - "autoincrement": false, - "default": "'ask'" - }, - "created_at": { - "name": "created_at", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - }, - "updated_at": { - "name": "updated_at", - "type": "integer", - "primaryKey": false, - "notNull": true, - "autoincrement": false - } - }, - "indexes": { - "browser_site_permissions_origin_idx": { - "name": "browser_site_permissions_origin_idx", - "columns": [ - "origin" - ], - "isUnique": false - }, - "browser_site_permissions_origin_kind_unique": { - "name": "browser_site_permissions_origin_kind_unique", - "columns": [ - "origin", - "kind" - ], - "isUnique": true - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "checkConstraints": {} - }, "organization_members": { "name": "organization_members", "columns": { @@ -528,6 +459,13 @@ "notNull": false, "autoincrement": false }, + "agent_preset_permissions_migrated_at": { + "name": "agent_preset_permissions_migrated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, "selected_ringtone_id": { "name": "selected_ringtone_id", "type": "text", @@ -599,13 +537,6 @@ "notNull": false, "autoincrement": false }, - "prevent_agent_sleep": { - "name": "prevent_agent_sleep", - "type": "integer", - "primaryKey": false, - "notNull": false, - "autoincrement": false - }, "delete_local_branch": { "name": "delete_local_branch", "type": "integer", @@ -689,6 +620,13 @@ "primaryKey": false, "notNull": false, "autoincrement": false + }, + "expose_host_service_via_relay": { + "name": "expose_host_service_via_relay", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false } }, "indexes": {}, diff --git a/packages/local-db/drizzle/meta/_journal.json b/packages/local-db/drizzle/meta/_journal.json index c6886654b11..91d91dced30 100644 --- a/packages/local-db/drizzle/meta/_journal.json +++ b/packages/local-db/drizzle/meta/_journal.json @@ -484,6 +484,13 @@ "when": 1776884577928, "tag": "0068_add_agent_kind_codex_fields", "breakpoints": true + }, + { + "idx": 40, + "version": "6", + "when": 1776796221146, + "tag": "0040_agent_preset_permissions_migrated_at", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/local-db/package.json b/packages/local-db/package.json index 6ade8993a43..22baef34b1b 100644 --- a/packages/local-db/package.json +++ b/packages/local-db/package.json @@ -23,7 +23,7 @@ "typecheck": "tsc --noEmit --emitDeclarationOnly false" }, "dependencies": { - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "uuid": "^13.0.0", "zod": "^4.3.5" }, diff --git a/packages/local-db/src/schema/schema.ts b/packages/local-db/src/schema/schema.ts index 541cc219487..1005e41a46f 100644 --- a/packages/local-db/src/schema/schema.ts +++ b/packages/local-db/src/schema/schema.ts @@ -210,6 +210,9 @@ export const settings = sqliteTable("settings", { agentCustomDefinitions: text("agent_custom_definitions", { mode: "json", }).$type(), + agentPresetPermissionsMigratedAt: integer( + "agent_preset_permissions_migrated_at", + ), selectedRingtoneId: text("selected_ringtone_id"), activeOrganizationId: text("active_organization_id"), confirmOnQuit: integer("confirm_on_quit", { mode: "boolean" }), diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 6906fc650b2..2e546bbc50c 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -25,7 +25,7 @@ "@modelcontextprotocol/sdk": "^1.26.0", "@superset/db": "workspace:*", "@superset/shared": "workspace:*", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "zod": "^4.3.5" }, "devDependencies": { diff --git a/packages/shared/package.json b/packages/shared/package.json index bb5c03629d2..a2fa14a9ef0 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -44,6 +44,30 @@ "types": "./src/agent-prompt-template.ts", "default": "./src/agent-prompt-template.ts" }, + "./agent-custom": { + "types": "./src/agent-custom.ts", + "default": "./src/agent-custom.ts" + }, + "./billing": { + "types": "./src/billing.ts", + "default": "./src/billing.ts" + }, + "./workspace-launch": { + "types": "./src/workspace-launch/index.ts", + "default": "./src/workspace-launch/index.ts" + }, + "./agent-settings": { + "types": "./src/agent-settings.ts", + "default": "./src/agent-settings.ts" + }, + "./agent-launch-request": { + "types": "./src/agent-launch-request.ts", + "default": "./src/agent-launch-request.ts" + }, + "./agent-permissions-migration": { + "types": "./src/agent-permissions-migration.ts", + "default": "./src/agent-permissions-migration.ts" + }, "./task-slug": { "types": "./src/task-slug.ts", "default": "./src/task-slug.ts" @@ -64,13 +88,17 @@ "types": "./src/device-info.ts", "default": "./src/device-info.ts" }, + "./github-remote": { + "types": "./src/github-remote.ts", + "default": "./src/github-remote.ts" + }, "./shell-ready-scanner": { "types": "./src/shell-ready-scanner.ts", "default": "./src/shell-ready-scanner.ts" }, - "./simple-git-unsafe": { - "types": "./src/simple-git-unsafe.ts", - "default": "./src/simple-git-unsafe.ts" + "./rrule": { + "types": "./src/rrule.ts", + "default": "./src/rrule.ts" } }, "scripts": { @@ -79,10 +107,14 @@ "test": "bun test" }, "dependencies": { + "@date-fns/tz": "^1.4.1", + "friendly-words": "^1.3.1", + "rrule": "^2.8.1", "zod": "^4.3.5" }, "devDependencies": { "@superset/typescript": "workspace:*", + "@types/friendly-words": "^1.2.2", "bun-types": "^1.3.1", "typescript": "^5.9.3" } diff --git a/packages/shared/src/agent-permissions-migration.ts b/packages/shared/src/agent-permissions-migration.ts new file mode 100644 index 00000000000..cda447361c9 --- /dev/null +++ b/packages/shared/src/agent-permissions-migration.ts @@ -0,0 +1,121 @@ +import type { + AgentPresetOverride, + AgentPresetOverrideEnvelope, +} from "./agent-custom"; + +type LegacyBuiltinAgentId = + | "claude" + | "codex" + | "gemini" + | "copilot" + | "cursor-agent"; + +interface LegacyAgentOverride { + command?: string; + promptCommand?: string; + promptCommandSuffix?: string; +} + +/** + * Pre-#3546 (canary) builtin terminal agent command strings. Used once, at + * the agent-preset permissions backfill, to restore YOLO-style defaults for + * users who were exposed to the old values before we swapped in safer ones. + * See runAgentPresetPermissionsMigration in the settings router. + */ +export const LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES: Readonly< + Record +> = Object.freeze({ + claude: { + command: "claude --dangerously-skip-permissions", + }, + codex: { + command: + 'codex -c model_reasoning_effort="high" --dangerously-bypass-approvals-and-sandbox -c model_reasoning_summary="detailed" -c model_supports_reasoning_summaries=true', + promptCommand: + 'codex -c model_reasoning_effort="high" --dangerously-bypass-approvals-and-sandbox -c model_reasoning_summary="detailed" -c model_supports_reasoning_summaries=true --', + }, + gemini: { + command: "gemini --yolo", + promptCommand: "gemini", + promptCommandSuffix: "--yolo", + }, + copilot: { + command: "copilot --allow-all", + promptCommand: "copilot -i --allow-all", + promptCommandSuffix: "--yolo", + }, + "cursor-agent": { + promptCommandSuffix: "--yolo", + }, +}); + +/** + * Exact full-string matches for the pre-#3546 builtin `command` field of the + * four agents seeded into a user's terminal-preset row on first app open. If + * any of a user's stored terminal-preset commands matches one of these + * strings, they were seeded on a pre-#3546 build and are an "existing user" + * for the permissions backfill. Substring matching would false-positive on + * user-authored commands that happen to contain `--yolo` etc. + */ +const LEGACY_SEEDED_TERMINAL_PRESET_COMMAND_STRINGS = new Set([ + LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES.claude.command, + LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES.codex.command, + LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES.gemini.command, + LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES.copilot.command, +] as string[]); + +export function terminalPresetsMatchPre3546Seed( + presets: ReadonlyArray<{ commands?: string[] }> | null | undefined, +): boolean { + if (!presets) return false; + return presets.some((preset) => + preset.commands?.some((command) => + LEGACY_SEEDED_TERMINAL_PRESET_COMMAND_STRINGS.has(command), + ), + ); +} + +/** + * Merge pre-#3546 command strings into the user's override envelope for each + * affected builtin agent, but only for fields the user hasn't already set + * themselves (so their own customizations always win). + */ +export function applyLegacyPermissionsOverrides( + currentEnvelope: AgentPresetOverrideEnvelope, +): AgentPresetOverrideEnvelope { + const nextById = new Map( + currentEnvelope.presets.map((preset) => [preset.id, preset]), + ); + + for (const [agentId, legacy] of Object.entries( + LEGACY_BUILTIN_TERMINAL_AGENT_OVERRIDES, + )) { + const existing: AgentPresetOverride = nextById.get(agentId) ?? { + id: agentId, + }; + const next: AgentPresetOverride = { ...existing, id: agentId }; + + if (legacy.command !== undefined && !Object.hasOwn(existing, "command")) { + next.command = legacy.command; + } + if ( + legacy.promptCommand !== undefined && + !Object.hasOwn(existing, "promptCommand") + ) { + next.promptCommand = legacy.promptCommand; + } + if ( + legacy.promptCommandSuffix !== undefined && + !Object.hasOwn(existing, "promptCommandSuffix") + ) { + next.promptCommandSuffix = legacy.promptCommandSuffix; + } + + nextById.set(agentId, next); + } + + return { + version: 1, + presets: Array.from(nextById.values()), + }; +} diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index 91315376c94..b1bed9f4c54 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -2,6 +2,8 @@ export const AUTH_PROVIDERS = ["github", "google"] as const; export type AuthProvider = (typeof AUTH_PROVIDERS)[number]; +export const ORGANIZATION_HEADER = "x-superset-organization-id"; + // Deep link protocol schemes (used for desktop OAuth callbacks) export const PROTOCOL_SCHEMES = { DEV: "superset-dev", diff --git a/packages/trpc/package.json b/packages/trpc/package.json index b49abcd9cf6..48101e1cdd7 100644 --- a/packages/trpc/package.json +++ b/packages/trpc/package.json @@ -28,7 +28,7 @@ "@upstash/qstash": "^2.8.4", "@vercel/blob": "^2.0.0", "@vercel/kv": "^3.0.0", - "drizzle-orm": "0.45.1", + "drizzle-orm": "0.45.2", "superjson": "^2.2.5", "zod": "^4.3.5" }, diff --git a/packages/trpc/src/router/agent/agent.ts b/packages/trpc/src/router/agent/agent.ts index 06969982f47..72a5439e2b2 100644 --- a/packages/trpc/src/router/agent/agent.ts +++ b/packages/trpc/src/router/agent/agent.ts @@ -21,7 +21,7 @@ export const agentRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ code: "BAD_REQUEST", diff --git a/packages/trpc/src/router/api-key/api-key.ts b/packages/trpc/src/router/api-key/api-key.ts index 2e30fcbb5e6..da5f46b58e9 100644 --- a/packages/trpc/src/router/api-key/api-key.ts +++ b/packages/trpc/src/router/api-key/api-key.ts @@ -7,7 +7,7 @@ export const apiKeyRouter = { create: protectedProcedure .input(z.object({ name: z.string().min(1) })) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ code: "BAD_REQUEST", diff --git a/packages/trpc/src/router/billing/billing.ts b/packages/trpc/src/router/billing/billing.ts index 7dc45ed83ec..3616f241006 100644 --- a/packages/trpc/src/router/billing/billing.ts +++ b/packages/trpc/src/router/billing/billing.ts @@ -27,12 +27,10 @@ function subtractMonthsClamped(date: Date, months: number) { } async function requireOwnerWithCustomer(ctx: { - session: { - session: { activeOrganizationId: string | null }; - user: { id: string }; - }; + session: { user: { id: string } }; + activeOrganizationId: string | null; }) { - const activeOrgId = ctx.session.session.activeOrganizationId; + const activeOrgId = ctx.activeOrganizationId; if (!activeOrgId) { throw new TRPCError({ code: "BAD_REQUEST", @@ -68,7 +66,7 @@ async function requireOwnerWithCustomer(ctx: { export const billingRouter = { invoices: protectedProcedure.query(async ({ ctx }) => { - const activeOrgId = ctx.session.session.activeOrganizationId; + const activeOrgId = ctx.activeOrganizationId; if (!activeOrgId) { throw new TRPCError({ code: "BAD_REQUEST", diff --git a/packages/trpc/src/router/chat/chat.ts b/packages/trpc/src/router/chat/chat.ts index c113d2376a3..2a7c1d2f916 100644 --- a/packages/trpc/src/router/chat/chat.ts +++ b/packages/trpc/src/router/chat/chat.ts @@ -8,6 +8,11 @@ import { protectedProcedure } from "../../trpc"; import { uploadChatAttachment } from "./utils/upload-chat-attachment"; const AVAILABLE_MODELS = [ + { + id: "anthropic/claude-opus-4-7", + name: "Opus 4.7", + provider: "Anthropic", + }, { id: "anthropic/claude-opus-4-6", name: "Opus 4.6", @@ -58,7 +63,7 @@ export const chatRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ @@ -90,7 +95,7 @@ export const chatRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ @@ -126,7 +131,7 @@ export const chatRouter = { deleteSession: protectedProcedure .input(z.object({ sessionId: z.uuid() })) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ diff --git a/packages/trpc/src/router/device/device.ts b/packages/trpc/src/router/device/device.ts index 3ec2da7e62f..00f11c20057 100644 --- a/packages/trpc/src/router/device/device.ts +++ b/packages/trpc/src/router/device/device.ts @@ -79,7 +79,7 @@ export const deviceRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ code: "BAD_REQUEST", @@ -132,7 +132,7 @@ export const deviceRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ code: "BAD_REQUEST", @@ -180,7 +180,7 @@ export const deviceRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = ctx.session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ code: "BAD_REQUEST", diff --git a/packages/trpc/src/router/organization/organization.ts b/packages/trpc/src/router/organization/organization.ts index 9258916ae7d..4d7045b6f78 100644 --- a/packages/trpc/src/router/organization/organization.ts +++ b/packages/trpc/src/router/organization/organization.ts @@ -56,7 +56,7 @@ function verificationMatchesInvitation({ export const organizationRouter = { getActive: protectedProcedure.query(async ({ ctx }) => { - const orgId = ctx.session.session.activeOrganizationId; + const orgId = ctx.activeOrganizationId; if (!orgId) return null; const membership = await db.query.members.findFirst({ @@ -92,6 +92,26 @@ export const organizationRouter = { return org ?? null; }), + getByIdFromJwt: jwtProcedure + .input(z.object({ id: z.string() })) + .query(async ({ ctx, input }) => { + if (!ctx.organizationIds.includes(input.id)) return null; + + const membership = await db.query.members.findFirst({ + where: and( + eq(members.userId, ctx.userId), + eq(members.organizationId, input.id), + ), + }); + if (!membership) return null; + + const org = await db.query.organizations.findFirst({ + where: eq(organizations.id, input.id), + columns: { id: true, name: true, slug: true }, + }); + return org ?? null; + }), + getInvitation: protectedProcedure .input(z.uuid()) .query(async ({ ctx, input }) => { diff --git a/packages/trpc/src/router/task/task.ts b/packages/trpc/src/router/task/task.ts index adf1c7d1226..b9ef11852d6 100644 --- a/packages/trpc/src/router/task/task.ts +++ b/packages/trpc/src/router/task/task.ts @@ -170,7 +170,7 @@ async function getScopedAssigneeId( export const taskRouter = { all: protectedProcedure.query(async ({ ctx }) => { - const organizationId = await requireActiveOrgMembership(ctx.session); + const organizationId = await requireActiveOrgMembership(ctx); const assignee = alias(users, "assignee"); const creator = alias(users, "creator"); @@ -215,7 +215,7 @@ export const taskRouter = { .query(({ ctx, input }) => getTaskById(ctx.session.user.id, input)), bySlug: protectedProcedure.input(z.string()).query(async ({ ctx, input }) => { - const organizationId = await requireActiveOrgMembership(ctx.session); + const organizationId = await requireActiveOrgMembership(ctx); return getTaskBySlug(ctx.session.user.id, organizationId, input); }), @@ -267,7 +267,7 @@ export const taskRouter = { createFromUi: protectedProcedure .input(createTaskFromUiSchema) .mutation(async ({ ctx, input }) => { - const organizationId = await requireActiveOrgMembership(ctx.session); + const organizationId = await requireActiveOrgMembership(ctx); for (let attempt = 0; attempt < TASK_SLUG_RETRY_LIMIT; attempt += 1) { try { diff --git a/packages/trpc/src/router/user/user.ts b/packages/trpc/src/router/user/user.ts index 233e04b15e2..ecf6468cb7a 100644 --- a/packages/trpc/src/router/user/user.ts +++ b/packages/trpc/src/router/user/user.ts @@ -11,7 +11,7 @@ export const userRouter = { me: protectedProcedure.query(({ ctx }) => ctx.session.user), myOrganization: protectedProcedure.query(async ({ ctx }) => { - const activeOrganizationId = ctx.session.session.activeOrganizationId; + const activeOrganizationId = ctx.activeOrganizationId; const membership = await db.query.members.findFirst({ where: activeOrganizationId diff --git a/packages/trpc/src/router/utils/active-org.ts b/packages/trpc/src/router/utils/active-org.ts index cf59678991a..80749dac7a5 100644 --- a/packages/trpc/src/router/utils/active-org.ts +++ b/packages/trpc/src/router/utils/active-org.ts @@ -4,11 +4,16 @@ import { verifyOrgMembership } from "../integration/utils"; type Session = NonNullable; +type ProtectedContext = { + session: Session; + activeOrganizationId: string | null; +}; + export function requireActiveOrgId( - session: Session, + ctx: ProtectedContext, message = "No active organization selected", ) { - const organizationId = session.session.activeOrganizationId; + const organizationId = ctx.activeOrganizationId; if (!organizationId) { throw new TRPCError({ @@ -21,10 +26,10 @@ export function requireActiveOrgId( } export async function requireActiveOrgMembership( - session: Session, + ctx: ProtectedContext, message?: string, ) { - const organizationId = requireActiveOrgId(session, message); - await verifyOrgMembership(session.user.id, organizationId); + const organizationId = requireActiveOrgId(ctx, message); + await verifyOrgMembership(ctx.session.user.id, organizationId); return organizationId; } diff --git a/packages/trpc/src/router/v2-project/v2-project.ts b/packages/trpc/src/router/v2-project/v2-project.ts index 1359d06981a..33cad1db445 100644 --- a/packages/trpc/src/router/v2-project/v2-project.ts +++ b/packages/trpc/src/router/v2-project/v2-project.ts @@ -157,10 +157,7 @@ export const v2ProjectRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = requireActiveOrgId( - ctx.session, - "No active organization", - ); + const organizationId = requireActiveOrgId(ctx, "No active organization"); const project = await getProjectAccess(ctx.session.user.id, input.id, { organizationId, }); @@ -205,7 +202,7 @@ export const v2ProjectRouter = { .input(z.object({ id: z.string().uuid() })) .mutation(async ({ ctx, input }) => { const organizationId = await requireActiveOrgMembership( - ctx.session, + ctx, "No active organization", ); const project = await getScopedProject(organizationId, input.id); diff --git a/packages/trpc/src/router/v2-workspace/v2-workspace.ts b/packages/trpc/src/router/v2-workspace/v2-workspace.ts index 6e52441bfe7..7fc643e024e 100644 --- a/packages/trpc/src/router/v2-workspace/v2-workspace.ts +++ b/packages/trpc/src/router/v2-workspace/v2-workspace.ts @@ -142,10 +142,7 @@ export const v2WorkspaceRouter = { }), ) .mutation(async ({ ctx, input }) => { - const organizationId = requireActiveOrgId( - ctx.session, - "No active organization", - ); + const organizationId = requireActiveOrgId(ctx, "No active organization"); const workspace = await getWorkspaceAccess( ctx.session.user.id, input.id, diff --git a/packages/trpc/src/trpc.ts b/packages/trpc/src/trpc.ts index ab46a48b024..f58c5a4c1cc 100644 --- a/packages/trpc/src/trpc.ts +++ b/packages/trpc/src/trpc.ts @@ -1,6 +1,9 @@ import type { auth, Session } from "@superset/auth/server"; -import { COMPANY } from "@superset/shared/constants"; +import { db } from "@superset/db/client"; +import { members } from "@superset/db/schema"; +import { COMPANY, ORGANIZATION_HEADER } from "@superset/shared/constants"; import { initTRPC, TRPCError } from "@trpc/server"; +import { and, eq } from "drizzle-orm"; import superjson from "superjson"; import { ZodError } from "zod"; @@ -32,16 +35,40 @@ export const createCallerFactory = t.createCallerFactory; export const publicProcedure = t.procedure; -export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => { - if (!ctx.session) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Not authenticated. Please sign in.", - }); - } +export const protectedProcedure = t.procedure + .use(async ({ ctx, next }) => { + if (!ctx.session) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Not authenticated. Please sign in.", + }); + } - return next({ ctx: { session: ctx.session } }); -}); + return next({ ctx: { ...ctx, session: ctx.session } }); + }) + .use(async ({ ctx, next }) => { + const sessionOrgId = ctx.session.session.activeOrganizationId ?? null; + const headerOrgId = ctx.headers.get(ORGANIZATION_HEADER)?.trim() || null; + + let activeOrganizationId = sessionOrgId; + if (headerOrgId && headerOrgId !== sessionOrgId) { + const membership = await db.query.members.findFirst({ + where: and( + eq(members.userId, ctx.session.user.id), + eq(members.organizationId, headerOrgId), + ), + }); + if (!membership) { + throw new TRPCError({ + code: "FORBIDDEN", + message: `Not a member of organization ${headerOrgId}`, + }); + } + activeOrganizationId = headerOrgId; + } + + return next({ ctx: { ...ctx, activeOrganizationId } }); + }); export const jwtProcedure = t.procedure.use(async ({ ctx, next }) => { const authHeader = ctx.headers.get("authorization"); diff --git a/packages/workspace-client/src/providers/WorkspaceClientProvider/WorkspaceClientProvider.tsx b/packages/workspace-client/src/providers/WorkspaceClientProvider/WorkspaceClientProvider.tsx index b0e6c5ed217..1ad9dfb12c4 100644 --- a/packages/workspace-client/src/providers/WorkspaceClientProvider/WorkspaceClientProvider.tsx +++ b/packages/workspace-client/src/providers/WorkspaceClientProvider/WorkspaceClientProvider.tsx @@ -126,7 +126,7 @@ export function useWorkspaceWsUrl( params?: Record, ): string { const { hostUrl, getWsToken } = useWorkspaceClient(); - const url = new URL(path, hostUrl); + const url = new URL(`${hostUrl}${path}`); url.protocol = url.protocol === "https:" ? "wss:" : "ws:"; if (params) { for (const [key, value] of Object.entries(params)) { diff --git a/plans/20260421-pr-detection-matcher-fix.md b/plans/20260421-pr-detection-matcher-fix.md new file mode 100644 index 00000000000..ee6b582a10a --- /dev/null +++ b/plans/20260421-pr-detection-matcher-fix.md @@ -0,0 +1,52 @@ +# Fix PR โ†’ workspace matcher (cross-fork collision) + +Shipped in PR #3625. + +## The bug + +Two workspace โ†’ PR match sites keyed on branch name alone. Any cross-fork PR whose `headRefName` collided with a local branch got attached โ€” e.g. PR #3261 (`quueli/superset-windows:main` โ†’ `superset-sh/superset:main`) showing on every local `main` workspace. + +## Where the symptom came from + +- **v1 (`pr-resolution.ts`, visible to the user)** โ€” powers `usePRStatus` via `workspaces.getGitHubStatus`. `prMatchesLocalBranch` accepted any PR whose `headRefName` equaled the local branch name. Cross-fork not considered. **This is what attached PR #3261 in the user's sidebar.** +- **v2 / host-service (`pull-requests.ts`, latent)** โ€” powers `pullRequests.getByWorkspaces` (`_dashboard` sidebar) + `git.getPullRequest` (v2 review tab). Same branch-name-only matcher. Wasn't firing in the reported environment because the host-service `workspaces` table was empty / pointing at deleted worktree paths, but the bug existed in code. + +## What we shipped + +### v1 (`apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts`) + +- `prMatchesLocalBranch`: when the local branch has no fork-owner prefix, reject any PR with `isCrossRepository === true`. One line, uses the already-fetched and already-typed field that the predicate just never consulted. +- Module header marks it **v1-only, dies with v1 UI sunset** โ€” don't evolve, v2 already resolves PRs via host-service. + +### v2 / host-service (`packages/host-service/src/runtime/pull-requests/`) + +- **GraphQL query extended** with `isCrossRepository`, `headRepositoryOwner { login }`, `headRepository { name }`. +- **Schema migration `0003_workspace_upstream_ref`** (local SQLite, not Neon): adds `upstream_owner`, `upstream_repo`, `upstream_branch` columns to `workspaces`; replaces `workspaces_branch_idx` with composite `workspaces_upstream_ref_idx`. +- **`resolveWorkspaceUpstream`** populates those columns during `syncWorkspaceBranches`. Resolution modeled on `gh` CLI: + - `@{push}` happy path โ€” single `git rev-parse --abbrev-ref @{push}` returns `remote/branch` respecting all config precedence. + - Fallback walks `branch..pushRemote` โ†’ `remote.pushDefault` โ†’ `branch..remote`, handling URL-valued configs in addition to remote names. + - Fallback requires explicit `branch..merge` โ€” without it, a repo-wide `remote.pushDefault` would re-open the collision hole on untracked branches (coderabbit-flagged). + - `upstream_branch` is stored separately from local `branch` so `gh pr checkout` renames (`main` โ†’ `quueli-main`) still match the PR's `headRefName`. +- **Matcher** keys on `(upstreamOwner, upstreamRepo, upstreamBranch)` tuples, lowercased for owner/repo (GitHub is case-insensitive there) and preserving branch casing. + +## What we didn't do + +- **Consolidate v1 and v2 into one path** โ€” deferred. v1 dies with the v1 UI sunset (see `project_v1_sunset` memory). No port needed. +- **`headRefOid` SHA-fallback in v2** โ€” v1 has it (matches by HEAD commit when no tracking remote is set), v2 doesn't yet. Can be ported when v1 is actually deleted. + +## Review feedback addressed + +- **cubic-dev-ai** โ€” case-sensitive owner/repo key. Fixed by lowercasing in `upstreamKey`. +- **coderabbitai** โ€” untracked branch could resolve via `remote.pushDefault` alone and latch onto same-named PR. Fixed by requiring `branch..merge` in fallback. + +## Verification + +- PR #3261 (cross-fork): workspace upstream `superset-sh/superset#main` vs PR key `quueli/superset-windows#main` โ€” no match in v2. v1 predicate returns false via `isCrossRepository` check. โœ“ +- PR #3625 (this PR, same-repo): local branch `pr-3261-detection-in-v1-sidebar` tracking `origin/pr-3261-detection-in-v1-sidebar`. Tuples match in v2. v1 predicate returns true. โœ“ +- Fresh untracked branch: upstream null, no match. โœ“ +- `gh pr checkout` cross-fork review (local `quueli-main` tracking fork's `main`): `upstream_branch = main`, matches PR's `headRefName = main`. โœ“ + +## Commit trail + +- `aff1763bc` โ€” main fix (both paths + schema + migration) after clean squash +- `6811f7449` โ€” coderabbit-flagged fallback gate