From ce4531461c515922eb901d37f1a269233faac24d Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 15:24:19 +0530 Subject: [PATCH 01/16] chore: update zero-cache image and dependencies to version 1.4.0 --- docker/docker-compose.deps-only.yml | 2 +- docker/docker-compose.dev.yml | 2 +- docker/docker-compose.yml | 2 +- surfsense_web/package.json | 2 +- surfsense_web/pnpm-lock.yaml | 1441 +++++++++++++++++---------- 5 files changed, 916 insertions(+), 533 deletions(-) diff --git a/docker/docker-compose.deps-only.yml b/docker/docker-compose.deps-only.yml index ee09a4d5b..31dcd8b26 100644 --- a/docker/docker-compose.deps-only.yml +++ b/docker/docker-compose.deps-only.yml @@ -83,7 +83,7 @@ services: retries: 5 zero-cache: - image: rocicorp/zero:0.26.2 + image: rocicorp/zero:1.4.0 ports: - "${ZERO_CACHE_PORT:-4848}:4848" extra_hosts: diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index bbe758d4f..528061882 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -174,7 +174,7 @@ services: # - celery_worker zero-cache: - image: rocicorp/zero:0.26.2 + image: rocicorp/zero:1.4.0 ports: - "${ZERO_CACHE_PORT:-4848}:4848" extra_hosts: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 10cace249..18147a189 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -163,7 +163,7 @@ services: # restart: unless-stopped zero-cache: - image: rocicorp/zero:0.26.2 + image: rocicorp/zero:1.4.0 ports: - "${ZERO_CACHE_PORT:-5929}:4848" extra_hosts: diff --git a/surfsense_web/package.json b/surfsense_web/package.json index fa8d50cdc..efeb45fd8 100644 --- a/surfsense_web/package.json +++ b/surfsense_web/package.json @@ -79,7 +79,7 @@ "@remotion/media": "^4.0.438", "@remotion/player": "^4.0.438", "@remotion/web-renderer": "^4.0.438", - "@rocicorp/zero": "^0.26.2", + "@rocicorp/zero": "^1.4.0", "@slate-serializers/html": "^2.2.3", "@streamdown/code": "^1.0.2", "@streamdown/math": "^1.0.2", diff --git a/surfsense_web/pnpm-lock.yaml b/surfsense_web/pnpm-lock.yaml index af2850dfa..62056a215 100644 --- a/surfsense_web/pnpm-lock.yaml +++ b/surfsense_web/pnpm-lock.yaml @@ -165,8 +165,8 @@ importers: specifier: ^4.0.438 version: 4.0.438(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@rocicorp/zero': - specifier: ^0.26.2 - version: 0.26.2(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0)) + specifier: ^1.4.0 + version: 1.4.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0)) '@slate-serializers/html': specifier: ^2.2.3 version: 2.2.3 @@ -1186,8 +1186,8 @@ packages: '@date-fns/tz@1.4.1': resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} - '@dotenvx/dotenvx@1.57.2': - resolution: {integrity: sha512-lv9+UZPnl/KOvShepevLWm3+/wc1It5kgO5Q580evnvOFMZcgKVEYFwxlL7Ohl9my1yjTsWo28N3PJYUEO8wFQ==} + '@dotenvx/dotenvx@1.65.0': + resolution: {integrity: sha512-v4FA/Lw3pTEloLxBqTOaYDX6MNo0Jo7lGBsPZhwnJBqRJp0AzQg1ZZNxrFsh6HVC6QWeWrfIKLn0y2eyIXaVDg==} hasBin: true '@drdgvhbh/postgres-error-codes@0.0.6': @@ -1196,9 +1196,9 @@ packages: '@drizzle-team/brocli@0.10.2': resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} - '@ecies/ciphers@0.2.5': - resolution: {integrity: sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==} - engines: {bun: '>=1', deno: '>=2', node: '>=16'} + '@ecies/ciphers@0.2.6': + resolution: {integrity: sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g==} + engines: {bun: '>=1', deno: '>=2.7.10', node: '>=16'} peerDependencies: '@noble/ciphers': ^1.0.0 @@ -1780,8 +1780,8 @@ packages: resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} engines: {node: '>=12.10.0'} - '@grpc/proto-loader@0.8.0': - resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + '@grpc/proto-loader@0.8.1': + resolution: {integrity: sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==} engines: {node: '>=6'} hasBin: true @@ -2172,6 +2172,10 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + '@opentelemetry/auto-instrumentations-node@0.62.2': resolution: {integrity: sha512-Ipe6X7ddrCiRsuewyTU83IvKiSFT4piqmv9z8Ovg1E7v98pdTj1pUE6sDrHV50zl7/ypd+cONBgt+EYSZu4u9Q==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2185,8 +2189,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/context-async-hooks@2.6.0': - resolution: {integrity: sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q==} + '@opentelemetry/context-async-hooks@2.7.1': + resolution: {integrity: sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' @@ -2209,6 +2213,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.7.1': + resolution: {integrity: sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/exporter-logs-otlp-grpc@0.203.0': resolution: {integrity: sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2569,8 +2579,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/redis-common@0.38.2': - resolution: {integrity: sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==} + '@opentelemetry/redis-common@0.38.3': + resolution: {integrity: sha512-VCghU1JYs/4gP6Gqf/xro9MEsZ7LrMv2uONVsaESKL38ZOB9BqnI98FfS23wjMnHlpuE+TTaWSoAVNpTwYXzjw==} engines: {node: ^18.19.0 || >=20.6.0} '@opentelemetry/resource-detector-alibaba-cloud@0.31.11': @@ -2579,8 +2589,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 - '@opentelemetry/resource-detector-aws@2.13.0': - resolution: {integrity: sha512-ZPCn7gZhGqUYUoD+RCHIlayoHBMaJaEjfqlgz2EPKoXJ4y7Ru7CUm+Tm3yJVMKF92cN9xUQR0j5KALyF0fg9aw==} + '@opentelemetry/resource-detector-aws@2.17.0': + resolution: {integrity: sha512-IpeUtIdKW5PQsO2Ylfvxqr5ZawoObKigzQtEbT96NxSs7gej8Fp4LQZuooGAGu5H+qAI8/wjCZWLlJk2FT1Uzg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.0.0 @@ -2621,6 +2631,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/resources@2.7.1': + resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-logs@0.203.0': resolution: {integrity: sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2645,6 +2661,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.9.0 <1.10.0' + '@opentelemetry/sdk-metrics@2.7.1': + resolution: {integrity: sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <1.10.0' + '@opentelemetry/sdk-node@0.203.0': resolution: {integrity: sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2663,8 +2685,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-trace-base@2.6.0': - resolution: {integrity: sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ==} + '@opentelemetry/sdk-trace-base@2.7.1': + resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' @@ -2675,8 +2697,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/sdk-trace-node@2.6.0': - resolution: {integrity: sha512-YhswtasmsbIGEFvLGvR9p/y3PVRTfFf+mgY8van4Ygpnv4sA3vooAjvh+qAn9PNWxs4/IwGGqiQS0PPsaRJ0vQ==} + '@opentelemetry/sdk-trace-node@2.7.1': + resolution: {integrity: sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' @@ -2685,6 +2707,10 @@ packages: resolution: {integrity: sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==} engines: {node: '>=14'} + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + '@opentelemetry/sql-common@0.41.2': resolution: {integrity: sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2695,6 +2721,120 @@ packages: resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==} engines: {node: '>= 20.0.0'} + '@oxfmt/binding-android-arm-eabi@0.45.0': + resolution: {integrity: sha512-A/UMxFob1fefCuMeGxQBulGfFE38g2Gm23ynr3u6b+b7fY7/ajGbNsa3ikMIkGMLJW/TRoQaMoP1kME7S+815w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.45.0': + resolution: {integrity: sha512-L63z4uZmHjgvvqvMJD7mwff8aSBkM0+X4uFr6l6U5t6+Qc9DCLVZWIunJ7Gm4fn4zHPdSq6FFQnhu9yqqobxIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.45.0': + resolution: {integrity: sha512-UV34dd623FzqT+outIGndsCA/RBB+qgB3XVQhgmmJ9PJwa37NzPC9qzgKeOhPKxVk2HW+JKldQrVL54zs4Noww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.45.0': + resolution: {integrity: sha512-pMNJv0CMa1pDefVPeNbuQxibh8ITpWDFEhMC/IBB9Zlu76EbgzYwrzI4Cb11mqX2+rIYN70UTrh3z06TM59ptQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.45.0': + resolution: {integrity: sha512-xTcRoxbbo61sW2+ZRPeH+vp/o9G8gkdhiVumFU+TpneiPm14c79l6GFlxPXlCE9bNWikigbsrvJw46zCVAQFfg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.45.0': + resolution: {integrity: sha512-hWL8Hdni+3U1mPFx1UtWeGp3tNb6EhBAUHRMbKUxVkOp3WwoJbpVO2bfUVbS4PfpledviXXNHSTl1veTa6FhkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.45.0': + resolution: {integrity: sha512-6Blt/0OBT7vvfQpqYuYbpbFLPqSiaYpEJzUUWhinPEuADypDbtV1+LdjM0vYBNGPvnj85ex7lTerEX6JGcPt9w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.45.0': + resolution: {integrity: sha512-jLjoLfe+hGfjhA8hNBSdw85yCA8ePKq7ME4T+g6P9caQXvmt6IhE2X7iVjnVdkmYUWEzZrxlh4p6RkDmAMJY/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-arm64-musl@0.45.0': + resolution: {integrity: sha512-XQKXZIKYJC3GQJ8FnD3iMntpw69Wd9kDDK/Xt79p6xnFYlGGxSNv2vIBvRTDg5CKByWFWWZLCRDOXoP/m6YN4g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@oxfmt/binding-linux-ppc64-gnu@0.45.0': + resolution: {integrity: sha512-+g5RiG+xOkdrCWkKodv407nTvMq4vYM18Uox2MhZBm/YoqFxxJpWKsloskFFG5NU13HGPw1wzYjjOVcyd9moCA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-gnu@0.45.0': + resolution: {integrity: sha512-V7dXKoSyEbWAkkSF4JJNtF+NJZDmJoSarSoP30WCsB3X636Rehd3CvxBj49FIJxEBFWhvcUjGSHVeU8Erck1bQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-riscv64-musl@0.45.0': + resolution: {integrity: sha512-Vdelft1sAEYojVGgcODEFXSWYQYlIvoyIGWebKCuUibd1tvS1TjTx413xG2ZLuHpYj45CkN/ztMLMX6jrgqpgg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + + '@oxfmt/binding-linux-s390x-gnu@0.45.0': + resolution: {integrity: sha512-RR7xKgNpqwENnK0aYCGYg0JycY2n93J0reNjHyes+I9Gq52dH95x+CBlnlAQHCPfz6FGnKA9HirgUl14WO6o7w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@oxfmt/binding-linux-x64-gnu@0.45.0': + resolution: {integrity: sha512-U/QQ0+BQNSHxjuXR/utvXnQ50Vu5kUuqEomZvQ1/3mhgbBiMc2WU9q5kZ5WwLp3gnFIx9ibkveoRSe2EZubkqg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-linux-x64-musl@0.45.0': + resolution: {integrity: sha512-o5TLOUCF0RWQjsIS06yVC+kFgp092/yLe6qBGSUvtnmTVw9gxjpdQSXc3VN5Cnive4K11HNstEZF8ROKHfDFSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@oxfmt/binding-openharmony-arm64@0.45.0': + resolution: {integrity: sha512-RnGcV3HgPuOjsGx/k9oyRNKmOp+NBLGzZTdPDYbc19r7NGeYPplnUU/BfU35bX2Y/O4ejvHxcfkvW2WoYL/gsg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.45.0': + resolution: {integrity: sha512-v3Vj7iKKsUFwt9w5hsqIIoErKVoENC6LoqfDlteOQ5QMDCXihlqLoxpmviUhXnNncg4zV6U9BPwlBbwa+qm4wg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.45.0': + resolution: {integrity: sha512-N8yotPBX6ph0H3toF4AEpdCeVPrdcSetj+8eGiZGsrLsng3bs/Q5HPu4bbSxip5GBPx5hGbGHrZwH4+rcrjhHA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.45.0': + resolution: {integrity: sha512-w5MMTRCK1dpQeRA+HHqXQXyN33DlG/N2LOYxJmaT4fJjcmZrbNnqw7SmIk7I2/a2493PPLZ+2E/Ar6t2iKVMug==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@parcel/watcher-android-arm64@2.5.6': resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} engines: {node: '>= 10.0.0'} @@ -2950,6 +3090,9 @@ packages: '@protobufjs/codegen@2.0.4': resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + '@protobufjs/eventemitter@1.1.0': resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} @@ -2962,6 +3105,9 @@ packages: '@protobufjs/inquire@1.1.0': resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + '@protobufjs/path@1.1.2': resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} @@ -2971,6 +3117,9 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -4018,23 +4167,26 @@ packages: resolution: {integrity: sha512-TfjMTQp9cNNqNtHFfa+XHEGdA7NnmDRu+ZJH4YF3dso0Xk/b9DMhg/sl+b6CR4ThFZArXXDsG1j8Mwl34wcOZQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - '@rocicorp/zero-sqlite3@1.0.15': - resolution: {integrity: sha512-o4ezzTgNQvOM23X/mBRN4LAo0i7XkIDAL3Obg7FaJLFTuwJyYwqE45aqk9vg8/0mlBw2U+DEUGLP1q/Pf+VgYQ==} - engines: {bun: '>=1.1.0', node: 20.x || 22.x || 23.x || 24.x} + '@rocicorp/zero-sqlite3@1.0.18': + resolution: {integrity: sha512-JwHcCijxKj94NDij5UDCJsGHo/D8z4j5De/5zphQ+NctQ4TWr9Zx7L+Q1JBfie4ewVS82Ingu+QKbIwWvdNFXg==} + engines: {bun: '>=1.1.0', node: 20.x || 22.x || 23.x || 24.x || 25.x} hasBin: true - '@rocicorp/zero@0.26.2': - resolution: {integrity: sha512-fq67gwxvV3rWx/QeKTXu6ab2CLqR7O9GrcZPbI5bCBxHgRB2S+VSxEvcbEtYDjyZvI3GWmisa5UdsYN3H2vYsA==} + '@rocicorp/zero@1.4.0': + resolution: {integrity: sha512-BRgdF64JWNgIsHG4Fajgjr5ms0HBTdmZUWoJy09KE3TNwMo0Rmz1r1fte1MMH1zY4witcUJsFhGj4aHLsZAfTA==} engines: {node: '>=22'} hasBin: true peerDependencies: '@op-engineering/op-sqlite': '>=15' expo-sqlite: '>=15' + kysely: ^0.28.16 peerDependenciesMeta: '@op-engineering/op-sqlite': optional: true expo-sqlite: optional: true + kysely: + optional: true '@rollup/rollup-android-arm-eabi@4.59.0': resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} @@ -4875,8 +5027,8 @@ packages: ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -5202,8 +5354,8 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - compare-utf8@0.1.1: - resolution: {integrity: sha512-bND8Irz+KrF96w4Tkm1m8u5q8iE2fnvP196sHGy7XNrGNXlhyl07VnsCRYrXgEhhf/lM7hyCKRnMeh8Icis4Sw==} + compare-utf8@0.2.0: + resolution: {integrity: sha512-5BjVs4Be9AwMm4le3Qb3crp44OAn+uuJhvrjPWA8Es/DfVPq5lSc8JaRg/clrrHOMCU+CdDfv/9eBSPh6OOiUQ==} compute-scroll-into-view@3.1.1: resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} @@ -5348,8 +5500,8 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} @@ -5792,8 +5944,8 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-json-stringify@6.3.0: - resolution: {integrity: sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA==} + fast-json-stringify@6.4.0: + resolution: {integrity: sha512-ibRCQ0GZKJIQ+P3Et1h0LhPgp3PMTYk0MH8O+kW3lNYsvmaQww5Nn3f1jf73Q0jR1Yz3a1CDP4/NZD3vOajWJQ==} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} @@ -5801,14 +5953,14 @@ packages: fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fastify-plugin@5.1.0: resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} - fastify@5.8.4: - resolution: {integrity: sha512-sa42J1xylbBAYUWALSBoyXKPDUvM3OoNOibIefA+Oha57FryXKKCZarA1iDntOCWp3O35voZLuDg2mdODXtPzQ==} + fastify@5.8.5: + resolution: {integrity: sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -5843,8 +5995,8 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - find-my-way@9.5.0: - resolution: {integrity: sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==} + find-my-way@9.6.0: + resolution: {integrity: sha512-Zf4Xve4RymLl7NgaavNebZ01joJ8MfVerOG43wy7SHLO+r+K0C6d/SE0BiR7AV5V1VOCFlOP7ecdo+I4qmiHrQ==} engines: {node: '>=20'} find-replace@5.0.2: @@ -6137,6 +6289,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hasown@2.0.3: + resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + engines: {node: '>= 0.4'} + hast-util-from-dom@5.0.1: resolution: {integrity: sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==} @@ -6288,8 +6444,8 @@ packages: intl-messageformat@11.1.2: resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==} - ipaddr.js@2.3.0: - resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} engines: {node: '>= 10'} is-alphabetical@1.0.4: @@ -6338,6 +6494,10 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} @@ -7037,6 +7197,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.1.11: + resolution: {integrity: sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==} + engines: {node: ^18 || >=20} + hasBin: true + nanoid@5.1.7: resolution: {integrity: sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==} engines: {node: ^18 || >=20} @@ -7100,8 +7265,8 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abi@3.89.0: - resolution: {integrity: sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==} + node-abi@3.92.0: + resolution: {integrity: sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==} engines: {node: '>=10'} node-addon-api@7.1.1: @@ -7212,6 +7377,11 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + oxfmt@0.45.0: + resolution: {integrity: sha512-0o/COoN9fY50bjVeM7PQsNgbhndKurBIeTIcspW033OumksjJJmIVDKjAk5HMwU/GHTxSOdGDdhJ6BRzGPmsHg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -7293,6 +7463,9 @@ packages: pg-protocol@1.11.0: resolution: {integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==} + pg-protocol@1.13.0: + resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==} + pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -7320,6 +7493,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pino-abstract-transport@3.0.0: resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} @@ -7416,11 +7593,6 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.8.1: - resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} - engines: {node: '>=14'} - hasBin: true - prismjs@1.27.0: resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} engines: {node: '>=6'} @@ -7455,6 +7627,10 @@ packages: resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} engines: {node: '>=12.0.0'} + protobufjs@7.5.7: + resolution: {integrity: sha512-NGnrxS/nLKUo5nkbVQxlC71sB4hdfImdYIbFeSCidxtwATx0AHRPcANSLd0q5Bb2BkoSWo2iisQhGg5/r+ihbA==} + engines: {node: '>=12.0.0'} + proxy-compare@2.6.0: resolution: {integrity: sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==} @@ -7673,6 +7849,9 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} + real-require@1.0.0: + resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==} + recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} @@ -7797,6 +7976,11 @@ packages: engines: {node: '>= 0.4'} hasBin: true + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + resolve@2.0.0-next.6: resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==} engines: {node: '>= 0.4'} @@ -7828,6 +8012,9 @@ packages: safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -7836,8 +8023,8 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} - safe-regex2@5.1.0: - resolution: {integrity: sha512-pNHAuBW7TrcleFHsxBr5QMi/Iyp0ENjUKz7GCcX1UO7cMh+NmVK6HxQckNL1tJp1XAJVjG6B8OKIPqodqj9rtw==} + safe-regex2@5.1.1: + resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} hasBin: true safe-stable-stringify@2.5.0: @@ -7865,6 +8052,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} + engines: {node: '>=10'} + hasBin: true + server-only@0.0.1: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} @@ -8042,6 +8234,9 @@ packages: string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -8115,6 +8310,9 @@ packages: tailwind-merge@3.5.0: resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + tailwind-scrollbar-hide@4.0.0: resolution: {integrity: sha512-gobtvVcThB2Dxhy0EeYSS1RKQJ5baDFkamkhwBvzvevwX6L4XQfpZ3me9s25Ss1ecFVT5jPYJ50n+7xTBJG9WQ==} peerDependencies: @@ -8142,8 +8340,8 @@ packages: text-segmentation@1.0.3: resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} - thread-stream@4.0.0: - resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} + thread-stream@4.1.0: + resolution: {integrity: sha512-Bw6h2iBDt16v6iHLChBIoVYU8CBo9GPsW8TG7h1hRVhqKhIkH6N8qkxNSmiOZTKsCLPbtWG4ViWLkU6KeKXpig==} engines: {node: '>=20'} throttleit@2.1.0: @@ -8167,6 +8365,10 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -8415,10 +8617,12 @@ packages: uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true vaul@1.1.2: @@ -8564,6 +8768,14 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yocto-spinner@1.2.0: + resolution: {integrity: sha512-Yw0hUB6UA3o4YUgKy3oSe9a4cxoaZ9sBfYDw+JSxo6Id0KoJGoxzPA24qqUXYKBWABs/zDSGTz9kww7t3F0XGw==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: @@ -9494,23 +9706,24 @@ snapshots: '@date-fns/tz@1.4.1': {} - '@dotenvx/dotenvx@1.57.2': + '@dotenvx/dotenvx@1.65.0': dependencies: commander: 11.1.0 dotenv: 17.3.1 eciesjs: 0.4.18 execa: 5.1.1 - fdir: 6.5.0(picomatch@4.0.3) + fdir: 6.5.0(picomatch@4.0.4) ignore: 5.3.2 object-treeify: 1.1.33 - picomatch: 4.0.3 + picomatch: 4.0.4 which: 4.0.0 + yocto-spinner: 1.2.0 '@drdgvhbh/postgres-error-codes@0.0.6': {} '@drizzle-team/brocli@0.10.2': {} - '@ecies/ciphers@0.2.5(@noble/ciphers@1.3.0)': + '@ecies/ciphers@0.2.6(@noble/ciphers@1.3.0)': dependencies: '@noble/ciphers': 1.3.0 @@ -9813,9 +10026,9 @@ snapshots: '@fastify/ajv-compiler@4.0.5': dependencies: - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.2 '@fastify/cors@10.1.0': dependencies: @@ -9826,7 +10039,7 @@ snapshots: '@fastify/fast-json-stringify-compiler@5.0.3': dependencies: - fast-json-stringify: 6.3.0 + fast-json-stringify: 6.4.0 '@fastify/forwarded@3.0.1': {} @@ -9837,7 +10050,7 @@ snapshots: '@fastify/proxy-addr@5.1.0': dependencies: '@fastify/forwarded': 3.0.1 - ipaddr.js: 2.3.0 + ipaddr.js: 2.4.0 '@fastify/websocket@11.2.0': dependencies: @@ -9910,14 +10123,14 @@ snapshots: '@grpc/grpc-js@1.14.3': dependencies: - '@grpc/proto-loader': 0.8.0 + '@grpc/proto-loader': 0.8.1 '@js-sdsl/ordered-map': 4.4.2 - '@grpc/proto-loader@0.8.0': + '@grpc/proto-loader@0.8.1': dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.5.5 + protobufjs: 7.5.7 yargs: 17.7.2 '@hookform/resolvers@5.2.2(react-hook-form@7.71.2(react@19.2.4))': @@ -10230,7 +10443,7 @@ snapshots: '@opentelemetry/api-logs@0.203.0': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs@0.208.0': dependencies: @@ -10238,74 +10451,76 @@ snapshots: '@opentelemetry/api@1.9.0': {} - '@opentelemetry/auto-instrumentations-node@0.62.2(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))': + '@opentelemetry/api@1.9.1': {} + + '@opentelemetry/auto-instrumentations-node@0.62.2(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0))': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-amqplib': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-aws-lambda': 0.54.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-aws-sdk': 0.58.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-bunyan': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-cassandra-driver': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-connect': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-cucumber': 0.19.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dataloader': 0.21.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dns': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-express': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fastify': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fs': 0.23.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-generic-pool': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-graphql': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-hapi': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-ioredis': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-kafkajs': 0.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-knex': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-koa': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-lru-memoizer': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-memcached': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongodb': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongoose': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql2': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-nestjs-core': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-net': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-oracledb': 0.29.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pg': 0.56.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pino': 0.50.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-redis': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-restify': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-router': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-runtime-node': 0.17.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-socket.io': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-tedious': 0.22.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-undici': 0.14.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-winston': 0.48.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-alibaba-cloud': 0.31.11(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-aws': 2.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-azure': 0.10.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-container': 0.7.11(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-gcp': 0.37.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-amqplib': 0.50.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-aws-lambda': 0.54.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-aws-sdk': 0.58.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-bunyan': 0.49.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-cassandra-driver': 0.49.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-connect': 0.47.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-cucumber': 0.19.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-dataloader': 0.21.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-dns': 0.47.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-express': 0.52.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-fastify': 0.48.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-fs': 0.23.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-generic-pool': 0.47.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-graphql': 0.51.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-grpc': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-hapi': 0.50.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-ioredis': 0.51.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-kafkajs': 0.13.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-knex': 0.48.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-koa': 0.51.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-lru-memoizer': 0.48.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-memcached': 0.47.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongodb': 0.56.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongoose': 0.50.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql': 0.49.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql2': 0.50.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-nestjs-core': 0.49.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-net': 0.47.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-oracledb': 0.29.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pg': 0.56.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pino': 0.50.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-redis': 0.52.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-restify': 0.49.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-router': 0.48.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-runtime-node': 0.17.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-socket.io': 0.50.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-tedious': 0.22.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-undici': 0.14.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-winston': 0.48.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-alibaba-cloud': 0.31.11(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-aws': 2.17.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-azure': 0.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-container': 0.7.11(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-gcp': 0.37.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - encoding - supports-color - '@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 - '@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/context-async-hooks@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 - '@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10317,24 +10532,34 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/exporter-logs-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/exporter-logs-otlp-grpc@0.203.0(@opentelemetry/api@1.9.1)': dependencies: '@grpc/grpc-js': 1.14.3 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-logs-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-logs-otlp-http@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.1) '@opentelemetry/exporter-logs-otlp-http@0.208.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10345,446 +10570,446 @@ snapshots: '@opentelemetry/otlp-transformer': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-logs-otlp-proto@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-metrics-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-grpc@0.203.0(@opentelemetry/api@1.9.1)': dependencies: '@grpc/grpc-js': 1.14.3 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-metrics-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-http@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-metrics-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-proto@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-prometheus@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-prometheus@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-trace-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-grpc@0.203.0(@opentelemetry/api@1.9.1)': dependencies: '@grpc/grpc-js': 1.14.3 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-trace-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-http@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-trace-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-proto@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-zipkin@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-zipkin@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 - '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-aws-lambda@0.54.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-aws-lambda@0.54.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/aws-lambda': 8.10.152 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-aws-sdk@0.58.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-aws-sdk@0.58.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-bunyan@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-bunyan@0.49.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) '@types/bunyan': 1.8.11 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-cassandra-driver@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-cassandra-driver@0.49.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-cucumber@0.19.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-cucumber@0.19.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-dataloader@0.21.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-dataloader@0.21.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-dns@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-dns@0.47.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-fastify@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-fastify@0.48.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-generic-pool@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-generic-pool@0.47.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-graphql@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-graphql@0.51.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-grpc@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-http@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-ioredis@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-ioredis@0.51.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.2 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.38.3 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-kafkajs@0.13.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-kafkajs@0.13.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-knex@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-knex@0.48.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-lru-memoizer@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-lru-memoizer@0.48.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-memcached@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-memcached@0.47.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/memcached': 2.2.10 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongodb@0.56.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mongodb@0.56.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql2@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mysql2@0.50.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-mysql@0.49.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/mysql': 2.15.27 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-nestjs-core@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-nestjs-core@0.49.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-net@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-net@0.47.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-oracledb@0.29.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-oracledb@0.29.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/oracledb': 6.5.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pg@0.56.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-pg@0.56.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1) '@types/pg': 8.15.5 '@types/pg-pool': 2.0.6 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pino@0.50.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-pino@0.50.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-redis@0.52.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-redis@0.52.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.2 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.38.3 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-restify@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-restify@0.49.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-router@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-router@0.48.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-runtime-node@0.17.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-runtime-node@0.17.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-socket.io@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-socket.io@0.50.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-tedious@0.22.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-tedious@0.22.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@types/tedious': 4.0.14 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-winston@0.48.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-winston@0.48.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 import-in-the-middle: 1.15.0 require-in-the-middle: 7.5.2 transitivePeerDependencies: - supports-color - '@opentelemetry/otlp-exporter-base@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-exporter-base@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) '@opentelemetry/otlp-exporter-base@0.208.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10792,24 +11017,24 @@ snapshots: '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-transformer': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-grpc-exporter-base@0.203.0(@opentelemetry/api@1.9.1)': dependencies: '@grpc/grpc-js': 1.14.3 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-transformer@0.203.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - protobufjs: 7.5.5 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) + protobufjs: 7.5.7 '@opentelemetry/otlp-transformer@0.208.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10822,60 +11047,60 @@ snapshots: '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) protobufjs: 7.5.5 - '@opentelemetry/propagator-b3@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/propagator-b3@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/propagator-jaeger@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/propagator-jaeger@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/redis-common@0.38.2': {} + '@opentelemetry/redis-common@0.38.3': {} - '@opentelemetry/resource-detector-alibaba-cloud@0.31.11(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-alibaba-cloud@0.31.11(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resource-detector-aws@2.13.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-aws@2.17.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 - '@opentelemetry/resource-detector-azure@0.10.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-azure@0.10.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 - '@opentelemetry/resource-detector-container@0.7.11(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-container@0.7.11(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resource-detector-gcp@0.37.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-gcp@0.37.0(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 gcp-metadata: 6.1.1 transitivePeerDependencies: - encoding - supports-color - '@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10889,12 +11114,18 @@ snapshots: '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-logs@0.208.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10903,11 +11134,11 @@ snapshots: '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-metrics@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10915,40 +11146,46 @@ snapshots: '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-metrics@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/sdk-node@0.203.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-prometheus': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-zipkin': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-b3': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-logs-otlp-proto': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-metrics-otlp-proto': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-prometheus': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-proto': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-zipkin': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-b3': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-jaeger': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10957,36 +11194,95 @@ snapshots: '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 - '@opentelemetry/sdk-trace-node@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-node@2.0.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-node@2.6.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-node@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/context-async-hooks': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions@1.39.0': {} - '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': + '@opentelemetry/semantic-conventions@1.40.0': {} + + '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) '@orama/orama@3.1.18': {} + '@oxfmt/binding-android-arm-eabi@0.45.0': + optional: true + + '@oxfmt/binding-android-arm64@0.45.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.45.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.45.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.45.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.45.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.45.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.45.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.45.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.45.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.45.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.45.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.45.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.45.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.45.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.45.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.45.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.45.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.45.0': + optional: true + '@parcel/watcher-android-arm64@2.5.6': optional: true @@ -11279,6 +11575,8 @@ snapshots: '@protobufjs/codegen@2.0.4': {} + '@protobufjs/codegen@2.0.5': {} + '@protobufjs/eventemitter@1.1.0': {} '@protobufjs/fetch@1.1.0': @@ -11290,12 +11588,16 @@ snapshots: '@protobufjs/inquire@1.1.0': {} + '@protobufjs/inquire@1.1.1': {} + '@protobufjs/path@1.1.2': {} '@protobufjs/pool@1.1.0': {} '@protobufjs/utf8@1.1.0': {} + '@protobufjs/utf8@1.1.1': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.0.0': @@ -12405,59 +12707,58 @@ snapshots: '@rocicorp/resolver@1.0.2': {} - '@rocicorp/zero-sqlite3@1.0.15': + '@rocicorp/zero-sqlite3@1.0.18': dependencies: bindings: 1.5.0 prebuild-install: 7.1.3 - '@rocicorp/zero@0.26.2(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))': + '@rocicorp/zero@1.4.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0))': dependencies: '@badrap/valita': 0.3.11 '@databases/escape-identifier': 1.0.3 '@databases/sql': 3.3.0 - '@dotenvx/dotenvx': 1.57.2 + '@dotenvx/dotenvx': 1.65.0 '@drdgvhbh/postgres-error-codes': 0.0.6 '@fastify/cors': 10.1.0 '@fastify/websocket': 11.2.0 '@google-cloud/precise-date': 4.0.0 - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.9.1 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/auto-instrumentations-node': 0.62.2(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0)) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/auto-instrumentations-node': 0.62.2(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0)) + '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': 2.7.1(@opentelemetry/api@1.9.1) '@postgresql-typed/oids': 0.2.0 '@rocicorp/lock': 1.0.4 '@rocicorp/logger': 5.4.0 '@rocicorp/resolver': 1.0.2 - '@rocicorp/zero-sqlite3': 1.0.15 + '@rocicorp/zero-sqlite3': 1.0.18 '@standard-schema/spec': 1.1.0 '@types/basic-auth': 1.1.8 '@types/ws': 8.18.1 basic-auth: 2.0.1 - chalk: 5.6.2 chalk-template: 1.1.2 chokidar: 4.0.3 cloudevents: 10.0.0 command-line-args: 6.0.2 command-line-usage: 7.0.4 - compare-utf8: 0.1.1 - defu: 6.1.4 + compare-utf8: 0.2.0 + defu: 6.1.7 eventemitter3: 5.0.4 - fastify: 5.8.4 + fastify: 5.8.5 is-in-subnet: 4.0.1 jose: 5.10.0 js-xxhash: 4.0.0 json-custom-numbers: 3.1.1 kasi: 1.1.2 - nanoid: 5.1.7 + nanoid: 5.1.11 + oxfmt: 0.45.0 parse-prometheus-text-format: 1.1.1 pg-format: pg-format-fix@1.0.5 postgres: 3.4.7 - prettier: 3.8.1 - semver: 7.7.4 + semver: 7.8.0 tsx: 4.21.0 url-pattern: 1.0.3 urlpattern-polyfill: 10.1.0 @@ -13017,7 +13318,7 @@ snapshots: '@types/pg@8.15.5': dependencies: '@types/node': 20.19.33 - pg-protocol: 1.11.0 + pg-protocol: 1.13.0 pg-types: 2.2.0 '@types/pg@8.16.0': @@ -13263,13 +13564,13 @@ snapshots: optionalDependencies: react: 19.2.4 - ajv-formats@2.1.1(ajv@8.18.0): + ajv-formats@2.1.1(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 - ajv-formats@3.0.1(ajv@8.18.0): + ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 ajv@6.14.0: dependencies: @@ -13278,10 +13579,10 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.18.0: + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -13567,8 +13868,8 @@ snapshots: cloudevents@10.0.0: dependencies: - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) json-bigint: 1.0.0 process: 0.11.10 util: 0.12.5 @@ -13628,7 +13929,7 @@ snapshots: commander@8.3.0: {} - compare-utf8@0.1.1: {} + compare-utf8@0.2.0: {} compute-scroll-into-view@3.1.1: {} @@ -13769,7 +14070,7 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - defu@6.1.4: {} + defu@6.1.7: {} dequal@2.0.3: {} @@ -13869,7 +14170,7 @@ snapshots: eciesjs@0.4.18: dependencies: - '@ecies/ciphers': 0.2.5(@noble/ciphers@1.3.0) + '@ecies/ciphers': 0.2.6(@noble/ciphers@1.3.0) '@noble/ciphers': 1.3.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 @@ -13887,7 +14188,7 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) react-easy-sort: 1.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tailwind-merge: 3.5.0 + tailwind-merge: 3.6.0 transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -14393,12 +14694,12 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-json-stringify@6.3.0: + fast-json-stringify@6.4.0: dependencies: '@fastify/merge-json-schemas': 0.2.1 - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.2 json-schema-ref-resolver: 3.0.0 rfdc: 1.4.1 @@ -14408,11 +14709,11 @@ snapshots: dependencies: fast-decode-uri-component: 1.0.1 - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fastify-plugin@5.1.0: {} - fastify@5.8.4: + fastify@5.8.5: dependencies: '@fastify/ajv-compiler': 4.0.5 '@fastify/error': 4.2.0 @@ -14420,14 +14721,14 @@ snapshots: '@fastify/proxy-addr': 5.1.0 abstract-logging: 2.0.1 avvio: 9.2.0 - fast-json-stringify: 6.3.0 - find-my-way: 9.5.0 + fast-json-stringify: 6.4.0 + find-my-way: 9.6.0 light-my-request: 6.6.0 pino: 10.3.1 process-warning: 5.0.0 rfdc: 1.4.1 secure-json-parse: 4.1.0 - semver: 7.7.4 + semver: 7.8.0 toad-cache: 3.7.0 fastq@1.20.1: @@ -14442,6 +14743,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + fflate@0.4.8: {} file-entry-cache@8.0.0: @@ -14458,11 +14763,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 - find-my-way@9.5.0: + find-my-way@9.6.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 - safe-regex2: 5.1.0 + safe-regex2: 5.1.1 find-replace@5.0.2: {} @@ -14736,6 +15041,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.3: + dependencies: + function-bind: 1.1.2 + hast-util-from-dom@5.0.1: dependencies: '@types/hast': 3.0.4 @@ -14989,7 +15298,7 @@ snapshots: '@formatjs/icu-messageformat-parser': 3.5.1 tslib: 2.8.1 - ipaddr.js@2.3.0: {} + ipaddr.js@2.4.0: {} is-alphabetical@1.0.4: {} @@ -15045,6 +15354,10 @@ snapshots: dependencies: hasown: 2.0.2 + is-core-module@2.16.2: + dependencies: + hasown: 2.0.3 + is-data-view@1.0.2: dependencies: call-bound: 1.0.4 @@ -15924,6 +16237,8 @@ snapshots: nanoid@3.3.11: {} + nanoid@5.1.11: {} + nanoid@5.1.7: {} napi-build-utils@2.0.0: {} @@ -15989,9 +16304,9 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 - node-abi@3.89.0: + node-abi@3.92.0: dependencies: - semver: 7.7.4 + semver: 7.8.0 node-addon-api@7.1.1: {} @@ -16111,6 +16426,30 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxfmt@0.45.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.45.0 + '@oxfmt/binding-android-arm64': 0.45.0 + '@oxfmt/binding-darwin-arm64': 0.45.0 + '@oxfmt/binding-darwin-x64': 0.45.0 + '@oxfmt/binding-freebsd-x64': 0.45.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.45.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.45.0 + '@oxfmt/binding-linux-arm64-gnu': 0.45.0 + '@oxfmt/binding-linux-arm64-musl': 0.45.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.45.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.45.0 + '@oxfmt/binding-linux-riscv64-musl': 0.45.0 + '@oxfmt/binding-linux-s390x-gnu': 0.45.0 + '@oxfmt/binding-linux-x64-gnu': 0.45.0 + '@oxfmt/binding-linux-x64-musl': 0.45.0 + '@oxfmt/binding-openharmony-arm64': 0.45.0 + '@oxfmt/binding-win32-arm64-msvc': 0.45.0 + '@oxfmt/binding-win32-ia32-msvc': 0.45.0 + '@oxfmt/binding-win32-x64-msvc': 0.45.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -16193,6 +16532,8 @@ snapshots: pg-protocol@1.11.0: {} + pg-protocol@1.13.0: {} + pg-types@2.2.0: dependencies: pg-int8: 1.0.1 @@ -16221,6 +16562,8 @@ snapshots: picomatch@4.0.3: {} + picomatch@4.0.4: {} + pino-abstract-transport@3.0.0: dependencies: split2: 4.2.0 @@ -16239,7 +16582,7 @@ snapshots: real-require: 0.2.0 safe-stable-stringify: 2.5.0 sonic-boom: 4.2.1 - thread-stream: 4.0.0 + thread-stream: 4.1.0 platejs@52.0.17(@types/react@19.2.14)(immer@10.2.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(scheduler@0.27.0)(use-sync-external-store@1.6.0(react@19.2.4)): dependencies: @@ -16344,7 +16687,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.89.0 + node-abi: 3.92.0 pump: 3.0.4 rc: 1.2.8 simple-get: 4.0.1 @@ -16353,8 +16696,6 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.8.1: {} - prismjs@1.27.0: {} prismjs@1.30.0: {} @@ -16394,6 +16735,21 @@ snapshots: '@types/node': 20.19.33 long: 5.3.2 + protobufjs@7.5.7: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 20.19.33 + long: 5.3.2 + proxy-compare@2.6.0: {} pump@3.0.4: @@ -16661,7 +17017,7 @@ snapshots: readable-stream@3.6.2: dependencies: inherits: 2.0.4 - string_decoder: 1.1.1 + string_decoder: 1.3.0 util-deprecate: 1.0.2 readdirp@4.1.2: {} @@ -16670,6 +17026,8 @@ snapshots: real-require@0.2.0: {} + real-require@1.0.0: {} + recma-build-jsx@1.0.0: dependencies: '@types/estree': 1.0.8 @@ -16867,7 +17225,7 @@ snapshots: dependencies: debug: 4.4.3 module-details-from-path: 1.0.4 - resolve: 1.22.11 + resolve: 1.22.12 transitivePeerDependencies: - supports-color @@ -16881,6 +17239,13 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + resolve@2.0.0-next.6: dependencies: es-errors: 1.3.0 @@ -16941,6 +17306,8 @@ snapshots: safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -16952,7 +17319,7 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 - safe-regex2@5.1.0: + safe-regex2@5.1.1: dependencies: ret: 0.5.0 @@ -16972,6 +17339,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.0: {} + server-only@0.0.1: {} set-cookie-parser@2.7.2: {} @@ -17257,6 +17626,10 @@ snapshots: dependencies: safe-buffer: 5.1.2 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -17322,6 +17695,8 @@ snapshots: tailwind-merge@3.5.0: {} + tailwind-merge@3.6.0: {} + tailwind-scrollbar-hide@4.0.0(tailwindcss@4.2.1): dependencies: tailwindcss: 4.2.1 @@ -17353,9 +17728,9 @@ snapshots: dependencies: utrie: 1.0.2 - thread-stream@4.0.0: + thread-stream@4.1.0: dependencies: - real-require: 0.2.0 + real-require: 1.0.0 throttleit@2.1.0: {} @@ -17372,6 +17747,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinypool@2.1.0: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -17414,7 +17791,7 @@ snapshots: tunnel-agent@0.6.0: dependencies: - safe-buffer: 5.1.2 + safe-buffer: 5.2.1 type-check@0.4.0: dependencies: @@ -17781,6 +18158,12 @@ snapshots: yocto-queue@0.1.0: {} + yocto-spinner@1.2.0: + dependencies: + yoctocolors: 2.1.2 + + yoctocolors@2.1.2: {} + zod-to-json-schema@3.25.1(zod@4.3.6): dependencies: zod: 4.3.6 From d923d34e389bc61fdab7520cd41a9b9775e7fb26 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 16:43:50 +0530 Subject: [PATCH 02/16] feat(migration): add migration 143 to force zero-cache resync after Zero upgrade --- .../143_force_zero_publication_resync.py | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 surfsense_backend/alembic/versions/143_force_zero_publication_resync.py diff --git a/surfsense_backend/alembic/versions/143_force_zero_publication_resync.py b/surfsense_backend/alembic/versions/143_force_zero_publication_resync.py new file mode 100644 index 000000000..147cbde56 --- /dev/null +++ b/surfsense_backend/alembic/versions/143_force_zero_publication_resync.py @@ -0,0 +1,142 @@ +"""force zero-cache to resync after upgrading to Zero >= 1.0 + +Re-emits the current ``zero_publication`` shape using +``ALTER PUBLICATION ... SET TABLE`` wrapped in +``COMMENT ON PUBLICATION`` bookends. This is the publication-change +hook documented for Zero ``>=1.0``: + + https://zero.rocicorp.dev/docs/connecting-to-postgres#publication-changes + +Background +---------- +Migrations 117 / 139 / 140 mutated ``zero_publication`` using +``DROP PUBLICATION`` + ``CREATE PUBLICATION``. On Zero 0.26.2 that +sequence did not reliably wake the zero-cache change-streamer, so +affected installs ended up with a SQLite replica file (in the +``surfsense-zero-cache`` volume) that was snapshotted against the +pre-``user`` publication. The frontend Zero schema includes a +``userTable`` query, which then failed with +``SchemaVersionNotSupported`` and triggered the default +``onUpdateNeeded`` -> ``location.reload()`` every WebSocket keepalive +interval (~60s). See bug #1355. + +This migration emits the canonical publication shape one more time, +this time using a pattern that fires Postgres event triggers and +Zero's schema-change hook. With ``ZERO_AUTO_RESET=true`` (the default) +and Zero ``>=1.0``, zero-cache responds by wiping its replica and +doing a fresh initial sync from the corrected publication. + +The publication shape itself is unchanged versus migration 140 -- on +installs whose replica is already correct, this is a no-op aside +from the harmless event-trigger fire. + +Revision ID: 143 +Revises: 142 +""" + +from collections.abc import Sequence + +import sqlalchemy as sa + +from alembic import op + +revision: str = "143" +down_revision: str | None = "142" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + +PUBLICATION_NAME = "zero_publication" + +# Must stay in sync with the column lists in migrations 117 / 139 / 140. +DOCUMENT_COLS = [ + "id", + "title", + "document_type", + "search_space_id", + "folder_id", + "created_by_id", + "status", + "created_at", + "updated_at", +] + +USER_COLS = [ + "id", + "pages_limit", + "pages_used", + "premium_credit_micros_limit", + "premium_credit_micros_used", +] + + +def _has_zero_version(conn, table: str) -> bool: + return ( + conn.execute( + sa.text( + "SELECT 1 FROM information_schema.columns " + "WHERE table_name = :tbl AND column_name = '_0_version'" + ), + {"tbl": table}, + ).fetchone() + is not None + ) + + +def _build_set_table_ddl( + *, documents_has_zero_ver: bool, user_has_zero_ver: bool +) -> str: + doc_cols = DOCUMENT_COLS + (['"_0_version"'] if documents_has_zero_ver else []) + user_cols = USER_COLS + (['"_0_version"'] if user_has_zero_ver else []) + doc_col_list = ", ".join(doc_cols) + user_col_list = ", ".join(user_cols) + return ( + f"ALTER PUBLICATION {PUBLICATION_NAME} SET TABLE " + f"notifications, " + f"documents ({doc_col_list}), " + f"folders, " + f"search_source_connectors, " + f"new_chat_messages, " + f"chat_comments, " + f"chat_session_state, " + f'"user" ({user_col_list})' + ) + + +def upgrade() -> None: + conn = op.get_bind() + + exists = conn.execute( + sa.text("SELECT 1 FROM pg_publication WHERE pubname = :name"), + {"name": PUBLICATION_NAME}, + ).fetchone() + if not exists: + return + + documents_has_zero_ver = _has_zero_version(conn, "documents") + user_has_zero_ver = _has_zero_version(conn, "user") + + # The COMMENT-ALTER-COMMENT trio MUST run in a single transaction so + # Zero observes them as one schema-change event. Alembic's outer + # transaction already covers us, but a SAVEPOINT keeps the trio + # atomic with asyncpg, matching the pattern used in migrations + # 117 / 139 / 140. + tx = conn.begin_nested() if conn.in_transaction() else conn.begin() + with tx: + conn.execute( + sa.text(f"COMMENT ON PUBLICATION {PUBLICATION_NAME} IS 'pre-143-resync'") + ) + conn.execute( + sa.text( + _build_set_table_ddl( + documents_has_zero_ver=documents_has_zero_ver, + user_has_zero_ver=user_has_zero_ver, + ) + ) + ) + conn.execute( + sa.text(f"COMMENT ON PUBLICATION {PUBLICATION_NAME} IS 'post-143-resync'") + ) + + +def downgrade() -> None: + """No-op. The publication shape is unchanged versus migration 140.""" From c43bfdb1d97ac28ef366ee53367a8fe2e69126be Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 17:31:49 +0530 Subject: [PATCH 03/16] chore(migration): update migration files to enforce new publication mutation pattern --- .../alembic/versions/116_create_zero_publication.py | 11 +++++++++++ .../117_optimize_zero_publication_column_lists.py | 10 ++++++++++ .../118_add_local_folder_sync_and_versioning.py | 11 +++++++++++ .../versions/139_add_user_to_zero_publication.py | 10 ++++++++++ .../versions/140_premium_tokens_to_credit_micros.py | 10 ++++++++++ 5 files changed, 52 insertions(+) diff --git a/surfsense_backend/alembic/versions/116_create_zero_publication.py b/surfsense_backend/alembic/versions/116_create_zero_publication.py index ff74952a9..927673c35 100644 --- a/surfsense_backend/alembic/versions/116_create_zero_publication.py +++ b/surfsense_backend/alembic/versions/116_create_zero_publication.py @@ -5,6 +5,17 @@ queries via Zero, instead of replicating all tables in public schema. See: https://zero.rocicorp.dev/docs/zero-cache-config#app-publications +NOTE for future migration authors: this is the ONLY migration allowed +to use bare ``CREATE PUBLICATION``. All subsequent mutations of +``zero_publication`` MUST use the ``COMMENT ON PUBLICATION`` bookend +pattern wrapping an ``ALTER PUBLICATION ... SET TABLE`` -- copy the +``upgrade()`` function from migration +``143_force_zero_publication_resync.py`` as your starting template. +Raw ``DROP``/``CREATE PUBLICATION`` in new migrations would +re-introduce bug #1355 (zero-cache stuck on a stale replica snapshot +because Zero >= 1.0's change-streamer never sees the schema-change +event). + Revision ID: 116 Revises: 115 """ diff --git a/surfsense_backend/alembic/versions/117_optimize_zero_publication_column_lists.py b/surfsense_backend/alembic/versions/117_optimize_zero_publication_column_lists.py index 3ad5a043b..c21ed2bf0 100644 --- a/surfsense_backend/alembic/versions/117_optimize_zero_publication_column_lists.py +++ b/surfsense_backend/alembic/versions/117_optimize_zero_publication_column_lists.py @@ -17,6 +17,16 @@ IMPORTANT — before AND after running this migration: 3. Delete / reset the zero-cache data volume 4. Restart zero-cache (it will do a fresh initial sync) +DO NOT COPY THIS PATTERN. The ``DROP PUBLICATION`` + ``CREATE +PUBLICATION`` dance below is the pre-#1355 anti-pattern: on Zero >= +1.0 it does not reliably wake the zero-cache change-streamer and can +leave the replica pinned to a stale snapshot. This file is +grandfathered in because it has already shipped to users; new +publication mutations MUST use the ``COMMENT ON PUBLICATION`` bookend +pattern wrapping an ``ALTER PUBLICATION ... SET TABLE`` -- copy the +``upgrade()`` function from migration +``143_force_zero_publication_resync.py`` as your starting template. + Revision ID: 117 Revises: 116 """ diff --git a/surfsense_backend/alembic/versions/118_add_local_folder_sync_and_versioning.py b/surfsense_backend/alembic/versions/118_add_local_folder_sync_and_versioning.py index 1fef9fbcb..1dce24e56 100644 --- a/surfsense_backend/alembic/versions/118_add_local_folder_sync_and_versioning.py +++ b/surfsense_backend/alembic/versions/118_add_local_folder_sync_and_versioning.py @@ -1,5 +1,16 @@ """Add LOCAL_FOLDER_FILE document type, folder metadata, and document_versions table +DO NOT COPY THIS PATTERN. The bare ``ALTER PUBLICATION ... ADD/DROP +TABLE`` calls below pre-date the ``COMMENT ON PUBLICATION`` bookend +fix for bug #1355: on Zero >= 1.0 they do not reliably wake the +zero-cache change-streamer and can leave the replica pinned to a +stale snapshot. This file is grandfathered in because it has already +shipped to users; new publication mutations MUST use the +``COMMENT ON PUBLICATION`` bookend pattern wrapping an +``ALTER PUBLICATION ... SET TABLE`` -- copy the ``upgrade()`` function +from migration ``143_force_zero_publication_resync.py`` as your +starting template. + Revision ID: 118 Revises: 117 """ diff --git a/surfsense_backend/alembic/versions/139_add_user_to_zero_publication.py b/surfsense_backend/alembic/versions/139_add_user_to_zero_publication.py index 83c96a429..646049e3c 100644 --- a/surfsense_backend/alembic/versions/139_add_user_to_zero_publication.py +++ b/surfsense_backend/alembic/versions/139_add_user_to_zero_publication.py @@ -21,6 +21,16 @@ IMPORTANT - before AND after running this migration: 3. Delete / reset the zero-cache data volume 4. Restart zero-cache (it will do a fresh initial sync) +DO NOT COPY THIS PATTERN. The ``DROP PUBLICATION`` + ``CREATE +PUBLICATION`` dance below is the pre-#1355 anti-pattern: on Zero >= +1.0 it does not reliably wake the zero-cache change-streamer and can +leave the replica pinned to a stale snapshot. This file is +grandfathered in because it has already shipped to users; new +publication mutations MUST use the ``COMMENT ON PUBLICATION`` bookend +pattern wrapping an ``ALTER PUBLICATION ... SET TABLE`` -- copy the +``upgrade()`` function from migration +``143_force_zero_publication_resync.py`` as your starting template. + Revision ID: 139 Revises: 138 """ diff --git a/surfsense_backend/alembic/versions/140_premium_tokens_to_credit_micros.py b/surfsense_backend/alembic/versions/140_premium_tokens_to_credit_micros.py index 64aa699e8..ff88ac34e 100644 --- a/surfsense_backend/alembic/versions/140_premium_tokens_to_credit_micros.py +++ b/surfsense_backend/alembic/versions/140_premium_tokens_to_credit_micros.py @@ -32,6 +32,16 @@ Skipping the zero-cache stop will deadlock at the ACCESS EXCLUSIVE LOCK on "user". Skipping the data-volume reset will leave IndexedDB clients seeing column-not-found errors from a stale catalog snapshot. +DO NOT COPY THIS PATTERN. The ``DROP PUBLICATION`` + ``CREATE +PUBLICATION`` dance below is the pre-#1355 anti-pattern: on Zero >= +1.0 it does not reliably wake the zero-cache change-streamer and can +leave the replica pinned to a stale snapshot. This file is +grandfathered in because it has already shipped to users; new +publication mutations MUST use the ``COMMENT ON PUBLICATION`` bookend +pattern wrapping an ``ALTER PUBLICATION ... SET TABLE`` -- copy the +``upgrade()`` function from migration +``143_force_zero_publication_resync.py`` as your starting template. + Revision ID: 140 Revises: 139 """ From 8ea042e88c59030b9c21fa085cfd079a37c33c13 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 20:57:15 +0530 Subject: [PATCH 04/16] refactor(chat): improve user query handling and mention chip functionality --- .../app/tasks/chat/stream_new_chat.py | 22 ++-- .../assistant-ui/inline-mention-editor.tsx | 117 +++++++++++++----- .../components/assistant-ui/mention-chip.tsx | 10 +- 3 files changed, 107 insertions(+), 42 deletions(-) diff --git a/surfsense_backend/app/tasks/chat/stream_new_chat.py b/surfsense_backend/app/tasks/chat/stream_new_chat.py index 818282996..aed62ece9 100644 --- a/surfsense_backend/app/tasks/chat/stream_new_chat.py +++ b/surfsense_backend/app/tasks/chat/stream_new_chat.py @@ -1507,14 +1507,20 @@ async def stream_new_chat( # Resolve @-mention chips to canonical virtual paths and rewrite # the user-typed text so the LLM sees ``\`/documents/...\``` instead - # of bare ``@title``. The persisted user-message text keeps - # ``@title`` so chip rendering on reload is unchanged — see - # ``persistence._build_user_content``. + # of bare ``@title``. The substitution lands in ``agent_user_query`` + # ONLY — the original ``user_query`` (with ``@title`` tokens) flows + # untouched into ``persist_user_turn`` below so chip rendering on + # reload still works (``UserTextPart`` → ``parseMentionSegments`` + # matches ``@title``, not ``\`/documents/...\```). It also feeds + # the human-readable surfaces — SSE "Processing X" status, auto + # thread title, memory seed — which all want what the user typed. + # See ``persistence._build_user_content``. # # Cloud mode only: local-folder mode keeps the legacy # ``@title`` text path; mention support there is a follow-up # task because the path scheme (mount-rooted) and the picker # UI both need separate work. + agent_user_query = user_query accepted_folder_ids: list[int] = [] if fs_mode == FilesystemMode.CLOUD.value and ( mentioned_document_ids @@ -1549,11 +1555,13 @@ async def stream_new_chat( mentioned_surfsense_doc_ids=mentioned_surfsense_doc_ids, mentioned_folder_ids=mentioned_folder_ids, ) - user_query = substitute_in_text(user_query, resolved.token_to_path) + agent_user_query = substitute_in_text(user_query, resolved.token_to_path) accepted_folder_ids = resolved.mentioned_folder_ids - # Format the user query with context (SurfSense docs + reports only) - final_query = user_query + # Format the user query with context (SurfSense docs + reports only). + # Uses ``agent_user_query`` so the LLM sees backtick-wrapped paths + # instead of bare ``@title`` tokens. + final_query = agent_user_query context_parts = [] if mentioned_surfsense_docs: @@ -1584,7 +1592,7 @@ async def stream_new_chat( if context_parts: context = "\n\n".join(context_parts) - final_query = f"{context}\n\n{user_query}" + final_query = f"{context}\n\n{agent_user_query}" if visibility == ChatVisibility.SEARCH_SPACE and current_user_display_name: final_query = f"**[{current_user_display_name}]:** {final_query}" diff --git a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx index e12556486..c2b896794 100644 --- a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx +++ b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx @@ -1,6 +1,6 @@ "use client"; -import { Folder as FolderIcon } from "lucide-react"; +import { Folder as FolderIcon, X as XIcon } from "lucide-react"; import type { PlateElementProps } from "platejs/react"; import { createPlatePlugin, @@ -9,7 +9,16 @@ import { PlateContent, usePlateEditor, } from "platejs/react"; -import { type FC, forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from "react"; +import { + createContext, + type FC, + forwardRef, + useCallback, + useContext, + useImperativeHandle, + useMemo, + useRef, +} from "react"; import { FOLDER_MENTION_DOCUMENT_TYPE } from "@/atoms/chat/mentioned-documents.atom"; import { getConnectorIcon } from "@/contracts/enums/connectorIcons"; import type { Document } from "@/contracts/types/document.types"; @@ -107,13 +116,25 @@ type ComposerValue = ComposerParagraph[]; const MENTION_TYPE = "mention"; const MENTION_CHIP_CLASSNAME = - "inline-flex h-5 items-center gap-1 mx-0.5 rounded bg-primary/10 px-1 text-xs font-bold text-primary/60 select-none align-middle leading-none"; + "group inline-flex h-5 items-center gap-1 mx-0.5 rounded bg-primary/10 px-1 text-xs font-bold text-primary/60 select-none align-middle leading-none"; const MENTION_CHIP_ICON_CLASSNAME = "flex items-center text-muted-foreground leading-none"; const MENTION_CHIP_TITLE_CLASSNAME = "max-w-[120px] truncate leading-none"; const COMPOSER_TEXT_METRICS_CLASSNAME = "text-sm leading-6"; const EMPTY_VALUE: ComposerValue = [{ type: "p", children: [{ text: "" }] }]; +/** + * Internal seam that lets ``MentionElement`` (a Plate render component + * with no React props beyond ``element``) reach the editor's chip-removal + * function. Mirrors the Backspace path in ``handleKeyDown`` so the X + * button delegates to the exact same combined call site — no extra + * state, no atom coupling leaking into the chip. + */ +type MentionEditorContextValue = { + removeChip: (docId: number, docType: string | undefined) => void; +}; +const MentionEditorContext = createContext(null); + const MentionElement: FC> = ({ attributes, children, @@ -127,16 +148,36 @@ const MentionElement: FC> = ({ : "text-amber-700"; const isFolder = element.kind === "folder"; + const ctx = useContext(MentionEditorContext); return ( - {isFolder ? ( - - ) : ( - getConnectorIcon(element.document_type ?? "UNKNOWN", "h-3 w-3") - )} + + + {isFolder ? ( + + ) : ( + getConnectorIcon(element.document_type ?? "UNKNOWN", "h-3 w-3") + )} + + {ctx ? ( + + ) : null} + {element.title} @@ -464,6 +505,18 @@ export const InlineMentionEditor = forwardRef { + removeDocumentChip(docId, docType); + onDocumentRemove?.(docId, docType); + }, + [onDocumentRemove, removeDocumentChip] + ); + const setDocumentChipStatus = useCallback( ( docId: number, @@ -568,10 +621,9 @@ export const InlineMentionEditor = forwardRef( + () => ({ removeChip }), + [removeChip] + ); + return (
- { - emitState(value as ComposerValue); - }} - > - - + + { + emitState(value as ComposerValue); + }} + > + + +
); } diff --git a/surfsense_web/components/assistant-ui/mention-chip.tsx b/surfsense_web/components/assistant-ui/mention-chip.tsx index 9f9c9b177..7197fccdc 100644 --- a/surfsense_web/components/assistant-ui/mention-chip.tsx +++ b/surfsense_web/components/assistant-ui/mention-chip.tsx @@ -66,23 +66,21 @@ export function MentionChip({ disabled={disabled} aria-label={ariaLabel ?? label} className={cn( - "inline-flex max-w-[220px] items-center gap-1.5 rounded-md border bg-background px-2 py-0.5 align-middle text-xs font-medium text-foreground leading-5 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", - isInteractive - ? "cursor-pointer hover:bg-accent hover:text-accent-foreground" - : "cursor-default", + "inline-flex h-5 items-center gap-1 rounded bg-primary/10 px-1 align-middle text-xs font-bold text-primary/60 leading-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", + isInteractive ? "cursor-pointer" : "cursor-default", disabled && "opacity-60", className )} > {icon} - {label} + {label} ); if (!tooltip) return chip; return ( - + {chip} {tooltip} From 0c2beb7ce8c4b417abac0eb5e6d13dd577b15064 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 21:26:33 +0530 Subject: [PATCH 05/16] fix(thread): conditionally render screen capture button for desktop users --- .../components/assistant-ui/thread.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx index ec7d19eff..4f4395611 100644 --- a/surfsense_web/components/assistant-ui/thread.tsx +++ b/surfsense_web/components/assistant-ui/thread.tsx @@ -1212,17 +1212,19 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false )}
- void handleScreenCapture()} - > - - + {isDesktop && ( + void handleScreenCapture()} + > + + + )} !thread.isRunning}> Date: Tue, 12 May 2026 23:18:45 +0530 Subject: [PATCH 06/16] refactor(assistant-ui): enhance mention chip handling and editor focus behavior --- .../assistant-ui/inline-mention-editor.tsx | 241 ++++++++++-------- .../components/assistant-ui/thread.tsx | 108 +++++--- 2 files changed, 215 insertions(+), 134 deletions(-) diff --git a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx index c2b896794..da5fe878f 100644 --- a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx +++ b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx @@ -1,6 +1,7 @@ "use client"; import { Folder as FolderIcon, X as XIcon } from "lucide-react"; +import type { NodeEntry, TElement } from "platejs"; import type { PlateElementProps } from "platejs/react"; import { createPlatePlugin, @@ -56,10 +57,7 @@ export interface InlineMentionEditorRef { setText: (text: string) => void; getText: () => string; getMentionedDocuments: () => MentionedDocument[]; - insertMentionChip: ( - mention: MentionChipInput, - options?: { removeTriggerText?: boolean } - ) => void; + insertMentionChip: (mention: MentionChipInput, options?: { removeTriggerText?: boolean }) => void; /** * @deprecated Use ``insertMentionChip``. Kept for one transition * cycle so we don't break ad-hoc callers; prefer the new name. @@ -338,17 +336,21 @@ export const InlineMentionEditor = forwardRef { - const el = editableRef.current; - if (!el) return; - el.focus(); - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNodeContents(el); - range.collapse(false); - selection?.removeAllRanges(); - selection?.addRange(range); - }, []); + try { + editor.tf.select(editor.api.end([])); + editor.tf.focus(); + } catch { + editableRef.current?.focus(); + } + }, [editor]); const getCurrentValue = useCallback( () => (editor.children as ComposerValue) ?? EMPTY_VALUE, @@ -396,17 +398,30 @@ export const InlineMentionEditor = forwardRef { if (typeof mention.id !== "number" || typeof mention.title !== "string") return; const removeTriggerText = options?.removeTriggerText ?? true; - const current = getCurrentValue(); - const selection = editor.selection; const kind: MentionKind = mention.kind ?? "doc"; const document_type = - mention.document_type ?? - (kind === "folder" ? FOLDER_MENTION_DOCUMENT_TYPE : undefined); + mention.document_type ?? (kind === "folder" ? FOLDER_MENTION_DOCUMENT_TYPE : undefined); const mentionNode: MentionElementNode = { type: MENTION_TYPE, id: mention.id, @@ -416,60 +431,49 @@ export const InlineMentionEditor = forwardRef { + const selection = editor.selection; - const block = current[cursorCtx.blockIndex]; - const currentChild = getTextNode(block.children[cursorCtx.childIndex]); - if (!currentChild) { - const children = [...block.children]; - children.splice(cursorCtx.childIndex + 1, 0, mentionNode, { text: " " }); - const next = [...current]; - next[cursorCtx.blockIndex] = { ...block, children }; - setValue(next as ComposerValue); - requestAnimationFrame(focusAtEnd); - return; - } - - const text = currentChild.text; - let removeStart = cursorCtx.cursor; - if (removeTriggerText) { - for (let i = cursorCtx.cursor - 1; i >= 0; i--) { - if (text[i] === "@") { - removeStart = i; - break; + // No active editor selection — typically because focus + // moved to a picker/dropdown. Snap the caret to the end + // of the document so the chip appends cleanly instead + // of disappearing into a dead range. + if (!selection) { + editor.tf.select(editor.api.end([])); + } else if (removeTriggerText) { + // Delete the in-progress "@query" text so the chip + // stands in for it. Mirrors the old splice but lets + // Slate keep selection sane through the edit. + const cursorCtx = getCursorTextContext(getCurrentValue(), selection); + if (cursorCtx) { + const text = cursorCtx.text; + let triggerIndex = -1; + for (let i = cursorCtx.cursor - 1; i >= 0; i--) { + if (text[i] === "@") { + triggerIndex = i; + break; + } + if (text[i] === " " || text[i] === "\n") break; + } + if (triggerIndex >= 0 && triggerIndex < cursorCtx.cursor) { + const path = [cursorCtx.blockIndex, cursorCtx.childIndex]; + editor.tf.delete({ + at: { + anchor: { path, offset: triggerIndex }, + focus: { path, offset: cursorCtx.cursor }, + }, + }); + } } - if (text[i] === " " || text[i] === "\n") break; } - } - const before = text.slice(0, removeStart); - const after = text.slice(cursorCtx.cursor); - const replacement: ComposerNode[] = []; - if (before.length > 0) replacement.push({ text: before }); - replacement.push(mentionNode); - replacement.push({ text: ` ${after}` }); - - const children = [...block.children]; - children.splice(cursorCtx.childIndex, 1, ...replacement); - const next = [...current]; - next[cursorCtx.blockIndex] = { ...block, children }; - setValue(next as ComposerValue); - requestAnimationFrame(focusAtEnd); + editor.tf.insertNodes([mentionNode, { text: " " }] as unknown as TElement[], { + select: true, + }); + }); + editor.tf.focus(); }, - [editor.selection, focusAtEnd, getCurrentValue, setValue] + [editor, getCurrentValue] ); // Backwards-compatible shim — pre-folder callers pass a doc-only @@ -485,24 +489,34 @@ export const InlineMentionEditor = forwardRef { - const current = getCurrentValue(); - let changed = false; - const next = current.map((block) => { - const children = block.children.filter((node) => { - if (!isMentionNode(node)) return true; - const match = - node.id === docId && (node.document_type ?? "UNKNOWN") === (docType ?? "UNKNOWN"); - if (match) changed = true; - return !match; - }); - return { ...block, children: children.length ? children : [{ text: "" }] }; + const match = (n: unknown) => { + if (!n || typeof n !== "object" || !("type" in n)) return false; + const node = n as MentionElementNode; + if (node.type !== MENTION_TYPE) return false; + if (node.id !== docId) return false; + return (node.document_type ?? "UNKNOWN") === (docType ?? "UNKNOWN"); + }; + + const entries = Array.from(editor.api.nodes({ at: [], match })) as NodeEntry[]; + if (entries.length === 0) return; + editor.tf.withoutNormalizing(() => { + for (const [, path] of entries.reverse()) { + editor.tf.removeNodes({ at: path }); + } }); - if (!changed) return; - setValue(next as ComposerValue); }, - [getCurrentValue, setValue] + [editor] ); // Combined "remove chip end-to-end" used by both the Backspace @@ -517,6 +531,11 @@ export const InlineMentionEditor = forwardRef { - const current = getCurrentValue(); - let changed = false; - const next = current.map((block) => ({ - ...block, - children: block.children.map((node) => { - if (!isMentionNode(node)) return node; - const sameType = (node.document_type ?? "UNKNOWN") === (docType ?? "UNKNOWN"); - if (node.id !== docId || !sameType) return node; - changed = true; - return { - ...node, - statusLabel, - statusKind: statusLabel ? statusKind : undefined, - }; - }), - })); - if (!changed) return; - setValue(next as ComposerValue); + const match = (n: unknown) => { + if (!n || typeof n !== "object" || !("type" in n)) return false; + const node = n as MentionElementNode; + if (node.type !== MENTION_TYPE) return false; + if (node.id !== docId) return false; + return (node.document_type ?? "UNKNOWN") === (docType ?? "UNKNOWN"); + }; + + editor.tf.setNodes( + { + statusLabel, + statusKind: statusLabel ? statusKind : undefined, + } as Partial, + { at: [], match } + ); }, - [getCurrentValue, setValue] + [editor] ); const clear = useCallback(() => { setValue(EMPTY_VALUE); - }, [setValue]); + // ``tf.setValue`` (inside ``setValue``) wipes the editor's + // selection — without this, after the user presses Enter to + // submit, the composer is left with no caret and they would + // have to click before typing again. + requestAnimationFrame(focusAtEnd); + }, [focusAtEnd, setValue]); const setText = useCallback( (text: string) => { @@ -567,7 +588,22 @@ export const InlineMentionEditor = forwardRef ({ - focus: () => editableRef.current?.focus(), + // If we already have a Plate selection (user was typing + // before focus left), preserve it — just refocus. If we + // don't (first mount, or focus was lost without a + // surviving selection), seed a selection at end-of-doc + // so the contentEditable shows a caret instead of an + // invisible focus ring. + focus: () => { + try { + if (!editor.selection) { + editor.tf.select(editor.api.end([])); + } + editor.tf.focus(); + } catch { + editableRef.current?.focus(); + } + }, clear, setText, getText, @@ -579,6 +615,7 @@ export const InlineMentionEditor = forwardRef { const promptPickerRef = useRef(null); const { search_space_id, chat_id } = useParams(); const aui = useAui(); - const hasAutoFocusedRef = useRef(false); + // Gate the always-focused composer behaviour to desktop. On mobile, + // programmatic focus pops the soft keyboard, which would be jarring + // whenever a picker closes or the user navigates between threads. + const isDesktop = useMediaQuery("(min-width: 640px)"); const electronAPI = useElectronAPI(); const [clipboardInitialText, setClipboardInitialText] = useState(); @@ -437,16 +441,24 @@ const Composer: FC = () => { ); useBatchCommentsPreload(assistantDbMessageIds); - // Auto-focus editor on new chat page after mount + // Always-focused composer (Claude-style). Runs as a reactive + // invariant: whenever the composer is mounted and no transient + // picker has taken over keyboard input, the editor should be the + // focused element. This naturally restores focus after pickers + // close, after the user switches threads, and on first mount — + // replacing the previous one-shot ``hasAutoFocusedRef`` gate that + // only worked on the welcome screen. + // + // Gated on ``isDesktop`` so we don't repeatedly summon the mobile + // soft keyboard whenever any of the deps change. ``threadId`` is + // read so the effect re-fires when the user switches between two + // non-empty threads (where the Composer instance is reused). useEffect(() => { - if (isThreadEmpty && !hasAutoFocusedRef.current && editorRef.current) { - const timeoutId = setTimeout(() => { - editorRef.current?.focus(); - hasAutoFocusedRef.current = true; - }, 100); - return () => clearTimeout(timeoutId); - } - }, [isThreadEmpty]); + if (!isDesktop) return; + if (showDocumentPopover || showPromptPicker) return; + void threadId; + editorRef.current?.focus(); + }, [isDesktop, showDocumentPopover, showPromptPicker, threadId]); // Close document picker when a slide-out panel (inbox, shared/private chats) opens useEffect(() => { @@ -458,12 +470,45 @@ const Composer: FC = () => { return () => window.removeEventListener(SLIDEOUT_PANEL_OPENED_EVENT, handler); }, []); - // Sync editor text with assistant-ui composer runtime + // Sync editor text with the assistant-ui composer runtime and + // reconcile the chip atom from the editor's reported docs. + // + // The editor is the source of truth for which chips exist on + // screen. Reconciling here covers every deletion path Plate can + // produce (the explicit Backspace handler, the X-button, + // Cmd+Backspace, range-select+Delete, cut, paste-over) without + // needing per-keybinding plumbing. Without this, paths that bypass + // ``onDocumentRemove`` left the atom carrying stale entries that + // the picker would re-emit via ``initialSelectedDocuments`` and + // resurface as chips on the next selection. + // + // The setter returns ``prev`` when the chip set is unchanged so + // pure-text keystrokes don't churn the atom (Jotai compares by + // reference for store change notifications). const handleEditorChange = useCallback( - (text: string) => { + (text: string, docs: MentionedDocument[]) => { aui.composer().setText(text); + setMentionedDocuments((prev) => { + if (prev.length === docs.length) { + const editorKeys = new Set(docs.map((d) => getMentionDocKey(d))); + if (prev.every((d) => editorKeys.has(getMentionDocKey(d)))) { + return prev; + } + } + return docs.map((d) => ({ + id: d.id, + title: d.title, + // ``MentionedDocument.document_type`` is optional but + // the atom shape requires a string. ``"UNKNOWN"`` is + // the same sentinel ``getMentionDocKey`` and the + // editor's match predicates already use, so the key + // is stable across the round trip. + document_type: d.document_type ?? "UNKNOWN", + kind: d.kind, + })); + }); }, - [aui] + [aui, setMentionedDocuments] ); // Open document picker when @ mention is triggered @@ -621,27 +666,26 @@ const Composer: FC = () => { [setMentionedDocuments] ); - const handleDocumentsMention = useCallback( - (mentions: MentionedDocumentInfo[]) => { - const editorMentionedDocs = editorRef.current?.getMentionedDocuments() ?? []; - const editorDocKeys = new Set(editorMentionedDocs.map((doc) => getMentionDocKey(doc))); + const handleDocumentsMention = useCallback((mentions: MentionedDocumentInfo[]) => { + const editorMentionedDocs = editorRef.current?.getMentionedDocuments() ?? []; + const editorDocKeys = new Set(editorMentionedDocs.map((doc) => getMentionDocKey(doc))); - for (const mention of mentions) { - const key = getMentionDocKey(mention); - if (editorDocKeys.has(key)) continue; - editorRef.current?.insertMentionChip(mention); - } + for (const mention of mentions) { + const key = getMentionDocKey(mention); + if (editorDocKeys.has(key)) continue; + editorRef.current?.insertMentionChip(mention); + // Track within the loop so duplicates in the same batch + // (defensive — the picker shouldn't produce them today) + // can't slip through as double-inserted chips. + editorDocKeys.add(key); + } - setMentionedDocuments((prev) => { - const existingKeySet = new Set(prev.map((d) => getMentionDocKey(d))); - const uniqueNew = mentions.filter((m) => !existingKeySet.has(getMentionDocKey(m))); - return [...prev, ...uniqueNew]; - }); - - setMentionQuery(""); - }, - [setMentionedDocuments] - ); + // Atom is reconciled by the editor's ``onChange`` after each + // ``insertMentionChip`` (see ``handleEditorChange``); writing + // here would be a second, divergent write path — exactly the + // shape that let stale entries resurface in the past. + setMentionQuery(""); + }, []); useEffect(() => { const editor = editorRef.current; From 32ff864fd3f9a092dc0437483df0725895538b80 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 23:24:01 +0530 Subject: [PATCH 07/16] refactor(assistant-ui): streamline docstrings and comments --- .../assistant-ui/inline-mention-editor.tsx | 115 +++++------------- .../components/assistant-ui/thread.tsx | 110 ++++------------- 2 files changed, 57 insertions(+), 168 deletions(-) diff --git a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx index da5fe878f..cbd8e8d5a 100644 --- a/surfsense_web/components/assistant-ui/inline-mention-editor.tsx +++ b/surfsense_web/components/assistant-ui/inline-mention-editor.tsx @@ -36,13 +36,9 @@ export interface MentionedDocument { } /** - * Input shape for inserting a chip. ``kind`` defaults to ``"doc"`` - * when omitted so legacy callers don't have to thread the - * discriminator. Folder callers pass ``kind: "folder"`` and the - * folder ``id`` and ``title``; ``document_type`` defaults to - * ``FOLDER_MENTION_DOCUMENT_TYPE`` inside ``insertMentionChip`` so the - * dedup key (`kind:document_type:id`) never collides with a doc chip - * that happens to share an id. + * Input shape for inserting a chip. ``kind`` defaults to ``"doc"``. + * Folder chips default ``document_type`` to ``FOLDER_MENTION_DOCUMENT_TYPE`` + * so the dedup key never collides with a doc chip sharing the same id. */ export type MentionChipInput = { id: number; @@ -58,10 +54,7 @@ export interface InlineMentionEditorRef { getText: () => string; getMentionedDocuments: () => MentionedDocument[]; insertMentionChip: (mention: MentionChipInput, options?: { removeTriggerText?: boolean }) => void; - /** - * @deprecated Use ``insertMentionChip``. Kept for one transition - * cycle so we don't break ad-hoc callers; prefer the new name. - */ + /** @deprecated Use ``insertMentionChip``. */ insertDocumentChip: ( doc: Pick, options?: { removeTriggerText?: boolean } @@ -97,12 +90,7 @@ type MentionElementNode = { id: number; title: string; document_type?: string; - /** - * Discriminator added so a folder chip and a doc chip with the - * same id round-trip cleanly through ``getMentionedDocuments`` - * and the persisted ``mentioned-documents`` content part. - * Defaults to ``"doc"`` for nodes that predate this field. - */ + /** Discriminator; defaults to ``"doc"`` for legacy nodes. */ kind?: MentionKind; statusLabel?: string | null; statusKind?: MentionStatusKind; @@ -122,11 +110,8 @@ const COMPOSER_TEXT_METRICS_CLASSNAME = "text-sm leading-6"; const EMPTY_VALUE: ComposerValue = [{ type: "p", children: [{ text: "" }] }]; /** - * Internal seam that lets ``MentionElement`` (a Plate render component - * with no React props beyond ``element``) reach the editor's chip-removal - * function. Mirrors the Backspace path in ``handleKeyDown`` so the X - * button delegates to the exact same combined call site — no extra - * state, no atom coupling leaking into the chip. + * Lets ``MentionElement`` reach the editor's chip-removal helper so + * the X button and Backspace go through the same call site. */ type MentionEditorContextValue = { removeChip: (docId: number, docType: string | undefined) => void; @@ -336,13 +321,8 @@ export const InlineMentionEditor = forwardRef { try { editor.tf.select(editor.api.end([])); @@ -398,22 +378,13 @@ export const InlineMentionEditor = forwardRef { if (typeof mention.id !== "number" || typeof mention.title !== "string") return; @@ -434,16 +405,12 @@ export const InlineMentionEditor = forwardRef { const selection = editor.selection; - // No active editor selection — typically because focus - // moved to a picker/dropdown. Snap the caret to the end - // of the document so the chip appends cleanly instead - // of disappearing into a dead range. + // No active selection (focus moved to a picker) — snap + // to end-of-doc so the chip appends cleanly. if (!selection) { editor.tf.select(editor.api.end([])); } else if (removeTriggerText) { - // Delete the in-progress "@query" text so the chip - // stands in for it. Mirrors the old splice but lets - // Slate keep selection sane through the edit. + // Delete the in-progress "@query" so the chip stands in for it. const cursorCtx = getCursorTextContext(getCurrentValue(), selection); if (cursorCtx) { const text = cursorCtx.text; @@ -476,9 +443,7 @@ export const InlineMentionEditor = forwardRef, @@ -489,15 +454,10 @@ export const InlineMentionEditor = forwardRef { const match = (n: unknown) => { @@ -519,10 +479,8 @@ export const InlineMentionEditor = forwardRef { removeDocumentChip(docId, docType); @@ -531,11 +489,8 @@ export const InlineMentionEditor = forwardRef { setValue(EMPTY_VALUE); - // ``tf.setValue`` (inside ``setValue``) wipes the editor's - // selection — without this, after the user presses Enter to - // submit, the composer is left with no caret and they would - // have to click before typing again. + // ``tf.setValue`` wipes the selection — refocus so the caret + // returns after Enter-to-submit. requestAnimationFrame(focusAtEnd); }, [focusAtEnd, setValue]); @@ -588,12 +541,8 @@ export const InlineMentionEditor = forwardRef ({ - // If we already have a Plate selection (user was typing - // before focus left), preserve it — just refocus. If we - // don't (first mount, or focus was lost without a - // surviving selection), seed a selection at end-of-doc - // so the contentEditable shows a caret instead of an - // invisible focus ring. + // Preserve existing selection if any; otherwise seed one + // at end-of-doc so the contentEditable shows a caret. focus: () => { try { if (!editor.selection) { diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx index 64069870b..420f64fb3 100644 --- a/surfsense_web/components/assistant-ui/thread.tsx +++ b/surfsense_web/components/assistant-ui/thread.tsx @@ -172,36 +172,24 @@ const PremiumQuotaPinnedAlert: FC = () => { const getTimeBasedGreeting = (user?: { display_name?: string | null; email?: string }): string => { const hour = new Date().getHours(); - // Extract first name: prefer display_name, fall back to email extraction let firstName: string | null = null; - if (user?.display_name?.trim()) { - // Use display_name if available and not empty - // Extract first name from display_name (take first word) const nameParts = user.display_name.trim().split(/\s+/); firstName = nameParts[0].charAt(0).toUpperCase() + nameParts[0].slice(1).toLowerCase(); } else if (user?.email) { - // Fall back to email extraction if display_name is not available firstName = user.email.split("@")[0].split(".")[0].charAt(0).toUpperCase() + user.email.split("@")[0].split(".")[0].slice(1); } - // Array of greeting variations for each time period const morningGreetings = ["Good morning", "Fresh start today", "Morning", "Hey there"]; - const afternoonGreetings = ["Good afternoon", "Afternoon", "Hey there", "Hi there"]; - const eveningGreetings = ["Good evening", "Evening", "Hey there", "Hi there"]; - const nightGreetings = ["Good night", "Evening", "Hey there", "Winding down"]; - const lateNightGreetings = ["Still up", "Night owl mode", "Up past bedtime", "Hi there"]; - // Select a random greeting based on time let greeting: string; if (hour < 5) { - // Late night: midnight to 5 AM greeting = lateNightGreetings[Math.floor(Math.random() * lateNightGreetings.length)]; } else if (hour < 12) { greeting = morningGreetings[Math.floor(Math.random() * morningGreetings.length)]; @@ -210,33 +198,23 @@ const getTimeBasedGreeting = (user?: { display_name?: string | null; email?: str } else if (hour < 22) { greeting = eveningGreetings[Math.floor(Math.random() * eveningGreetings.length)]; } else { - // Night: 10 PM to midnight greeting = nightGreetings[Math.floor(Math.random() * nightGreetings.length)]; } - // Add personalization with first name if available - if (firstName) { - return `${greeting}, ${firstName}!`; - } - - return `${greeting}!`; + return firstName ? `${greeting}, ${firstName}!` : `${greeting}!`; }; const ThreadWelcome: FC = () => { const { data: user } = useAtomValue(currentUserAtom); - - // Memoize greeting so it doesn't change on re-renders (only on user change) const greeting = useMemo(() => getTimeBasedGreeting(user), [user]); return (
- {/* Greeting positioned above the composer */}

{greeting}

- {/* Composer - top edge fixed, expands downward only */}
@@ -373,7 +351,6 @@ const ClipboardChip: FC<{ text: string; onDismiss: () => void }> = ({ text, onDi }; const Composer: FC = () => { - // Document mention state (atoms persist across component remounts) const [mentionedDocuments, setMentionedDocuments] = useAtom(mentionedDocumentsAtom); const [showDocumentPopover, setShowDocumentPopover] = useState(false); const [showPromptPicker, setShowPromptPicker] = useState(false); @@ -385,9 +362,8 @@ const Composer: FC = () => { const promptPickerRef = useRef(null); const { search_space_id, chat_id } = useParams(); const aui = useAui(); - // Gate the always-focused composer behaviour to desktop. On mobile, - // programmatic focus pops the soft keyboard, which would be jarring - // whenever a picker closes or the user navigates between threads. + // Desktop-only auto-focus; on mobile, programmatic focus would + // summon the soft keyboard on every picker close / thread switch. const isDesktop = useMediaQuery("(min-width: 640px)"); const electronAPI = useElectronAPI(); @@ -408,7 +384,6 @@ const Composer: FC = () => { const currentPlaceholder = COMPOSER_PLACEHOLDER; - // Live collaboration state const { data: currentUser } = useAtomValue(currentUserAtom); const { data: members } = useAtomValue(membersAtom); const threadId = useMemo(() => { @@ -422,13 +397,11 @@ const Composer: FC = () => { const respondingToUserId = sessionState?.respondingToUserId ?? null; const isBlockedByOtherUser = isAiResponding && respondingToUserId !== currentUser?.id; - // Sync comments for the entire thread via Zero (one subscription per thread) + // One Zero subscription per thread for comment sync. useCommentsSync(threadId); - // Batch-prefetch comments for all assistant messages so individual useComments - // hooks never fire their own network requests (eliminates N+1 API calls). - // Return a primitive string from the selector so useSyncExternalStore can - // compare snapshots by value and avoid infinite re-render loops. + // Batch-prefetch assistant message comments to avoid N+1 fetches. + // Returns a primitive string so useSyncExternalStore can compare by value. const assistantIdsKey = useAuiState(({ thread }) => thread.messages .filter((m) => m.role === "assistant" && m.id?.startsWith("msg-")) @@ -441,18 +414,9 @@ const Composer: FC = () => { ); useBatchCommentsPreload(assistantDbMessageIds); - // Always-focused composer (Claude-style). Runs as a reactive - // invariant: whenever the composer is mounted and no transient - // picker has taken over keyboard input, the editor should be the - // focused element. This naturally restores focus after pickers - // close, after the user switches threads, and on first mount — - // replacing the previous one-shot ``hasAutoFocusedRef`` gate that - // only worked on the welcome screen. - // - // Gated on ``isDesktop`` so we don't repeatedly summon the mobile - // soft keyboard whenever any of the deps change. ``threadId`` is - // read so the effect re-fires when the user switches between two - // non-empty threads (where the Composer instance is reused). + // Always-focused composer: refocus whenever no picker has taken + // over input. ``threadId`` is in the deps so the effect re-fires + // on thread switch (Composer instance is reused). useEffect(() => { if (!isDesktop) return; if (showDocumentPopover || showPromptPicker) return; @@ -460,7 +424,7 @@ const Composer: FC = () => { editorRef.current?.focus(); }, [isDesktop, showDocumentPopover, showPromptPicker, threadId]); - // Close document picker when a slide-out panel (inbox, shared/private chats) opens + // Close document picker when a slide-out panel (inbox, etc.) opens. useEffect(() => { const handler = () => { setShowDocumentPopover(false); @@ -470,21 +434,12 @@ const Composer: FC = () => { return () => window.removeEventListener(SLIDEOUT_PANEL_OPENED_EVENT, handler); }, []); - // Sync editor text with the assistant-ui composer runtime and - // reconcile the chip atom from the editor's reported docs. - // - // The editor is the source of truth for which chips exist on - // screen. Reconciling here covers every deletion path Plate can - // produce (the explicit Backspace handler, the X-button, - // Cmd+Backspace, range-select+Delete, cut, paste-over) without - // needing per-keybinding plumbing. Without this, paths that bypass - // ``onDocumentRemove`` left the atom carrying stale entries that - // the picker would re-emit via ``initialSelectedDocuments`` and - // resurface as chips on the next selection. - // - // The setter returns ``prev`` when the chip set is unchanged so - // pure-text keystrokes don't churn the atom (Jotai compares by - // reference for store change notifications). + // Sync editor text into assistant-ui's composer and mirror the chip + // atom from the editor's reported ``docs``. The editor is the + // single source of truth, so this catches every Plate deletion path + // (Backspace, X button, Cmd+Backspace, range-delete, cut, + // paste-over) without per-keybinding plumbing. The ``prev`` + // short-circuit keeps pure-text keystrokes from churning the atom. const handleEditorChange = useCallback( (text: string, docs: MentionedDocument[]) => { aui.composer().setText(text); @@ -498,11 +453,9 @@ const Composer: FC = () => { return docs.map((d) => ({ id: d.id, title: d.title, - // ``MentionedDocument.document_type`` is optional but - // the atom shape requires a string. ``"UNKNOWN"`` is - // the same sentinel ``getMentionDocKey`` and the - // editor's match predicates already use, so the key - // is stable across the round trip. + // Atom requires a string; ``"UNKNOWN"`` matches the + // sentinel ``getMentionDocKey`` and the editor's + // match predicates use. document_type: d.document_type ?? "UNKNOWN", kind: d.kind, })); @@ -511,13 +464,11 @@ const Composer: FC = () => { [aui, setMentionedDocuments] ); - // Open document picker when @ mention is triggered const handleMentionTrigger = useCallback((query: string) => { setShowDocumentPopover(true); setMentionQuery(query); }, []); - // Close document picker and reset query const handleMentionClose = useCallback(() => { if (showDocumentPopover) { setShowDocumentPopover(false); @@ -525,13 +476,11 @@ const Composer: FC = () => { } }, [showDocumentPopover]); - // Open action picker when / is triggered const handleActionTrigger = useCallback((query: string) => { setShowPromptPicker(true); setActionQuery(query); }, []); - // Close action picker and reset query const handleActionClose = useCallback(() => { if (showPromptPicker) { setShowPromptPicker(false); @@ -575,7 +524,7 @@ const Composer: FC = () => { [clipboardInitialText, electronAPI, aui] ); - // Keyboard navigation for document/action picker (arrow keys, Enter, Escape) + // Arrow / Enter / Escape navigation for the active picker. const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (showPromptPicker) { @@ -656,7 +605,7 @@ const Composer: FC = () => { (docId: number, docType?: string) => { setMentionedDocuments((prev) => { if (!docType) { - // Defensive fallback: keep UI in sync even when chip type is unavailable. + // Fallback when chip type is unavailable. return prev.filter((doc) => doc.id !== docId); } const removedKey = getMentionDocKey({ id: docId, document_type: docType }); @@ -674,16 +623,12 @@ const Composer: FC = () => { const key = getMentionDocKey(mention); if (editorDocKeys.has(key)) continue; editorRef.current?.insertMentionChip(mention); - // Track within the loop so duplicates in the same batch - // (defensive — the picker shouldn't produce them today) - // can't slip through as double-inserted chips. + // Track within the loop so a duplicate-in-batch can't double-insert. editorDocKeys.add(key); } - // Atom is reconciled by the editor's ``onChange`` after each - // ``insertMentionChip`` (see ``handleEditorChange``); writing - // here would be a second, divergent write path — exactly the - // shape that let stale entries resurface in the past. + // Atom is reconciled by ``handleEditorChange`` via the editor's + // onChange — no second write path here. setMentionQuery(""); }, []); @@ -1315,12 +1260,7 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false ); }; -/** - * Friendly tool name for display in the chat UI. Delegates to the - * shared map in ``contracts/enums/toolIcons`` so unix-style identifiers - * (``rm``, ``ls``, ``grep`` …) and snake_cased function names render as - * plain English (e.g. "Delete file", "List files", "Search in files"). - */ +/** Friendly tool name (delegates to ``getToolDisplayName``). */ function formatToolName(name: string): string { return getToolDisplayName(name); } From 0884b63406135a817a7134a76f3a70f62f314d39 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 12 May 2026 23:25:33 +0530 Subject: [PATCH 08/16] chore: ran linting --- surfsense_web/atoms/chat/mentioned-documents.atom.ts | 4 +--- .../components/new-chat/document-mention-picker.tsx | 7 ++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/surfsense_web/atoms/chat/mentioned-documents.atom.ts b/surfsense_web/atoms/chat/mentioned-documents.atom.ts index eafdaf87e..9163960f4 100644 --- a/surfsense_web/atoms/chat/mentioned-documents.atom.ts +++ b/surfsense_web/atoms/chat/mentioned-documents.atom.ts @@ -97,9 +97,7 @@ export const mentionedDocumentIdsAtom = atom((get) => { surfsense_doc_ids: docs .filter((doc) => doc.document_type === "SURFSENSE_DOCS") .map((doc) => doc.id), - document_ids: docs - .filter((doc) => doc.document_type !== "SURFSENSE_DOCS") - .map((doc) => doc.id), + document_ids: docs.filter((doc) => doc.document_type !== "SURFSENSE_DOCS").map((doc) => doc.id), folder_ids: folders.map((f) => f.id), }; }); diff --git a/surfsense_web/components/new-chat/document-mention-picker.tsx b/surfsense_web/components/new-chat/document-mention-picker.tsx index 0881b11b6..0d68c8df8 100644 --- a/surfsense_web/components/new-chat/document-mention-picker.tsx +++ b/surfsense_web/components/new-chat/document-mention-picker.tsx @@ -301,8 +301,7 @@ export const DocumentMentionPicker = forwardRef< // folder entries lift the existing kind-aware key so the same // matchers used by the chip atom apply unchanged. const selectedKeys = useMemo( - () => - new Set(initialSelectedDocuments.map((d) => getMentionDocKey(d))), + () => new Set(initialSelectedDocuments.map((d) => getMentionDocKey(d))), [initialSelectedDocuments] ); @@ -583,9 +582,7 @@ export const DocumentMentionPicker = forwardRef< {(surfsenseDocsList.length > 0 || userDocsList.length > 0) && (
)} -
- Folders -
+
Folders
{folderMentions.map((folder) => { const folderKey = getMentionDocKey(folder); const isAlreadySelected = selectedKeys.has(folderKey); From 9b926b31337277e80c1a1f091d5a37ad7e588d5a Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Wed, 13 May 2026 00:22:43 +0530 Subject: [PATCH 09/16] refactor: update test for index() to use chunk_text_hybrid --- .../test_index_batch_parallel.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/surfsense_backend/tests/unit/indexing_pipeline/test_index_batch_parallel.py b/surfsense_backend/tests/unit/indexing_pipeline/test_index_batch_parallel.py index ae55bc089..10abd05e0 100644 --- a/surfsense_backend/tests/unit/indexing_pipeline/test_index_batch_parallel.py +++ b/surfsense_backend/tests/unit/indexing_pipeline/test_index_batch_parallel.py @@ -37,7 +37,11 @@ def _make_orm_doc(connector_doc, doc_id): async def test_index_calls_embed_and_chunk_via_to_thread( pipeline, make_connector_document, monkeypatch ): - """index() runs embed_texts and chunk_text via asyncio.to_thread, not blocking the loop.""" + """index() runs the chunker and embed_texts via asyncio.to_thread, not blocking the loop. + + The default (non-code) path uses ``chunk_text_hybrid`` so Markdown tables stay + intact (see issue #1334); ``chunk_text`` is reserved for the code-chunker branch. + """ to_thread_calls = [] original_to_thread = asyncio.to_thread @@ -51,11 +55,11 @@ async def test_index_calls_embed_and_chunk_via_to_thread( "app.indexing_pipeline.indexing_pipeline_service.summarize_document", AsyncMock(return_value="Summary."), ) - mock_chunk = MagicMock(return_value=["chunk1"]) - mock_chunk.__name__ = "chunk_text" + mock_chunk_hybrid = MagicMock(return_value=["chunk1"]) + mock_chunk_hybrid.__name__ = "chunk_text_hybrid" monkeypatch.setattr( - "app.indexing_pipeline.indexing_pipeline_service.chunk_text", - mock_chunk, + "app.indexing_pipeline.indexing_pipeline_service.chunk_text_hybrid", + mock_chunk_hybrid, ) mock_embed = MagicMock( side_effect=lambda texts: [[0.1] * _EMBEDDING_DIM for _ in texts] @@ -65,6 +69,11 @@ async def test_index_calls_embed_and_chunk_via_to_thread( "app.indexing_pipeline.indexing_pipeline_service.embed_texts", mock_embed, ) + # Bypass set_committed_value, which requires a real ORM instance (not MagicMock). + monkeypatch.setattr( + "app.indexing_pipeline.indexing_pipeline_service.attach_chunks_to_document", + MagicMock(), + ) connector_doc = make_connector_document( document_type=DocumentType.GOOGLE_GMAIL_CONNECTOR, @@ -77,8 +86,9 @@ async def test_index_calls_embed_and_chunk_via_to_thread( await pipeline.index(document, connector_doc, llm=MagicMock()) - assert "chunk_text" in to_thread_calls + assert "chunk_text_hybrid" in to_thread_calls assert "embed_texts" in to_thread_calls + assert document.status == DocumentStatus.ready() def _mock_session_factory(orm_docs_by_id): From bd452b3df4a53dc2624f73213c38b79e5d050e28 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Wed, 13 May 2026 00:44:20 +0530 Subject: [PATCH 10/16] fix(tests): improve composio module hijack in integration tests --- .../tests/integration/composio/conftest.py | 18 +++------ .../tests/integration/conftest.py | 37 +++++++++++++------ 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/surfsense_backend/tests/integration/composio/conftest.py b/surfsense_backend/tests/integration/composio/conftest.py index 779e7bdb2..44d707ec3 100644 --- a/surfsense_backend/tests/integration/composio/conftest.py +++ b/surfsense_backend/tests/integration/composio/conftest.py @@ -1,13 +1,11 @@ """Composio route integration fixtures. -The sys.modules hijack happens at module import time, before importing -app.app, so production `from composio import Composio` bindings resolve to -the strict E2E fake in this pytest process too. +The `composio` sys.modules hijack lives in the parent integration conftest +so it runs before any sibling suite imports `app.routes`. """ from __future__ import annotations -import sys from collections.abc import AsyncGenerator import httpx @@ -16,19 +14,15 @@ import pytest_asyncio from httpx import ASGITransport from sqlalchemy.ext.asyncio import AsyncSession -from tests.e2e.fakes import composio_module as _fake_composio - -sys.modules["composio"] = _fake_composio - -from app.app import app, limiter # noqa: E402 -from app.config import config # noqa: E402 -from app.db import ( # noqa: E402 +from app.app import app, limiter +from app.config import config +from app.db import ( SearchSourceConnector, SearchSourceConnectorType, User, get_async_session, ) -from app.users import current_active_user # noqa: E402 +from app.users import current_active_user pytestmark = pytest.mark.integration diff --git a/surfsense_backend/tests/integration/conftest.py b/surfsense_backend/tests/integration/conftest.py index d9d7cacae..2f4b3fe9a 100644 --- a/surfsense_backend/tests/integration/conftest.py +++ b/surfsense_backend/tests/integration/conftest.py @@ -1,3 +1,5 @@ +import importlib +import sys import uuid from unittest.mock import AsyncMock, MagicMock @@ -7,17 +9,27 @@ from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.pool import NullPool -from app.config import config as app_config -from app.db import ( - Base, - DocumentType, - SearchSourceConnector, - SearchSourceConnectorType, - SearchSpace, - User, -) -from app.indexing_pipeline.connector_document import ConnectorDocument -from tests.conftest import TEST_DATABASE_URL +# Hijack `composio` before any `from app.*` import; the `from composio import +# Composio` in app.services.composio_service binds once at first import. +from tests.e2e.fakes import composio_module as _fake_composio + +sys.modules["composio"] = _fake_composio + +app_config = importlib.import_module("app.config").config +app_db = importlib.import_module("app.db") +Base = app_db.Base +DocumentType = app_db.DocumentType +SearchSourceConnector = app_db.SearchSourceConnector +SearchSourceConnectorType = app_db.SearchSourceConnectorType +SearchSpace = app_db.SearchSpace +User = app_db.User +ConnectorDocument = importlib.import_module( + "app.indexing_pipeline.connector_document" +).ConnectorDocument +create_default_roles_and_membership = importlib.import_module( + "app.routes.search_spaces_routes" +).create_default_roles_and_membership +TEST_DATABASE_URL = importlib.import_module("tests.conftest").TEST_DATABASE_URL _EMBEDDING_DIM = app_config.embedding_model_instance.dimension @@ -105,6 +117,9 @@ async def db_search_space(db_session: AsyncSession, db_user: User) -> SearchSpac ) db_session.add(space) await db_session.flush() + # Mirror POST /searchspaces so routes guarded by check_permission find a membership. + await create_default_roles_and_membership(db_session, space.id, db_user.id) + await db_session.flush() return space From d9ec4018356e56667ad517c458d7a3da5e0ac5bc Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Wed, 13 May 2026 03:34:28 +0530 Subject: [PATCH 11/16] chore: remove caret from @rocicorp/zero dependency version --- surfsense_web/package.json | 2 +- surfsense_web/pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/surfsense_web/package.json b/surfsense_web/package.json index efeb45fd8..d71298c72 100644 --- a/surfsense_web/package.json +++ b/surfsense_web/package.json @@ -79,7 +79,7 @@ "@remotion/media": "^4.0.438", "@remotion/player": "^4.0.438", "@remotion/web-renderer": "^4.0.438", - "@rocicorp/zero": "^1.4.0", + "@rocicorp/zero": "1.4.0", "@slate-serializers/html": "^2.2.3", "@streamdown/code": "^1.0.2", "@streamdown/math": "^1.0.2", diff --git a/surfsense_web/pnpm-lock.yaml b/surfsense_web/pnpm-lock.yaml index 62056a215..8602feb8d 100644 --- a/surfsense_web/pnpm-lock.yaml +++ b/surfsense_web/pnpm-lock.yaml @@ -165,7 +165,7 @@ importers: specifier: ^4.0.438 version: 4.0.438(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@rocicorp/zero': - specifier: ^1.4.0 + specifier: 1.4.0 version: 1.4.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.0)) '@slate-serializers/html': specifier: ^2.2.3 From 3504be34133dd0584c48bbc96eaa6492ec30dda5 Mon Sep 17 00:00:00 2001 From: guangyang1206 Date: Sat, 16 May 2026 12:10:04 +0800 Subject: [PATCH 12/16] fix(web): make cacheKeys.*.withQueryParams order-stable (sort entries) Fixes #1370 Object.values() produces order-dependent cache keys because the order of values depends on the order of keys in the object. This causes the same logical query to produce different cache keys when the parameter object has keys in different orders. Added stableEntries() helper that: 1. Filters out undefined values 2. Sorts entries by key name 3. Returns flat array of [key, value] pairs This ensures cache key identity is stable regardless of parameter object key order. Co-authored-by: guangyang1206 --- surfsense_web/lib/query-client/cache-keys.ts | 23 +++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/surfsense_web/lib/query-client/cache-keys.ts b/surfsense_web/lib/query-client/cache-keys.ts index a05055075..ce45ee143 100644 --- a/surfsense_web/lib/query-client/cache-keys.ts +++ b/surfsense_web/lib/query-client/cache-keys.ts @@ -3,6 +3,19 @@ import type { GetDocumentsRequest } from "@/contracts/types/document.types"; import type { GetLogsRequest } from "@/contracts/types/log.types"; import type { GetSearchSpacesRequest } from "@/contracts/types/search-space.types"; +/** + * Convert an object to a stable array of [key, value] pairs sorted by key. + * This ensures cache keys are order-independent (avoiding Object.values order-dependency). + * Filters out undefined values. + */ +function stableEntries(obj: Record | null | undefined): unknown[] { + if (!obj) return []; + return Object.entries(obj) + .filter(([, v]) => v !== undefined) + .sort(([a], [b]) => a.localeCompare(b)) + .flat(); +} + export const cacheKeys = { // New chat threads (assistant-ui) threads: { @@ -13,9 +26,9 @@ export const cacheKeys = { }, documents: { globalQueryParams: (queries: GetDocumentsRequest["queryParams"]) => - ["documents", ...(queries ? Object.values(queries) : [])] as const, + ["documents", ...stableEntries(queries)] as const, withQueryParams: (queries: GetDocumentsRequest["queryParams"]) => - ["documents-with-queries", ...(queries ? Object.values(queries) : [])] as const, + ["documents-with-queries", ...stableEntries(queries)] as const, document: (documentId: string) => ["document", documentId] as const, byChunk: (chunkId: string) => ["documents", "by-chunk", chunkId] as const, }, @@ -24,7 +37,7 @@ export const cacheKeys = { detail: (logId: number | string) => ["logs", "detail", logId] as const, summary: (searchSpaceId?: number | string) => ["logs", "summary", searchSpaceId] as const, withQueryParams: (queries: GetLogsRequest["queryParams"]) => - ["logs", "with-query-params", ...(queries ? Object.values(queries) : [])] as const, + ["logs", "with-query-params", ...stableEntries(queries)] as const, }, newLLMConfigs: { all: (searchSpaceId: number) => ["new-llm-configs", searchSpaceId] as const, @@ -51,7 +64,7 @@ export const cacheKeys = { searchSpaces: { all: ["search-spaces"] as const, withQueryParams: (queries: GetSearchSpacesRequest["queryParams"]) => - ["search-spaces", ...(queries ? Object.values(queries) : [])] as const, + ["search-spaces", ...stableEntries(queries)] as const, detail: (searchSpaceId: string) => ["search-spaces", searchSpaceId] as const, }, user: { @@ -78,7 +91,7 @@ export const cacheKeys = { connectors: { all: (searchSpaceId: string) => ["connectors", searchSpaceId] as const, withQueryParams: (queries: GetConnectorsRequest["queryParams"]) => - ["connectors", ...(queries ? Object.values(queries) : [])] as const, + ["connectors", ...stableEntries(queries)] as const, byId: (connectorId: string) => ["connector", connectorId] as const, index: () => ["connector", "index"] as const, googleDrive: { From f096548a162b9a9062cfdc1f137a098eacba7b4b Mon Sep 17 00:00:00 2001 From: guangyang1206 Date: Sat, 16 May 2026 12:15:16 +0800 Subject: [PATCH 13/16] fix(web): extract single tryGetHostname helper (DRY, unified fallback) Fixes #1368 Previously, was duplicated in 4 places with 3 subtly different fallback behaviors: 1. inline-citation.tsx: returned on error 2. markdown-text.tsx: returned on error 3. assistant-message.tsx: returned on error 4. citation.tsx: returned on error Created canonical in that: - Returns - Strips prefix from hostname - Returns on invalid URL (safest contract) Updated all 4 call sites: - inline-citation.tsx: (preserves original fallback) - markdown-text.tsx: (preserves original fallback) - assistant-message.tsx: (drop-in, both return ) - citation.tsx: (drop-in, both return ) Co-authored-by: guangyang1206 --- .../components/assistant-ui/assistant-message.tsx | 12 +++--------- .../components/assistant-ui/inline-citation.tsx | 11 ++--------- .../components/assistant-ui/markdown-text.tsx | 13 +++---------- .../components/tool-ui/citation/citation.tsx | 12 ++---------- surfsense_web/lib/url.ts | 14 ++++++++++++++ 5 files changed, 24 insertions(+), 38 deletions(-) create mode 100644 surfsense_web/lib/url.ts diff --git a/surfsense_web/components/assistant-ui/assistant-message.tsx b/surfsense_web/components/assistant-ui/assistant-message.tsx index 00f3acebf..1748f47a9 100644 --- a/surfsense_web/components/assistant-ui/assistant-message.tsx +++ b/surfsense_web/components/assistant-ui/assistant-message.tsx @@ -24,6 +24,8 @@ import dynamic from "next/dynamic"; import type { FC } from "react"; import { useEffect, useMemo, useRef, useState } from "react"; import { commentsEnabledAtom, targetCommentIdAtom } from "@/atoms/chat/current-thread.atom"; +import { tryGetHostname } from "@/lib/url"; + import { globalNewLLMConfigsAtom, newLLMConfigsAtom, @@ -99,20 +101,12 @@ const GenerateImageToolUI = dynamic( import("@/components/tool-ui/generate-image").then((m) => ({ default: m.GenerateImageToolUI })), { ssr: false } ); -function extractDomain(url: string): string | undefined { - try { - return new URL(url).hostname.replace(/^www\./, ""); - } catch { - return undefined; - } -} - function useCitationsFromMetadata(): SerializableCitation[] { const allCitations = useAllCitationMetadata(); return useMemo(() => { const result: SerializableCitation[] = []; for (const [url, meta] of allCitations) { - const domain = extractDomain(url); + const domain = tryGetHostname(url); result.push({ id: `url-cite-${url}`, href: url, diff --git a/surfsense_web/components/assistant-ui/inline-citation.tsx b/surfsense_web/components/assistant-ui/inline-citation.tsx index 32a29cfc9..f0d9013bf 100644 --- a/surfsense_web/components/assistant-ui/inline-citation.tsx +++ b/surfsense_web/components/assistant-ui/inline-citation.tsx @@ -193,14 +193,7 @@ const SurfsenseDocCitation: FC<{ chunkId: number }> = ({ chunkId }) => { ); }; -function extractDomain(url: string): string { - try { - const hostname = new URL(url).hostname; - return hostname.replace(/^www\./, ""); - } catch { - return url; - } -} +import { tryGetHostname } from "@/lib/url"; interface UrlCitationProps { url: string; @@ -212,7 +205,7 @@ interface UrlCitationProps { * page title and snippet (extracted deterministically from web_search tool results). */ export const UrlCitation: FC = ({ url }) => { - const domain = extractDomain(url); + const domain = tryGetHostname(url) ?? url; const meta = useCitationMetadata(url); return ( diff --git a/surfsense_web/components/assistant-ui/markdown-text.tsx b/surfsense_web/components/assistant-ui/markdown-text.tsx index 1bb7cf2d9..43d435d20 100644 --- a/surfsense_web/components/assistant-ui/markdown-text.tsx +++ b/surfsense_web/components/assistant-ui/markdown-text.tsx @@ -23,6 +23,8 @@ import "katex/dist/katex.min.css"; import { toast } from "sonner"; import { processChildrenWithCitations } from "@/components/citations/citation-renderer"; import { Skeleton } from "@/components/ui/skeleton"; +import { tryGetHostname } from "@/lib/url"; + import { Table, TableBody, @@ -139,15 +141,6 @@ const MarkdownTextImpl = () => { export const MarkdownText = memo(MarkdownTextImpl); -function extractDomain(url: string): string { - try { - const parsed = new URL(url); - return parsed.hostname.replace(/^www\./, ""); - } catch { - return ""; - } -} - // Canonical local-file virtual paths are mount-prefixed: // const LOCAL_FILE_PATH_REGEX = /^\/[a-z0-9_-]+\/[^\s`]+(?:\/[^\s`]+)*$/; @@ -288,7 +281,7 @@ function FilePathLink({ path, className }: { path: string; className?: string }) function MarkdownImage({ src, alt }: { src?: string; alt?: string }) { if (!src) return null; - const domain = extractDomain(src); + const domain = tryGetHostname(src) ?? ""; return (
diff --git a/surfsense_web/components/tool-ui/citation/citation.tsx b/surfsense_web/components/tool-ui/citation/citation.tsx index 05ce214f3..a7c82de8c 100644 --- a/surfsense_web/components/tool-ui/citation/citation.tsx +++ b/surfsense_web/components/tool-ui/citation/citation.tsx @@ -6,19 +6,11 @@ import * as React from "react"; import { openSafeNavigationHref, sanitizeHref } from "../shared/media"; import { cn, Popover, PopoverContent, PopoverTrigger } from "./_adapter"; import type { CitationVariant, SerializableCitation } from "./schema"; +import { tryGetHostname } from "@/lib/url"; import { TYPE_ICONS } from "./type-icons"; const FALLBACK_LOCALE = "en-US"; -function extractDomain(url: string): string | undefined { - try { - const urlObj = new URL(url); - return urlObj.hostname.replace(/^www\./, ""); - } catch { - return undefined; - } -} - function formatDate(isoString: string, locale: string): string { try { const date = new Date(isoString); @@ -78,7 +70,7 @@ export function Citation(props: CitationProps) { const locale = providedLocale ?? FALLBACK_LOCALE; const sanitizedHref = sanitizeHref(rawHref); - const domain = providedDomain ?? extractDomain(rawHref); + const domain = providedDomain ?? tryGetHostname(rawHref); const citationData: SerializableCitation = { ...serializable, diff --git a/surfsense_web/lib/url.ts b/surfsense_web/lib/url.ts new file mode 100644 index 000000000..0c9227581 --- /dev/null +++ b/surfsense_web/lib/url.ts @@ -0,0 +1,14 @@ +/** + * Extract a normalized hostname from a URL. Strips a leading `www.`. + * Returns `undefined` if the input is not a parseable URL. + * + * This is the canonical replacement for the four previously-duplicated + * `extractDomain` helpers that had subtly different error fallbacks. + */ +export function tryGetHostname(url: string): string | undefined { + try { + return new URL(url).hostname.replace(/^www\./, ""); + } catch { + return undefined; + } +} From cc06cff4fb0054890e9bf52efbfa3345b904c11f Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Sat, 16 May 2026 20:20:04 +0530 Subject: [PATCH 14/16] feat(tests): add mock response for file ownership in composio_module --- .../tests/e2e/fakes/composio_module.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/surfsense_backend/tests/e2e/fakes/composio_module.py b/surfsense_backend/tests/e2e/fakes/composio_module.py index 38c4d4c46..16a93d0f1 100644 --- a/surfsense_backend/tests/e2e/fakes/composio_module.py +++ b/surfsense_backend/tests/e2e/fakes/composio_module.py @@ -350,6 +350,25 @@ def _drive_list_files(args: dict[str, Any]) -> dict[str, Any]: folder id and serve the matching fixture list. """ q = args.get("q", "") + if "in owners" in q: + return { + "data": { + "files": [ + { + "id": "fake-file-owner-probe", + "name": "owner-probe", + "owners": [ + { + "me": True, + "emailAddress": "e2e-fake@surfsense.example", + } + ], + } + ], + "nextPageToken": None, + } + } + folder_id = "root" if "in parents" in q: # q looks like: '' in parents and trashed = false ... From a0f2563dc35158be98f997272a72ed01b9cd2fec Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Sat, 16 May 2026 21:13:17 +0530 Subject: [PATCH 15/16] test: update Stripe and Google Calendar integration tests to use ComposioService --- .../test_stripe_page_purchases.py | 1 + .../test_calendar_indexer_credentials.py | 61 +++++++++++-------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/surfsense_backend/tests/integration/document_upload/test_stripe_page_purchases.py b/surfsense_backend/tests/integration/document_upload/test_stripe_page_purchases.py index 1c8f7f990..143c9e252 100644 --- a/surfsense_backend/tests/integration/document_upload/test_stripe_page_purchases.py +++ b/surfsense_backend/tests/integration/document_upload/test_stripe_page_purchases.py @@ -204,6 +204,7 @@ class TestStripeCheckoutSessionCreation: assert ( fake_client.last_params["success_url"] == f"http://localhost:3000/dashboard/{search_space_id}/purchase-success" + "?session_id={CHECKOUT_SESSION_ID}" ) assert ( fake_client.last_params["cancel_url"] diff --git a/surfsense_backend/tests/integration/google_unification/test_calendar_indexer_credentials.py b/surfsense_backend/tests/integration/google_unification/test_calendar_indexer_credentials.py index 795f0d564..44ff5c48a 100644 --- a/surfsense_backend/tests/integration/google_unification/test_calendar_indexer_credentials.py +++ b/surfsense_backend/tests/integration/google_unification/test_calendar_indexer_credentials.py @@ -7,7 +7,7 @@ mocked at their system boundaries. from __future__ import annotations -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import ANY, AsyncMock, MagicMock, patch import pytest import pytest_asyncio @@ -25,6 +25,7 @@ pytestmark = pytest.mark.integration _COMPOSIO_ACCOUNT_ID = "composio-calendar-test-789" _INDEXER_MODULE = "app.tasks.connector_indexers.google_calendar_indexer" +_GET_ACCESS_TOKEN = "app.services.composio_service.ComposioService.get_access_token" @pytest_asyncio.fixture @@ -69,32 +70,29 @@ async def native_calendar(async_engine): await cleanup_space(async_engine, data["search_space_id"]) +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") @patch(f"{_INDEXER_MODULE}.GoogleCalendarConnector") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") -async def test_composio_calendar_uses_composio_credentials( - mock_build_creds, +@patch(f"{_INDEXER_MODULE}.ComposioService") +async def test_composio_calendar_uses_composio_service( + mock_composio_service_cls, mock_cal_cls, mock_tl_cls, + mock_get_access_token, async_engine, composio_calendar, ): - """Calendar indexer calls build_composio_credentials for a Composio connector.""" + """Calendar indexer uses Composio tools directly for a Composio connector.""" from app.tasks.connector_indexers.google_calendar_indexer import ( index_google_calendar_events, ) data = composio_calendar - mock_creds = MagicMock(name="composio-creds") - mock_build_creds.return_value = mock_creds + mock_composio_service = MagicMock() + mock_composio_service.get_calendar_events = AsyncMock(return_value=([], None)) + mock_composio_service_cls.return_value = mock_composio_service mock_tl_cls.return_value = mock_task_logger() - mock_cal_instance = MagicMock() - mock_cal_instance.get_all_primary_calendar_events = AsyncMock( - return_value=([], None) - ) - mock_cal_cls.return_value = mock_cal_instance - maker = make_session_factory(async_engine) async with maker() as session: await index_google_calendar_events( @@ -104,17 +102,25 @@ async def test_composio_calendar_uses_composio_credentials( user_id=data["user_id"], ) - mock_build_creds.assert_called_once_with(_COMPOSIO_ACCOUNT_ID) - mock_cal_cls.assert_called_once() - _, kwargs = mock_cal_cls.call_args - assert kwargs.get("credentials") is mock_creds + mock_composio_service_cls.assert_called_once() + mock_composio_service.get_calendar_events.assert_called_once_with( + connected_account_id=_COMPOSIO_ACCOUNT_ID, + entity_id=f"surfsense_{data['user_id']}", + time_min=ANY, + time_max=ANY, + max_results=250, + ) + mock_cal_cls.assert_not_called() + mock_get_access_token.assert_not_called() +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") +@patch(f"{_INDEXER_MODULE}.ComposioService") async def test_composio_calendar_without_account_id_returns_error( - mock_build_creds, + mock_composio_service_cls, mock_tl_cls, + mock_get_access_token, async_engine, composio_calendar_no_id, ): @@ -138,20 +144,23 @@ async def test_composio_calendar_without_account_id_returns_error( assert count == 0 assert error is not None assert "composio" in error.lower() - mock_build_creds.assert_not_called() + mock_composio_service_cls.assert_not_called() + mock_get_access_token.assert_not_called() +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") +@patch(f"{_INDEXER_MODULE}.ComposioService") @patch(f"{_INDEXER_MODULE}.GoogleCalendarConnector") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") -async def test_native_calendar_does_not_use_composio_credentials( - mock_build_creds, +async def test_native_calendar_uses_google_calendar_connector( mock_cal_cls, + mock_composio_service_cls, mock_tl_cls, + mock_get_access_token, async_engine, native_calendar, ): - """Calendar indexer does NOT call build_composio_credentials for a native connector.""" + """Native Calendar connector uses GoogleCalendarConnector with no Composio path.""" from app.tasks.connector_indexers.google_calendar_indexer import ( index_google_calendar_events, ) @@ -174,4 +183,6 @@ async def test_native_calendar_does_not_use_composio_credentials( user_id=data["user_id"], ) - mock_build_creds.assert_not_called() + mock_cal_cls.assert_called_once() + mock_composio_service_cls.assert_not_called() + mock_get_access_token.assert_not_called() From cb9a0f327caa8b2bc3a5e7e40f737c22a77a1823 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Sat, 16 May 2026 21:26:40 +0530 Subject: [PATCH 16/16] test: refactor Gmail indexer tests to utilize ComposioService and hybrid chunking --- .../tests/integration/conftest.py | 4 ++ .../test_gmail_indexer_credentials.py | 62 ++++++++++++------- .../adapters/test_file_upload_adapter.py | 2 +- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/surfsense_backend/tests/integration/conftest.py b/surfsense_backend/tests/integration/conftest.py index 2f4b3fe9a..e03101e63 100644 --- a/surfsense_backend/tests/integration/conftest.py +++ b/surfsense_backend/tests/integration/conftest.py @@ -160,6 +160,10 @@ def patched_chunk_text(monkeypatch) -> MagicMock: "app.indexing_pipeline.indexing_pipeline_service.chunk_text", mock, ) + monkeypatch.setattr( + "app.indexing_pipeline.indexing_pipeline_service.chunk_text_hybrid", + mock, + ) return mock diff --git a/surfsense_backend/tests/integration/google_unification/test_gmail_indexer_credentials.py b/surfsense_backend/tests/integration/google_unification/test_gmail_indexer_credentials.py index afb3e64c3..b869f5607 100644 --- a/surfsense_backend/tests/integration/google_unification/test_gmail_indexer_credentials.py +++ b/surfsense_backend/tests/integration/google_unification/test_gmail_indexer_credentials.py @@ -7,7 +7,7 @@ mocked at their system boundaries. from __future__ import annotations -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import ANY, AsyncMock, MagicMock, patch import pytest import pytest_asyncio @@ -25,6 +25,7 @@ pytestmark = pytest.mark.integration _COMPOSIO_ACCOUNT_ID = "composio-gmail-test-456" _INDEXER_MODULE = "app.tasks.connector_indexers.google_gmail_indexer" +_GET_ACCESS_TOKEN = "app.services.composio_service.ComposioService.get_access_token" @pytest_asyncio.fixture @@ -69,30 +70,32 @@ async def native_gmail(async_engine): await cleanup_space(async_engine, data["search_space_id"]) +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") @patch(f"{_INDEXER_MODULE}.GoogleGmailConnector") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") -async def test_composio_gmail_uses_composio_credentials( - mock_build_creds, +@patch(f"{_INDEXER_MODULE}.ComposioService") +async def test_composio_gmail_uses_composio_service( + mock_composio_service_cls, mock_gmail_cls, mock_tl_cls, + mock_get_access_token, async_engine, composio_gmail, ): - """Gmail indexer calls build_composio_credentials for a Composio connector.""" + """Gmail indexer uses Composio tools directly for a Composio connector.""" from app.tasks.connector_indexers.google_gmail_indexer import ( index_google_gmail_messages, ) data = composio_gmail - mock_creds = MagicMock(name="composio-creds") - mock_build_creds.return_value = mock_creds + mock_composio_service = MagicMock() + mock_composio_service.get_gmail_messages = AsyncMock( + return_value=([], None, None, None) + ) + mock_composio_service.get_gmail_message_detail = AsyncMock(return_value=({}, None)) + mock_composio_service_cls.return_value = mock_composio_service mock_tl_cls.return_value = mock_task_logger() - mock_gmail_instance = MagicMock() - mock_gmail_instance.get_recent_messages = AsyncMock(return_value=([], None)) - mock_gmail_cls.return_value = mock_gmail_instance - maker = make_session_factory(async_engine) async with maker() as session: await index_google_gmail_messages( @@ -102,17 +105,25 @@ async def test_composio_gmail_uses_composio_credentials( user_id=data["user_id"], ) - mock_build_creds.assert_called_once_with(_COMPOSIO_ACCOUNT_ID) - mock_gmail_cls.assert_called_once() - args, _ = mock_gmail_cls.call_args - assert args[0] is mock_creds + mock_composio_service_cls.assert_called_once() + mock_composio_service.get_gmail_messages.assert_called_once_with( + connected_account_id=_COMPOSIO_ACCOUNT_ID, + entity_id=f"surfsense_{data['user_id']}", + query=ANY, + max_results=ANY, + page_token=None, + ) + mock_gmail_cls.assert_not_called() + mock_get_access_token.assert_not_called() +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") +@patch(f"{_INDEXER_MODULE}.ComposioService") async def test_composio_gmail_without_account_id_returns_error( - mock_build_creds, + mock_composio_service_cls, mock_tl_cls, + mock_get_access_token, async_engine, composio_gmail_no_id, ): @@ -136,20 +147,23 @@ async def test_composio_gmail_without_account_id_returns_error( assert count == 0 assert error is not None assert "composio" in error.lower() - mock_build_creds.assert_not_called() + mock_composio_service_cls.assert_not_called() + mock_get_access_token.assert_not_called() +@patch(_GET_ACCESS_TOKEN) @patch(f"{_INDEXER_MODULE}.TaskLoggingService") +@patch(f"{_INDEXER_MODULE}.ComposioService") @patch(f"{_INDEXER_MODULE}.GoogleGmailConnector") -@patch(f"{_INDEXER_MODULE}.build_composio_credentials") -async def test_native_gmail_does_not_use_composio_credentials( - mock_build_creds, +async def test_native_gmail_uses_google_gmail_connector( mock_gmail_cls, + mock_composio_service_cls, mock_tl_cls, + mock_get_access_token, async_engine, native_gmail, ): - """Gmail indexer does NOT call build_composio_credentials for a native connector.""" + """Native Gmail connector uses GoogleGmailConnector with no Composio path.""" from app.tasks.connector_indexers.google_gmail_indexer import ( index_google_gmail_messages, ) @@ -170,4 +184,6 @@ async def test_native_gmail_does_not_use_composio_credentials( user_id=data["user_id"], ) - mock_build_creds.assert_not_called() + mock_gmail_cls.assert_called_once() + mock_composio_service_cls.assert_not_called() + mock_get_access_token.assert_not_called() diff --git a/surfsense_backend/tests/integration/indexing_pipeline/adapters/test_file_upload_adapter.py b/surfsense_backend/tests/integration/indexing_pipeline/adapters/test_file_upload_adapter.py index 9fc802aa6..6bb1d2094 100644 --- a/surfsense_backend/tests/integration/indexing_pipeline/adapters/test_file_upload_adapter.py +++ b/surfsense_backend/tests/integration/indexing_pipeline/adapters/test_file_upload_adapter.py @@ -200,7 +200,7 @@ async def test_reindex_sets_status_ready(db_session, db_search_space, db_user, m async def test_reindex_replaces_chunks(db_session, db_search_space, db_user, mocker): """Reindexing replaces old chunks with new content rather than appending.""" mocker.patch( - "app.indexing_pipeline.indexing_pipeline_service.chunk_text", + "app.indexing_pipeline.indexing_pipeline_service.chunk_text_hybrid", side_effect=[["Original chunk."], ["Updated chunk."]], )