diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7a4e5c2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +.env +dist +Dockerfile +.git +.gitignore \ No newline at end of file diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 7272b08..27f5559 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -19,7 +19,13 @@ jobs: steps: - uses: actions/checkout@v4 - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 + - name: Resolve pnpm store path + id: pnpm-store-path + run: | + echo "PNPM_STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup Docker Buildx + id: setup-buildx + uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v2 with: @@ -27,6 +33,26 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/cache@v4 + with: + path: | + ${{ steps.pnpm-store-path.outputs.PNPM_STORE_PATH }} + # Generate a new cache whenever packages or source files change. + key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }} + # If source files changed but packages didn't, rebuild from a prior cache. + restore-keys: | + ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.json') }}- + + - name: Restore Docker cache mounts + uses: reproducible-containers/buildkit-cache-dance@v3 + with: + builder: ${{ steps.setup-buildx.outputs.name }} + dockerfile: Dockerfile + cache-map: | + { + "${{ steps.pnpm-store-path.outputs.PNPM_STORE_PATH }}": "/pnpm/store", + } + - name: Build the Docker image uses: docker/build-push-action@v5 with: @@ -34,3 +60,7 @@ jobs: platforms: linux/amd64 push: true tags: ghcr.io/polinetworkorg/telegram:latest + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILDKIT_INLINE_CACHE=1 diff --git a/Dockerfile b/Dockerfile index 8962801..58e7b47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,25 @@ -FROM node:22-alpine AS base +FROM node:24-alpine AS base ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable -COPY . /app WORKDIR /app +COPY package.json ./ + +# Fetch the correct pnpm version without installing deps +# This reads the "packageManager" field and downloads that pnpm version +RUN corepack prepare --activate $(node -p "require('./package.json').packageManager") +RUN pnpm --version + FROM base AS prod-deps +COPY package.json pnpm-*.yaml ./ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile FROM base AS build +COPY --from=prod-deps /app/node_modules /app/node_modules +COPY . . + +# Install all dependencies (including dev) for building the project RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile RUN pnpm run build diff --git a/package.json b/package.json index ebd05de..927844f 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "build": "tsup", "dev:raw": "NODE_ENV=development tsx watch --clear-screen=false --env-file=.env src/bot.ts", "dev": "pnpm run dev:raw | pino-pretty", - "test": "vitest", - "typecheck": "tsc --noEmit", + "test": "vitest run", + "typecheck": "tsgo --noEmit", "check": "biome check", "check:fix": "biome check --write --unsafe" }, @@ -21,14 +21,14 @@ "devDependencies": { "@biomejs/biome": "2.3.11", "@trpc/server": "11.5.1", - "@types/node": "^22.13.1", - "globals": "^15.14.0", + "@types/node": "^24.12.2", + "@typescript/native-preview": "7.0.0-dev.20260421.2", "pino-pretty": "^13.0.0", "ts-node": "^10.9.2", "tsup": "^8.4.0", "tsx": "^4.19.3", - "typescript": "^5.7.3", - "vitest": "^3.1.1" + "typescript": "^6.0.3", + "vitest": "^4.1.5" }, "dependencies": { "@grammyjs/auto-retry": "^2.0.2", @@ -44,12 +44,11 @@ "@trpc/client": "^11.5.1", "@types/ssdeep.js": "^0.0.2", "bullmq": "^5.59.0", - "croner": "^9.0.0", + "croner": "^10.0.1", "grammy": "^1.37.0", "nanoid": "^5.1.5", "neverthrow": "^8.2.0", - "openai": "^4.102.0", - "pino": "^9.6.0", + "pino": "^10.3.1", "redis": "^4.7.0", "secure-json-parse": "^4.0.0", "socket.io-client": "^4.8.1", @@ -60,7 +59,7 @@ "packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a", "engines": { "npm": ">=10.9.2", - "node": ">=22.14.0" + "node": ">=24.0.0" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4ef934..a7930fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,10 +37,10 @@ importers: version: 0.1.0 '@t3-oss/env-core': specifier: ^0.13.4 - version: 0.13.4(arktype@2.1.20)(typescript@5.7.3)(zod@4.1.11) + version: 0.13.4(arktype@2.1.20)(typescript@6.0.3)(zod@4.1.11) '@trpc/client': specifier: ^11.5.1 - version: 11.5.1(@trpc/server@11.5.1(typescript@5.7.3))(typescript@5.7.3) + version: 11.5.1(@trpc/server@11.5.1(typescript@6.0.3))(typescript@6.0.3) '@types/ssdeep.js': specifier: ^0.0.2 version: 0.0.2 @@ -48,8 +48,8 @@ importers: specifier: ^5.59.0 version: 5.59.0 croner: - specifier: ^9.0.0 - version: 9.0.0 + specifier: ^10.0.1 + version: 10.0.1 grammy: specifier: ^1.37.0 version: 1.37.0 @@ -59,15 +59,12 @@ importers: neverthrow: specifier: ^8.2.0 version: 8.2.0 - openai: - specifier: ^4.102.0 - version: 4.102.0(zod@4.1.11) pino: - specifier: ^9.6.0 - version: 9.6.0 + specifier: ^10.3.1 + version: 10.3.1 redis: specifier: ^4.7.0 - version: 4.7.0 + version: 4.7.1 secure-json-parse: specifier: ^4.0.0 version: 4.0.0 @@ -89,31 +86,31 @@ importers: version: 2.3.11 '@trpc/server': specifier: 11.5.1 - version: 11.5.1(typescript@5.7.3) + version: 11.5.1(typescript@6.0.3) '@types/node': - specifier: ^22.13.1 - version: 22.13.1 - globals: - specifier: ^15.14.0 - version: 15.14.0 + specifier: ^24.12.2 + version: 24.12.2 + '@typescript/native-preview': + specifier: 7.0.0-dev.20260421.2 + version: 7.0.0-dev.20260421.2 pino-pretty: specifier: ^13.0.0 version: 13.0.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.13.1)(typescript@5.7.3) + version: 10.9.2(@types/node@24.12.2)(typescript@6.0.3) tsup: specifier: ^8.4.0 - version: 8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3) + version: 8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@6.0.3) tsx: specifier: ^4.19.3 version: 4.19.3 typescript: - specifier: ^5.7.3 - version: 5.7.3 + specifier: ^6.0.3 + version: 6.0.3 vitest: - specifier: ^3.1.1 - version: 3.1.1(@types/node@22.13.1)(tsx@4.19.3) + specifier: ^4.1.5 + version: 4.1.5(@types/node@24.12.2)(vite@6.4.2(@types/node@24.12.2)(tsx@4.19.3)) packages: @@ -394,6 +391,9 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -430,6 +430,9 @@ packages: cpu: [x64] os: [win32] + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -442,8 +445,8 @@ packages: peerDependencies: '@redis/client': ^1.0.0 - '@redis/client@1.6.0': - resolution: {integrity: sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==} + '@redis/client@1.6.1': + resolution: {integrity: sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==} engines: {node: '>=14'} '@redis/graph@1.1.1': @@ -603,6 +606,9 @@ packages: resolution: {integrity: sha512-UODtNxJ9zrQKDy7SE0bsbaGoCUqwDZQd5KkOLhi3SugniNUH2FMUP7q3niLMePFlh55F4sZ8gWkRylT5+852Ig==} engines: {node: '>=10.0.0'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@t3-oss/env-core@0.13.4': resolution: {integrity: sha512-zVOiYO0+CF7EnBScz8s0O5JnJLPTU0lrUi8qhKXfIxIJXvI/jcppSiXXsEJwfB4A6XZawY/Wg/EQGKANi/aPmQ==} peerDependencies: @@ -641,52 +647,88 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node-fetch@2.6.12': - resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} - - '@types/node@18.19.103': - resolution: {integrity: sha512-hHTHp+sEz6SxFsp+SA+Tqrua3AbmlAw+Y//aEwdHrdZkYVRWdvWD3y5uPZ0flYOkgskaFWqZ/YGFm3FaFQ0pRw==} - - '@types/node@22.13.1': - resolution: {integrity: sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==} + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} '@types/ssdeep.js@0.0.2': resolution: {integrity: sha512-WSmAg2j7lIuETBTlos0erBWeL9C8nLe8rF5IydmHkhD8w64gyrbALINtXS+i0qJv6p0fEDRkNYLLC9KGderQJw==} - '@vitest/expect@3.1.1': - resolution: {integrity: sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==} + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw==} + cpu: [arm64] + os: [darwin] + + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg==} + cpu: [x64] + os: [darwin] + + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w==} + cpu: [arm64] + os: [linux] + + '@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww==} + cpu: [arm] + os: [linux] + + '@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw==} + cpu: [x64] + os: [linux] + + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ==} + cpu: [arm64] + os: [win32] + + '@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg==} + cpu: [x64] + os: [win32] + + '@typescript/native-preview@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg==} + hasBin: true + + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} - '@vitest/mocker@3.1.1': - resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==} + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.1.1': - resolution: {integrity: sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==} + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} - '@vitest/runner@3.1.1': - resolution: {integrity: sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==} + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} - '@vitest/snapshot@3.1.1': - resolution: {integrity: sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==} + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} - '@vitest/spy@3.1.1': - resolution: {integrity: sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==} + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} - '@vitest/utils@3.1.1': - resolution: {integrity: sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==} + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -701,10 +743,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agentkeepalive@4.6.0: - resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} - engines: {node: '>= 8.0.0'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -734,9 +772,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -760,17 +795,9 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - chai@5.2.0: - resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} - engines: {node: '>=12'} - - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} chokidar@4.0.3: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} @@ -790,10 +817,6 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -802,6 +825,9 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + copy-anything@3.0.5: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} @@ -813,8 +839,8 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} - croner@9.0.0: - resolution: {integrity: sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==} + croner@10.0.1: + resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==} engines: {node: '>=18.0'} cross-spawn@7.0.6: @@ -851,14 +877,6 @@ packages: supports-color: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -874,10 +892,6 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -897,24 +911,8 @@ packages: resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} engines: {node: '>=10.0.0'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} esbuild@0.25.1: resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} @@ -928,17 +926,13 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - expect-type@1.2.1: - resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} fast-copy@3.0.2: resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} - fast-redact@3.5.0: - resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} - engines: {node: '>=6'} - fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} @@ -963,37 +957,15 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data-encoder@1.7.2: - resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} - - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} - engines: {node: '>= 6'} - - formdata-node@4.4.1: - resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} - engines: {node: '>= 12.20'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - generic-pool@3.9.0: resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} engines: {node: '>= 4'} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - get-tsconfig@4.10.0: resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} @@ -1002,36 +974,13 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - globals@15.14.0: - resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} - engines: {node: '>=18'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - grammy@1.37.0: resolution: {integrity: sha512-UBGqGKux+49t1vm7n/m1BaeXIYbWESXjhaFxG+9z33VTLSHdQJwIOmpNKmZSaoBlSWbAJE+IJZ30X7RfWvEolA==} engines: {node: ^12.20.0 || >=14.13.1} - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - ioredis@5.8.0: resolution: {integrity: sha512-AUXbKn9gvo9hHKvk6LbZJQSKn/qIfkWXrnsyL9Yrf+oeXmla9Nmf6XEumOddyhM8neynpK5oAV6r9r99KBuwzA==} engines: {node: '>=12.22.0'} @@ -1074,9 +1023,6 @@ packages: lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - loupe@3.1.3: - resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1084,24 +1030,12 @@ packages: resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - minimatch@9.0.9: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} @@ -1143,11 +1077,6 @@ packages: node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - deprecated: Use your platform's native DOMException instead - node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -1165,6 +1094,9 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -1172,18 +1104,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - openai@4.102.0: - resolution: {integrity: sha512-CWk15CMhPSHNZnjz+6rwVYV551xaC8CwOd7/zxImrC1btEo37dX/Ii5tBKWfqqxqyzpJ6p3Y4bICzzKhW03WhQ==} - hasBin: true - peerDependencies: - ws: ^8.18.0 - zod: ^3.23.8 - peerDependenciesMeta: - ws: - optional: true - zod: - optional: true - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -1198,10 +1118,6 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.0: - resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} - engines: {node: '>= 14.16'} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1212,6 +1128,9 @@ packages: pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + pino-pretty@13.0.0: resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==} hasBin: true @@ -1219,8 +1138,8 @@ packages: pino-std-serializers@7.0.0: resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@9.6.0: - resolution: {integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==} + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} hasBin: true pirates@4.0.7: @@ -1249,8 +1168,8 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} - process-warning@4.0.1: - resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -1278,8 +1197,8 @@ packages: resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} engines: {node: '>=4'} - redis@4.7.0: - resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==} + redis@4.7.1: + resolution: {integrity: sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==} resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} @@ -1356,8 +1275,8 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - std-env@3.9.0: - resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -1395,8 +1314,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thread-stream@3.1.0: - resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + thread-stream@4.0.0: + resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} + engines: {node: '>=20'} tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -1404,6 +1324,10 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.1.1: + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + engines: {node: '>=18'} + tinyglobby@0.2.12: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} @@ -1412,16 +1336,8 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} tr46@0.0.3: @@ -1478,16 +1394,13 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} hasBin: true - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} @@ -1496,11 +1409,6 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - vite-node@3.1.1: - resolution: {integrity: sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - vite@6.4.2: resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -1541,26 +1449,39 @@ packages: yaml: optional: true - vitest@3.1.1: - resolution: {integrity: sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.1.1 - '@vitest/ui': 3.1.1 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@opentelemetry/api': optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -1569,10 +1490,6 @@ packages: jsdom: optional: true - web-streams-polyfill@4.0.0-beta.3: - resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} - engines: {node: '>= 14'} - webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -1810,6 +1727,8 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -1838,36 +1757,38 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': optional: true + '@pinojs/redact@0.4.0': {} + '@pkgjs/parseargs@0.11.0': optional: true '@polinetwork/backend@0.15.18': {} - '@redis/bloom@1.2.0(@redis/client@1.6.0)': + '@redis/bloom@1.2.0(@redis/client@1.6.1)': dependencies: - '@redis/client': 1.6.0 + '@redis/client': 1.6.1 - '@redis/client@1.6.0': + '@redis/client@1.6.1': dependencies: cluster-key-slot: 1.1.2 generic-pool: 3.9.0 yallist: 4.0.0 - '@redis/graph@1.1.1(@redis/client@1.6.0)': + '@redis/graph@1.1.1(@redis/client@1.6.1)': dependencies: - '@redis/client': 1.6.0 + '@redis/client': 1.6.1 - '@redis/json@1.0.7(@redis/client@1.6.0)': + '@redis/json@1.0.7(@redis/client@1.6.1)': dependencies: - '@redis/client': 1.6.0 + '@redis/client': 1.6.1 - '@redis/search@1.2.0(@redis/client@1.6.0)': + '@redis/search@1.2.0(@redis/client@1.6.1)': dependencies: - '@redis/client': 1.6.0 + '@redis/client': 1.6.1 - '@redis/time-series@1.1.0(@redis/client@1.6.0)': + '@redis/time-series@1.1.0(@redis/client@1.6.1)': dependencies: - '@redis/client': 1.6.0 + '@redis/client': 1.6.1 '@rollup/rollup-android-arm-eabi@4.60.1': optional: true @@ -1957,21 +1878,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@t3-oss/env-core@0.13.4(arktype@2.1.20)(typescript@5.7.3)(zod@4.1.11)': + '@standard-schema/spec@1.1.0': {} + + '@t3-oss/env-core@0.13.4(arktype@2.1.20)(typescript@6.0.3)(zod@4.1.11)': dependencies: arktype: 2.1.20 optionalDependencies: - typescript: 5.7.3 + typescript: 6.0.3 zod: 4.1.11 - '@trpc/client@11.5.1(@trpc/server@11.5.1(typescript@5.7.3))(typescript@5.7.3)': + '@trpc/client@11.5.1(@trpc/server@11.5.1(typescript@6.0.3))(typescript@6.0.3)': dependencies: - '@trpc/server': 11.5.1(typescript@5.7.3) - typescript: 5.7.3 + '@trpc/server': 11.5.1(typescript@6.0.3) + typescript: 6.0.3 - '@trpc/server@11.5.1(typescript@5.7.3)': + '@trpc/server@11.5.1(typescript@6.0.3)': dependencies: - typescript: 5.7.3 + typescript: 6.0.3 '@tsconfig/node10@1.0.11': {} @@ -1981,64 +1904,92 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@types/estree@1.0.6': {} + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} - '@types/node-fetch@2.6.12': + '@types/node@24.12.2': dependencies: - '@types/node': 22.13.1 - form-data: 4.0.4 + undici-types: 7.16.0 - '@types/node@18.19.103': - dependencies: - undici-types: 5.26.5 + '@types/ssdeep.js@0.0.2': {} - '@types/node@22.13.1': - dependencies: - undici-types: 6.20.0 + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2': + optional: true - '@types/ssdeep.js@0.0.2': {} + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2': + optional: true - '@vitest/expect@3.1.1': - dependencies: - '@vitest/spy': 3.1.1 - '@vitest/utils': 3.1.1 - chai: 5.2.0 - tinyrainbow: 2.0.0 + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2': + optional: true - '@vitest/mocker@3.1.1(vite@6.4.2(@types/node@22.13.1)(tsx@4.19.3))': - dependencies: - '@vitest/spy': 3.1.1 + '@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2': + optional: true + + '@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2': + optional: true + + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2': + optional: true + + '@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2': + optional: true + + '@typescript/native-preview@7.0.0-dev.20260421.2': + optionalDependencies: + '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-arm': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-x64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-win32-x64': 7.0.0-dev.20260421.2 + + '@vitest/expect@4.1.5': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.5(vite@6.4.2(@types/node@24.12.2)(tsx@4.19.3))': + dependencies: + '@vitest/spy': 4.1.5 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.21 optionalDependencies: - vite: 6.4.2(@types/node@22.13.1)(tsx@4.19.3) + vite: 6.4.2(@types/node@24.12.2)(tsx@4.19.3) - '@vitest/pretty-format@3.1.1': + '@vitest/pretty-format@4.1.5': dependencies: - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.0 - '@vitest/runner@3.1.1': + '@vitest/runner@4.1.5': dependencies: - '@vitest/utils': 3.1.1 + '@vitest/utils': 4.1.5 pathe: 2.0.3 - '@vitest/snapshot@3.1.1': + '@vitest/snapshot@4.1.5': dependencies: - '@vitest/pretty-format': 3.1.1 - magic-string: 0.30.17 + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 + magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.1.1': - dependencies: - tinyspy: 3.0.2 + '@vitest/spy@4.1.5': {} - '@vitest/utils@3.1.1': + '@vitest/utils@4.1.5': dependencies: - '@vitest/pretty-format': 3.1.1 - loupe: 3.1.3 - tinyrainbow: 2.0.0 + '@vitest/pretty-format': 4.1.5 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 abort-controller@3.0.0: dependencies: @@ -2050,10 +2001,6 @@ snapshots: acorn@8.14.0: {} - agentkeepalive@4.6.0: - dependencies: - humanize-ms: 1.2.1 - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -2075,8 +2022,6 @@ snapshots: assertion-error@2.0.1: {} - asynckit@0.4.0: {} - atomic-sleep@1.0.0: {} balanced-match@1.0.2: {} @@ -2104,20 +2049,7 @@ snapshots: cac@6.7.14: {} - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - chai@5.2.0: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.1.3 - pathval: 2.0.0 - - check-error@2.1.1: {} + chai@6.2.2: {} chokidar@4.0.3: dependencies: @@ -2133,14 +2065,12 @@ snapshots: colorette@2.0.20: {} - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - commander@4.1.1: {} consola@3.4.2: {} + convert-source-map@2.0.0: {} + copy-anything@3.0.5: dependencies: is-what: 4.1.16 @@ -2151,7 +2081,7 @@ snapshots: dependencies: luxon: 3.7.2 - croner@9.0.0: {} + croner@10.0.1: {} cross-spawn@7.0.6: dependencies: @@ -2173,10 +2103,6 @@ snapshots: dependencies: ms: 2.1.3 - deep-eql@5.0.2: {} - - delayed-stream@1.0.0: {} - denque@2.1.0: {} detect-libc@2.1.1: @@ -2186,12 +2112,6 @@ snapshots: diff@4.0.2: {} - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - eastasianwidth@0.2.0: {} emoji-regex@8.0.0: {} @@ -2216,22 +2136,7 @@ snapshots: engine.io-parser@5.2.3: {} - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@1.6.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 + es-module-lexer@2.1.0: {} esbuild@0.25.1: optionalDependencies: @@ -2263,16 +2168,14 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 event-target-shim@5.0.1: {} - expect-type@1.2.1: {} + expect-type@1.3.0: {} fast-copy@3.0.2: {} - fast-redact@3.5.0: {} - fast-safe-stringify@2.1.1: {} fdir@6.4.3(picomatch@4.0.4): @@ -2288,46 +2191,11 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data-encoder@1.7.2: {} - - form-data@4.0.4: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - formdata-node@4.4.1: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 4.0.0-beta.3 - fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - generic-pool@3.9.0: {} - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -2341,10 +2209,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - globals@15.14.0: {} - - gopd@1.2.0: {} - grammy@1.37.0: dependencies: '@grammyjs/types': 3.21.0 @@ -2355,22 +2219,8 @@ snapshots: - encoding - supports-color - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - help-me@5.0.0: {} - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - ioredis@5.8.0: dependencies: '@ioredis/commands': 1.4.0 @@ -2411,26 +2261,16 @@ snapshots: lodash.sortby@4.7.0: {} - loupe@3.1.3: {} - lru-cache@10.4.3: {} luxon@3.7.2: {} - magic-string@0.30.17: + magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 make-error@1.3.6: {} - math-intrinsics@1.1.0: {} - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - minimatch@9.0.9: dependencies: brace-expansion: 2.0.2 @@ -2473,8 +2313,6 @@ snapshots: node-abort-controller@3.1.1: {} - node-domexception@1.0.0: {} - node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -2486,26 +2324,14 @@ snapshots: object-assign@4.1.1: {} + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} once@1.4.0: dependencies: wrappy: 1.0.2 - openai@4.102.0(zod@4.1.11): - dependencies: - '@types/node': 18.19.103 - '@types/node-fetch': 2.6.12 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0 - optionalDependencies: - zod: 4.1.11 - transitivePeerDependencies: - - encoding - package-json-from-dist@1.0.1: {} path-key@3.1.1: {} @@ -2517,8 +2343,6 @@ snapshots: pathe@2.0.3: {} - pathval@2.0.0: {} - picocolors@1.1.1: {} picomatch@4.0.4: {} @@ -2527,6 +2351,10 @@ snapshots: dependencies: split2: 4.2.0 + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + pino-pretty@13.0.0: dependencies: colorette: 2.0.20 @@ -2545,19 +2373,19 @@ snapshots: pino-std-serializers@7.0.0: {} - pino@9.6.0: + pino@10.3.1: dependencies: + '@pinojs/redact': 0.4.0 atomic-sleep: 1.0.0 - fast-redact: 3.5.0 on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 + pino-abstract-transport: 3.0.0 pino-std-serializers: 7.0.0 - process-warning: 4.0.1 + process-warning: 5.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.5.0 sonic-boom: 4.2.0 - thread-stream: 3.1.0 + thread-stream: 4.0.0 pirates@4.0.7: {} @@ -2574,7 +2402,7 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - process-warning@4.0.1: {} + process-warning@5.0.0: {} pump@3.0.2: dependencies: @@ -2595,14 +2423,14 @@ snapshots: dependencies: redis-errors: 1.2.0 - redis@4.7.0: + redis@4.7.1: dependencies: - '@redis/bloom': 1.2.0(@redis/client@1.6.0) - '@redis/client': 1.6.0 - '@redis/graph': 1.1.1(@redis/client@1.6.0) - '@redis/json': 1.0.7(@redis/client@1.6.0) - '@redis/search': 1.2.0(@redis/client@1.6.0) - '@redis/time-series': 1.1.0(@redis/client@1.6.0) + '@redis/bloom': 1.2.0(@redis/client@1.6.1) + '@redis/client': 1.6.1 + '@redis/graph': 1.1.1(@redis/client@1.6.1) + '@redis/json': 1.0.7(@redis/client@1.6.1) + '@redis/search': 1.2.0(@redis/client@1.6.1) + '@redis/time-series': 1.1.0(@redis/client@1.6.1) resolve-from@5.0.0: {} @@ -2693,7 +2521,7 @@ snapshots: standard-as-callback@2.1.0: {} - std-env@3.9.0: {} + std-env@4.1.0: {} string-width@4.2.3: dependencies: @@ -2739,7 +2567,7 @@ snapshots: dependencies: any-promise: 1.3.0 - thread-stream@3.1.0: + thread-stream@4.0.0: dependencies: real-require: 0.2.0 @@ -2747,6 +2575,8 @@ snapshots: tinyexec@0.3.2: {} + tinyexec@1.1.1: {} + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.4) @@ -2757,11 +2587,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinypool@1.0.2: {} - - tinyrainbow@2.0.0: {} - - tinyspy@3.0.2: {} + tinyrainbow@3.1.0: {} tr46@0.0.3: {} @@ -2773,27 +2599,27 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@22.13.1)(typescript@5.7.3): + ts-node@10.9.2(@types/node@24.12.2)(typescript@6.0.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.13.1 + '@types/node': 24.12.2 acorn: 8.14.0 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.7.3 + typescript: 6.0.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 tslib@2.8.1: {} - tsup@8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3): + tsup@8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@6.0.3): dependencies: bundle-require: 5.1.0(esbuild@0.25.1) cac: 6.7.14 @@ -2813,7 +2639,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.3 - typescript: 5.7.3 + typescript: 6.0.3 transitivePeerDependencies: - jiti - supports-color @@ -2827,38 +2653,15 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - typescript@5.7.3: {} + typescript@6.0.3: {} - undici-types@5.26.5: {} - - undici-types@6.20.0: {} + undici-types@7.16.0: {} uuid@11.1.0: {} v8-compile-cache-lib@3.0.1: {} - vite-node@3.1.1(@types/node@22.13.1)(tsx@4.19.3): - dependencies: - cac: 6.7.14 - debug: 4.4.0 - es-module-lexer: 1.6.0 - pathe: 2.0.3 - vite: 6.4.2(@types/node@22.13.1)(tsx@4.19.3) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@6.4.2(@types/node@22.13.1)(tsx@4.19.3): + vite@6.4.2(@types/node@24.12.2)(tsx@4.19.3): dependencies: esbuild: 0.25.1 fdir: 6.5.0(picomatch@4.0.4) @@ -2867,49 +2670,36 @@ snapshots: rollup: 4.60.1 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.13.1 + '@types/node': 24.12.2 fsevents: 2.3.3 tsx: 4.19.3 - vitest@3.1.1(@types/node@22.13.1)(tsx@4.19.3): - dependencies: - '@vitest/expect': 3.1.1 - '@vitest/mocker': 3.1.1(vite@6.4.2(@types/node@22.13.1)(tsx@4.19.3)) - '@vitest/pretty-format': 3.1.1 - '@vitest/runner': 3.1.1 - '@vitest/snapshot': 3.1.1 - '@vitest/spy': 3.1.1 - '@vitest/utils': 3.1.1 - chai: 5.2.0 - debug: 4.4.0 - expect-type: 1.2.1 - magic-string: 0.30.17 + vitest@4.1.5(@types/node@24.12.2)(vite@6.4.2(@types/node@24.12.2)(tsx@4.19.3)): + dependencies: + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@6.4.2(@types/node@24.12.2)(tsx@4.19.3)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 pathe: 2.0.3 - std-env: 3.9.0 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.0.2 - tinyrainbow: 2.0.0 - vite: 6.4.2(@types/node@22.13.1)(tsx@4.19.3) - vite-node: 3.1.1(@types/node@22.13.1)(tsx@4.19.3) + tinyexec: 1.1.1 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 6.4.2(@types/node@24.12.2)(tsx@4.19.3) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.13.1 + '@types/node': 24.12.2 transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - web-streams-polyfill@4.0.0-beta.3: {} webidl-conversions@3.0.1: {} diff --git a/src/middlewares/auto-moderation-stack/ai-moderation.ts b/src/middlewares/auto-moderation-stack/ai-moderation.ts deleted file mode 100644 index 8c6a1c8..0000000 --- a/src/middlewares/auto-moderation-stack/ai-moderation.ts +++ /dev/null @@ -1,139 +0,0 @@ -import type { Filter } from "grammy" -import OpenAI from "openai" -import { env } from "@/env" -import { logger } from "@/logger" -import { getText } from "@/utils/messages" -import type { Context } from "@/utils/types" -import { Awaiter } from "@/utils/wait" -import { DELETION_THRESHOLDS } from "./constants" -import type { Category, FlaggedCategory, ModerationCandidate, ModerationResult } from "./types" - -/** - * # AI Moderation - * ### *Look ma, I'm doing AI!* - * - * Uses OpenAI's free Moderation API to check messages for harmful content. - * - * Checks will be batched every 10 seconds to avoid hitting rate limits. - * Checks both text and images (via URL) if present in the message. - * - * The bot will determine what to do with the results of the call based on - * predefined thresholds. See {@link [DELETION_THRESHOLDS](./constants.ts)} - * - * More info on the API here: https://platform.openai.com/docs/guides/moderation - */ -export class AIModeration { - /** - * Takes each category, and for the flagged ones takes the score (highest among related results) and - * confronts it with predefined thresholds - * - * @param results The array of results as provided by OpenAI's API - * @returns An array of {@link FlaggedCategory} containing each category that was flagged by OpenAI - */ - static parseFlaggedCategories(results: ModerationResult[]): FlaggedCategory[] { - if (results.length === 0) return [] - const categories = new Set( - results - .map((result) => result.categories) - .reduce((acc, curr) => { - Object.keys(curr).forEach((key) => { - const k = key as Category - if (curr[k]) acc.push(k) - }) - return acc - }, []) - ) - const scores = results - .map((result) => result.category_scores) - .reduce>((acc, curr) => { - Object.keys(curr).forEach((key) => { - const k = key as Category - acc[k] = Math.max(acc[k], curr[k]) - }) - return acc - }, results[0].category_scores) - return Array.from(categories).map((category) => ({ - category, - score: scores[category], - aboveThreshold: DELETION_THRESHOLDS[category] ? scores[category] >= DELETION_THRESHOLDS[category] : false, - })) - } - - private client: OpenAI | null - private checkQueue: ModerationCandidate[] = [] - private timeout: NodeJS.Timeout | null = null - private responseAwaiter: Awaiter = new Awaiter() - - constructor() { - this.client = env.OPENAI_API_KEY ? new OpenAI({ apiKey: env.OPENAI_API_KEY }) : null - this.responseAwaiter.resolve([]) // initialize it as resolved with empty results - - if (!this.client) logger.warn("[AI Mod] Missing env OPENAI_API_KEY, automatic moderation will not work.") - else logger.debug("[AI Mod] OpenAI client initialized for moderation.") - } - - /** - * Triggers a moderation check for the queued messages. - * - * Called by a timeout after pushing an element in the queue - */ - private triggerCheck() { - if (!this.client) return - if (this.checkQueue.length === 0) return - - this.responseAwaiter = new Awaiter() // reset the awaiter for the next batch - const candidates = this.checkQueue.splice(0, this.checkQueue.length) - - void this.client.moderations - .create({ input: candidates, model: "omni-moderation-latest" }) - .then((response) => { - this.responseAwaiter.resolve(response.results) - }) - .catch((error: unknown) => { - logger.error({ error }, "[AI Mod] Error during moderation check") - this.responseAwaiter.resolve([]) // fail open: return empty results on error - }) - } - - /** - * Add a candidate to the moderation check queue, returns the result if found. - * @param candidate the candidate to add to the queue, either text or image - * @returns A promise that resolves with the moderation result, or null if not found or timed out. - */ - private async addToCheckQueue(candidate: ModerationCandidate): Promise { - await this.responseAwaiter // wait for the previous batch to be processed - const index = this.checkQueue.push(candidate) - 1 - if (this.timeout === null) { - // throttle a check every 10 seconds - this.timeout = setTimeout(() => { - this.triggerCheck() - this.timeout = null - }, 10 * 1000) - } - return this.responseAwaiter.then((results) => results[index] ?? null) - } - - /** - * Check for harmful content in the message context. - * @param context the message context to check - * @returns A list of flagged categories found in the message - */ - async checkForHarmfulContent(context: Filter): Promise { - if (!this.client) return [] - const candidates: ModerationCandidate[] = [] - const { text } = getText(context.msg) - if (text) candidates.push({ text, type: "text" }) - if (context.msg.photo) { - const photo = context.msg.photo[0] - const file = await context.api.getFile(photo.file_id) - const url = `https://api.telegram.org/file/bot${context.api.token}/${file.file_path}` - - candidates.push({ image_url: { url }, type: "image_url" }) - } - - const raw = await Promise.all(candidates.map((candidate) => this.addToCheckQueue(candidate))) - const results = raw.filter((result) => result !== null) // fail open, e.g check times out: leave the message be - - return AIModeration.parseFlaggedCategories(results) - } -} diff --git a/src/middlewares/auto-moderation-stack/constants.ts b/src/middlewares/auto-moderation-stack/constants.ts index df672c3..a0e2377 100644 --- a/src/middlewares/auto-moderation-stack/constants.ts +++ b/src/middlewares/auto-moderation-stack/constants.ts @@ -1,5 +1,3 @@ -import type { Category } from "./types" - export const POLINETWORK_DISCORD_GUILD_ID = "1286773946045300787" export const BANNED_DOMAINS = [ "facebook.com", @@ -15,22 +13,6 @@ export const BANNED_DOMAINS = [ "polinetwork.it", ] as const -export const DELETION_THRESHOLDS: Record = { - harassment: false, - "harassment/threatening": 0.9, - hate: 0.9, - "hate/threatening": 0.9, - illicit: false, - "illicit/violent": false, - violence: 0.1, - "violence/graphic": false, - sexual: 0.9, - "sexual/minors": 0.8, - "self-harm": false, - "self-harm/intent": false, - "self-harm/instructions": false, -} as const - export const MULTI_CHAT_SPAM = { SIMILARITY_THR: 87, LENGTH_THR: 128, diff --git a/src/middlewares/auto-moderation-stack/index.ts b/src/middlewares/auto-moderation-stack/index.ts index ac7be95..676b9b1 100644 --- a/src/middlewares/auto-moderation-stack/index.ts +++ b/src/middlewares/auto-moderation-stack/index.ts @@ -74,8 +74,6 @@ export class AutoModerationStack> exte .fork() .use(measureForkDuration("auto_moderation_link_duration")) .use((ctx) => this.linkHandler(ctx)) - // AI takes too long to measure, completely defer it to avoid blocking the main stack, and just log any errors - // filtered.fork().use(defer((ctx) => this.harmfulContentHandler(ctx))) filtered .on([":text", ":caption"]) .fork() @@ -168,62 +166,6 @@ export class AutoModerationStack> exte ) } - // /** - // * Checks messages for harmful content using AI moderation. - // * If harmful content is detected, mutes the user and deletes the message. - // */ - // private async harmfulContentHandler(ctx: ModerationContext) { - // const message = ctx.msg - // const flaggedCategories = await this.aiModeration.checkForHarmfulContent(ctx) - - // if (flaggedCategories.length > 0) { - // const reasons = flaggedCategories.map((cat) => ` - ${cat.category} (${(cat.score * 100).toFixed(1)}%)`).join("\n") - - // if (flaggedCategories.some((cat) => cat.aboveThreshold)) { - // if (ctx.whitelisted) { - // // log the action but do not mute - // if (ctx.whitelisted.role === "user") - // await modules.get("tgLogger").grants({ - // action: "USAGE", - // from: ctx.from, - // chat: ctx.chat, - // message, - // }) - // } else { - // // above threshold, mute user and delete the message - // const res = await Moderation.mute( - // ctx.from, - // ctx.chat, - // ctx.me, - // duration.zod.parse("1d"), - // [message], - // `Automatic moderation detected harmful content\n${reasons}` - // ) - - // void ephemeral( - // ctx.reply( - // res.isOk() - // ? fmt(({ i, b }) => [ - // b`⚠️ Message from ${fmtUser(ctx.from)} was deleted automatically due to harmful content.`, - // i`If you think this is a mistake, please contact the group administrators.`, - // ]) - // : res.error.fmtError - // ) - // ) - // } - // } else { - // // no flagged category is above the threshold, still log it for manual review - // await modules.get("tgLogger").moderationAction({ - // action: "SILENT", - // from: ctx.me, - // chat: ctx.chat, - // target: ctx.from, - // reason: `Message flagged for moderation: \n${reasons}`, - // }) - // } - // } - // } - /** * Handles messages containing a high percentage of non-latin characters to avoid most spam bots. * If the percentage of non-latin characters is too high, mutes the user for 10 minutes and deletes the message. diff --git a/src/middlewares/auto-moderation-stack/types.ts b/src/middlewares/auto-moderation-stack/types.ts index e593ef2..b18121a 100644 --- a/src/middlewares/auto-moderation-stack/types.ts +++ b/src/middlewares/auto-moderation-stack/types.ts @@ -1,15 +1,3 @@ -import type OpenAI from "openai" - -export type ModerationCandidate = OpenAI.Moderations.ModerationMultiModalInput -export type ModerationResult = OpenAI.Moderations.Moderation -export type Category = keyof OpenAI.Moderations.Moderation.CategoryScores - -export interface FlaggedCategory { - category: Category - score: number - aboveThreshold: boolean -} - export type MultiChatMsgCollection = { chatId: number messages: { id: number; message: string; timestamp: Date }[] diff --git a/tests/throttle.test.ts b/tests/throttle.test.ts index 0f3db8a..a561d36 100644 --- a/tests/throttle.test.ts +++ b/tests/throttle.test.ts @@ -19,8 +19,8 @@ function testObject() { return { testobj, spy } } -describe("throttle function", () => { - it("test 1", async () => { +describe.concurrent("throttle function", () => { + it("should limit the number of calls to the throttled function", async () => { const { testobj, spy } = testObject() const limitms = 100 const throttled = throttle(() => testobj.foo(), limitms) @@ -28,7 +28,7 @@ describe("throttle function", () => { await wait(limitms + 20) expect(spy).toHaveBeenCalledTimes(3) }) - it("test 2", async () => { + it("should call the throttled function when the delay has passed", async () => { const { testobj, spy } = testObject() const limitms = 50 const throttled = throttle(() => testobj.foo(), limitms) @@ -36,7 +36,7 @@ describe("throttle function", () => { await wait(limitms + 20) expect(spy).toHaveBeenCalledTimes(3) }) - it("test 3", async () => { + it("should handle spam calls correctly, only first and last calls are executed", async () => { const { testobj, spy } = testObject() const limitms = 500 const throttled = throttle((i: number) => testobj.foo(i), limitms) @@ -48,12 +48,12 @@ describe("throttle function", () => { expect(spy).toHaveBeenNthCalledWith(1, 0) expect(spy).toHaveBeenLastCalledWith(49) }) - it("test 4", async () => { + it("should call the throttled function immediately on the first call", async () => { const { testobj, spy } = testObject() const limitms = 10 const throttled = throttle(() => testobj.foo(), limitms) throttled() - await wait(limitms + 20) + await wait(1) expect(spy).toHaveBeenCalledTimes(1) }) })