diff --git a/.docker/Dockerfile.api b/.docker/Dockerfile.api
new file mode 100644
index 0000000000..6566096a71
--- /dev/null
+++ b/.docker/Dockerfile.api
@@ -0,0 +1,27 @@
+# docker compose build base api
+
+FROM roomote-base AS base
+
+WORKDIR /roo
+
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+COPY packages/config-eslint/package.json ./packages/config-eslint/
+COPY packages/config-typescript/package.json ./packages/config-typescript/
+COPY packages/types/package.json ./packages/types/
+COPY packages/ipc/package.json ./packages/ipc/
+COPY apps/roomote/package.json ./apps/roomote/
+
+COPY scripts/bootstrap.mjs ./scripts/
+RUN pnpm install
+
+COPY apps/roomote ./apps/roomote/
+COPY packages/config-eslint ./packages/config-eslint/
+COPY packages/config-typescript ./packages/config-typescript/
+COPY packages/types ./packages/types/
+COPY packages/ipc ./packages/ipc/
+
+WORKDIR /roo/apps/roomote
+RUN pnpm build
+ENV NODE_ENV=production
+EXPOSE 3001
+CMD ["pnpm", "start"]
diff --git a/.docker/Dockerfile.base b/.docker/Dockerfile.base
new file mode 100644
index 0000000000..3320b0b6a5
--- /dev/null
+++ b/.docker/Dockerfile.base
@@ -0,0 +1,31 @@
+# docker compose build base
+
+FROM node:20-slim AS base
+
+# Install pnpm
+ENV PNPM_HOME="/pnpm"
+ENV PATH="$PNPM_HOME:$PATH"
+RUN corepack enable
+
+# Install common system packages
+RUN apt update && \
+ apt install -y \
+ curl \
+ git \
+ vim \
+ jq \
+ netcat-openbsd \
+ apt-transport-https \
+ ca-certificates \
+ gnupg \
+ lsb-release \
+ wget \
+ gpg \
+ gh \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install Docker cli
+RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
+ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
+ && apt update && apt install -y docker-ce-cli \
+ && rm -rf /var/lib/apt/lists/*
diff --git a/.docker/Dockerfile.controller b/.docker/Dockerfile.controller
new file mode 100644
index 0000000000..a2a2e00203
--- /dev/null
+++ b/.docker/Dockerfile.controller
@@ -0,0 +1,25 @@
+# docker compose build base controller
+
+FROM roomote-base AS base
+
+WORKDIR /roo
+
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+COPY packages/config-eslint/package.json ./packages/config-eslint/
+COPY packages/config-typescript/package.json ./packages/config-typescript/
+COPY packages/types/package.json ./packages/types/
+COPY packages/ipc/package.json ./packages/ipc/
+COPY apps/roomote/package.json ./apps/roomote/
+
+COPY scripts/bootstrap.mjs ./scripts/
+RUN pnpm install
+
+COPY apps/roomote ./apps/roomote/
+COPY packages/config-eslint ./packages/config-eslint/
+COPY packages/config-typescript ./packages/config-typescript/
+COPY packages/types ./packages/types/
+COPY packages/ipc ./packages/ipc/
+
+WORKDIR /roo/apps/roomote
+ENV NODE_ENV=production
+CMD ["pnpm", "controller"]
diff --git a/.docker/Dockerfile.dashboard b/.docker/Dockerfile.dashboard
new file mode 100644
index 0000000000..f04160d9d2
--- /dev/null
+++ b/.docker/Dockerfile.dashboard
@@ -0,0 +1,25 @@
+# docker compose build base dashboard
+
+FROM roomote-base AS base
+
+WORKDIR /roo
+
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+COPY packages/config-eslint/package.json ./packages/config-eslint/
+COPY packages/config-typescript/package.json ./packages/config-typescript/
+COPY packages/types/package.json ./packages/types/
+COPY packages/ipc/package.json ./packages/ipc/
+COPY apps/roomote/package.json ./apps/roomote/
+
+COPY scripts/bootstrap.mjs ./scripts/
+RUN pnpm install
+
+COPY apps/roomote ./apps/roomote/
+COPY packages/config-eslint ./packages/config-eslint/
+COPY packages/config-typescript ./packages/config-typescript/
+COPY packages/types ./packages/types/
+COPY packages/ipc ./packages/ipc/
+
+WORKDIR /roo/apps/roomote
+EXPOSE 3002
+CMD ["pnpm", "dashboard"]
diff --git a/.docker/Dockerfile.worker b/.docker/Dockerfile.worker
new file mode 100644
index 0000000000..b1a21c8a62
--- /dev/null
+++ b/.docker/Dockerfile.worker
@@ -0,0 +1,62 @@
+# docker compose build worker
+# Note: Requires $GH_TOKEN to be set as build argument.
+
+FROM roomote-base AS base
+
+# Install additional worker-specific packages
+RUN apt update && \
+ apt install -y \
+ xvfb \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install VS Code
+RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg \
+ && install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg \
+ && echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" | tee /etc/apt/sources.list.d/vscode.list > /dev/null \
+ && rm -f packages.microsoft.gpg \
+ && apt update && apt install -y code \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /roo
+
+# Install extensions
+RUN mkdir -p /roo/.vscode \
+ && code --no-sandbox --user-data-dir /roo/.vscode --install-extension dbaeumer.vscode-eslint \
+ && code --no-sandbox --user-data-dir /roo/.vscode --install-extension esbenp.prettier-vscode \
+ && code --no-sandbox --user-data-dir /roo/.vscode --install-extension csstools.postcss \
+ && code --no-sandbox --user-data-dir /roo/.vscode --install-extension RooVeterinaryInc.roo-cline
+
+# Clone repo (requires $GH_TOKEN)
+ARG GH_TOKEN
+ENV GH_TOKEN=${GH_TOKEN}
+WORKDIR /roo/repos
+RUN git config --global user.email "chris@roocode.com"
+RUN git config --global user.name "Roo Code"
+RUN git config --global credential.helper store
+RUN echo "https://oauth2:${GH_TOKEN}@github.com" > ~/.git-credentials
+RUN gh repo clone RooCodeInc/Roo-Code
+WORKDIR /roo/repos/Roo-Code
+RUN gh repo set-default RooCodeInc/Roo-Code
+RUN pnpm install
+
+# Install dependencies
+WORKDIR /roo
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
+COPY packages/config-eslint/package.json ./packages/config-eslint/
+COPY packages/config-typescript/package.json ./packages/config-typescript/
+COPY packages/types/package.json ./packages/types/
+COPY packages/ipc/package.json ./packages/ipc/
+COPY apps/roomote/package.json ./apps/roomote/
+
+COPY scripts/bootstrap.mjs ./scripts/
+RUN pnpm install
+
+COPY apps/roomote ./apps/roomote/
+COPY packages/config-eslint ./packages/config-eslint/
+COPY packages/config-typescript ./packages/config-typescript/
+COPY packages/types ./packages/types/
+COPY packages/ipc ./packages/ipc/
+
+WORKDIR /roo/apps/roomote
+ENV NODE_ENV=production
+CMD ["pnpm", "worker"]
diff --git a/apps/web/.docker/scripts/clickhouse/001-create-tables.sql b/.docker/scripts/clickhouse/001-create-tables.sql
similarity index 100%
rename from apps/web/.docker/scripts/clickhouse/001-create-tables.sql
rename to .docker/scripts/clickhouse/001-create-tables.sql
diff --git a/apps/web/.docker/scripts/postgres/create-databases.sh b/.docker/scripts/postgres/create-databases.sh
similarity index 100%
rename from apps/web/.docker/scripts/postgres/create-databases.sh
rename to .docker/scripts/postgres/create-databases.sh
diff --git a/.gitignore b/.gitignore
index 2fb2180020..ba03f70657 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ node_modules
Thumbs.db
# .env
+.env
.env*.local
.env*.production
@@ -17,3 +18,7 @@ Thumbs.db
# vercel
.vercel
+
+# docker
+.docker/data
+.docker/logs
diff --git a/apps/web/.prettierrc.json b/.prettierrc.json
similarity index 100%
rename from apps/web/.prettierrc.json
rename to .prettierrc.json
diff --git a/README.md b/README.md
index 5da8ba492c..a415fa96bf 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,27 @@
# Roo Code Cloud Monorepo
+
+### Web
+
+To start the web app you first need to start the `postgres` and `clickhouse` docker services:
+
+```sh
+pnpm db:up
+```
+
+This will automatically sync your database to the latest version of the schema. If you need to reset your database at any point, you can run:
+
+```sh
+pnpm db:reset
+```
+
+Then you can start the app in dev mode:
+
+```sh
+pnpm --filter @roo-code-cloud/web dev
+```
+
+The app will be available at (localhost:3000)[http://localhost:3000/].
+
+### Roomote
+
+TBD
diff --git a/apps/roomote/.env.example b/apps/roomote/.env.example
new file mode 100644
index 0000000000..0e1eb3ae79
--- /dev/null
+++ b/apps/roomote/.env.example
@@ -0,0 +1,9 @@
+DATABASE_URL=postgresql://postgres:password@localhost:5433/cloud_agents
+REDIS_URL=redis://localhost:6380
+
+GH_WEBHOOK_SECRET=your-webhook-secret-here
+GH_TOKEN=your-token-here
+
+OPENROUTER_API_KEY=sk-or-v1-...
+
+SLACK_API_TOKEN=xoxb-...
diff --git a/apps/roomote/.gitignore b/apps/roomote/.gitignore
new file mode 100644
index 0000000000..37799ec24d
--- /dev/null
+++ b/apps/roomote/.gitignore
@@ -0,0 +1,3 @@
+# next.js
+/.next
+/out
diff --git a/apps/roomote/drizzle.config.ts b/apps/roomote/drizzle.config.ts
new file mode 100644
index 0000000000..9233f37d33
--- /dev/null
+++ b/apps/roomote/drizzle.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'drizzle-kit';
+
+export default defineConfig({
+ schema: './src/db/schema.ts',
+ out: './drizzle',
+ dialect: 'postgresql',
+ dbCredentials: {
+ url: process.env.DATABASE_URL!,
+ },
+});
diff --git a/apps/roomote/drizzle/0000_cuddly_luke_cage.sql b/apps/roomote/drizzle/0000_cuddly_luke_cage.sql
new file mode 100644
index 0000000000..2535f219e2
--- /dev/null
+++ b/apps/roomote/drizzle/0000_cuddly_luke_cage.sql
@@ -0,0 +1,21 @@
+CREATE TABLE "cloud_jobs" (
+ "id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "cloud_jobs_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
+ "type" text NOT NULL,
+ "status" text DEFAULT 'pending' NOT NULL,
+ "payload" jsonb NOT NULL,
+ "result" jsonb,
+ "error" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "started_at" timestamp,
+ "completed_at" timestamp
+);
+--> statement-breakpoint
+CREATE TABLE "cloud_tasks" (
+ "id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "cloud_tasks_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
+ "job_id" integer NOT NULL,
+ "task_id" integer,
+ "container_id" text,
+ "created_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE "cloud_tasks" ADD CONSTRAINT "cloud_tasks_job_id_cloud_jobs_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."cloud_jobs"("id") ON DELETE no action ON UPDATE no action;
\ No newline at end of file
diff --git a/apps/roomote/drizzle/0001_fluffy_sasquatch.sql b/apps/roomote/drizzle/0001_fluffy_sasquatch.sql
new file mode 100644
index 0000000000..aeddbe02a8
--- /dev/null
+++ b/apps/roomote/drizzle/0001_fluffy_sasquatch.sql
@@ -0,0 +1 @@
+ALTER TABLE "cloud_jobs" ADD COLUMN "slack_thread_ts" text;
\ No newline at end of file
diff --git a/apps/roomote/drizzle/0002_brief_sentry.sql b/apps/roomote/drizzle/0002_brief_sentry.sql
new file mode 100644
index 0000000000..2f22f7825c
--- /dev/null
+++ b/apps/roomote/drizzle/0002_brief_sentry.sql
@@ -0,0 +1 @@
+DROP TABLE "cloud_tasks" CASCADE;
\ No newline at end of file
diff --git a/apps/roomote/drizzle/meta/0000_snapshot.json b/apps/roomote/drizzle/meta/0000_snapshot.json
new file mode 100644
index 0000000000..ea3dda697f
--- /dev/null
+++ b/apps/roomote/drizzle/meta/0000_snapshot.json
@@ -0,0 +1,164 @@
+{
+ "id": "8f65bfed-78de-4e22-a15f-36de8afe5f2e",
+ "prevId": "00000000-0000-0000-0000-000000000000",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.cloud_jobs": {
+ "name": "cloud_jobs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "identity": {
+ "type": "always",
+ "name": "cloud_jobs_id_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "2147483647",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "result": {
+ "name": "result",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cloud_tasks": {
+ "name": "cloud_tasks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "identity": {
+ "type": "always",
+ "name": "cloud_tasks_id_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "2147483647",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "job_id": {
+ "name": "job_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "task_id": {
+ "name": "task_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "container_id": {
+ "name": "container_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cloud_tasks_job_id_cloud_jobs_id_fk": {
+ "name": "cloud_tasks_job_id_cloud_jobs_id_fk",
+ "tableFrom": "cloud_tasks",
+ "tableTo": "cloud_jobs",
+ "columnsFrom": ["job_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/apps/roomote/drizzle/meta/0001_snapshot.json b/apps/roomote/drizzle/meta/0001_snapshot.json
new file mode 100644
index 0000000000..14c0e9c48c
--- /dev/null
+++ b/apps/roomote/drizzle/meta/0001_snapshot.json
@@ -0,0 +1,170 @@
+{
+ "id": "4cae0c18-141d-40a3-acc8-38fcd7f07534",
+ "prevId": "8f65bfed-78de-4e22-a15f-36de8afe5f2e",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.cloud_jobs": {
+ "name": "cloud_jobs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "identity": {
+ "type": "always",
+ "name": "cloud_jobs_id_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "2147483647",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "result": {
+ "name": "result",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "slack_thread_ts": {
+ "name": "slack_thread_ts",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cloud_tasks": {
+ "name": "cloud_tasks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "identity": {
+ "type": "always",
+ "name": "cloud_tasks_id_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "2147483647",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "job_id": {
+ "name": "job_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "task_id": {
+ "name": "task_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "container_id": {
+ "name": "container_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cloud_tasks_job_id_cloud_jobs_id_fk": {
+ "name": "cloud_tasks_job_id_cloud_jobs_id_fk",
+ "tableFrom": "cloud_tasks",
+ "tableTo": "cloud_jobs",
+ "columnsFrom": ["job_id"],
+ "columnsTo": ["id"],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/apps/roomote/drizzle/meta/0002_snapshot.json b/apps/roomote/drizzle/meta/0002_snapshot.json
new file mode 100644
index 0000000000..dbbc7d7cdc
--- /dev/null
+++ b/apps/roomote/drizzle/meta/0002_snapshot.json
@@ -0,0 +1,105 @@
+{
+ "id": "16afebd7-b27a-457e-b3d5-4de50a597c2e",
+ "prevId": "4cae0c18-141d-40a3-acc8-38fcd7f07534",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.cloud_jobs": {
+ "name": "cloud_jobs",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "identity": {
+ "type": "always",
+ "name": "cloud_jobs_id_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "2147483647",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "payload": {
+ "name": "payload",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "result": {
+ "name": "result",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "slack_thread_ts": {
+ "name": "slack_thread_ts",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "started_at": {
+ "name": "started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/apps/roomote/drizzle/meta/_journal.json b/apps/roomote/drizzle/meta/_journal.json
new file mode 100644
index 0000000000..179f2cdbf7
--- /dev/null
+++ b/apps/roomote/drizzle/meta/_journal.json
@@ -0,0 +1,27 @@
+{
+ "version": "7",
+ "dialect": "postgresql",
+ "entries": [
+ {
+ "idx": 0,
+ "version": "7",
+ "when": 1749740498648,
+ "tag": "0000_cuddly_luke_cage",
+ "breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "7",
+ "when": 1750099429125,
+ "tag": "0001_fluffy_sasquatch",
+ "breakpoints": true
+ },
+ {
+ "idx": 2,
+ "version": "7",
+ "when": 1750107620472,
+ "tag": "0002_brief_sentry",
+ "breakpoints": true
+ }
+ ]
+}
diff --git a/apps/roomote/eslint.config.mjs b/apps/roomote/eslint.config.mjs
new file mode 100644
index 0000000000..00b53054bd
--- /dev/null
+++ b/apps/roomote/eslint.config.mjs
@@ -0,0 +1,4 @@
+import { nextJsConfig } from '@roo-code-cloud/config-eslint/next-js';
+
+/** @type {import("eslint").Linter.Config} */
+export default [...nextJsConfig];
diff --git a/apps/roomote/next-env.d.ts b/apps/roomote/next-env.d.ts
new file mode 100644
index 0000000000..1b3be0840f
--- /dev/null
+++ b/apps/roomote/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/apps/roomote/next.config.ts b/apps/roomote/next.config.ts
new file mode 100644
index 0000000000..9d3c27b2e8
--- /dev/null
+++ b/apps/roomote/next.config.ts
@@ -0,0 +1,7 @@
+import type { NextConfig } from 'next';
+
+const nextConfig: NextConfig = {
+ serverExternalPackages: ['postgres', 'ioredis', 'bullmq'],
+};
+
+export default nextConfig;
diff --git a/apps/roomote/package.json b/apps/roomote/package.json
index c7398c792b..b51dea3908 100644
--- a/apps/roomote/package.json
+++ b/apps/roomote/package.json
@@ -1,4 +1,55 @@
{
"name": "@roo-code-cloud/roomote",
- "private": true
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "lint": "next lint --max-warnings 0",
+ "check-types": "tsc --noEmit",
+ "test": "vitest",
+ "dev": "concurrently \"next dev --port 3001\" \"ngrok http 3001 --domain cte.ngrok.dev\"",
+ "build": "next build",
+ "start": "next start --port 3001",
+ "clean": "rimraf .next .turbo",
+ "drizzle-kit": "dotenvx run -f .env -- tsx node_modules/drizzle-kit/bin.cjs",
+ "db:generate": "pnpm drizzle-kit generate",
+ "db:migrate": "pnpm drizzle-kit migrate",
+ "db:push": "pnpm drizzle-kit push",
+ "db:check": "pnpm drizzle-kit check",
+ "db:studio": "pnpm drizzle-kit studio",
+ "services:start": "docker compose up -d db redis dashboard",
+ "services:stop": "docker compose down dashboard redis db",
+ "worker": "dotenvx run -f .env -- tsx src/lib/worker.ts",
+ "controller": "dotenvx run -f .env -- tsx src/lib/controller.ts",
+ "dashboard": "tsx scripts/dashboard.ts"
+ },
+ "dependencies": {
+ "@bull-board/api": "^6.10.1",
+ "@bull-board/express": "^6.10.1",
+ "@bull-board/ui": "^6.10.1",
+ "@roo-code/types": "^1.26.0",
+ "@roo-code-cloud/ipc": "workspace:^",
+ "bullmq": "^5.37.0",
+ "drizzle-orm": "^0.44.1",
+ "execa": "^9.6.0",
+ "express": "^5.1.0",
+ "ioredis": "^5.4.3",
+ "next": "^15.3.3",
+ "p-wait-for": "^5.0.2",
+ "postgres": "^3.4.7",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "zod": "^3.25.41"
+ },
+ "devDependencies": {
+ "@roo-code-cloud/config-eslint": "workspace:^",
+ "@roo-code-cloud/config-typescript": "workspace:^",
+ "@types/express": "^5.0.3",
+ "@types/node": "^22.15.20",
+ "@types/react": "^19.1.6",
+ "@types/react-dom": "^19.1.6",
+ "concurrently": "^9.1.0",
+ "drizzle-kit": "^0.31.1",
+ "tsx": "^4.19.3",
+ "vitest": "^3.2.3"
+ }
}
diff --git a/apps/roomote/scripts/build.sh b/apps/roomote/scripts/build.sh
new file mode 100755
index 0000000000..1bc54d1e26
--- /dev/null
+++ b/apps/roomote/scripts/build.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Build script for roomote services.
+# This ensures the base image is built before dependent services.
+
+set -e
+
+build_service() {
+ local service=$1
+
+ case $service in
+ "dashboard"|"api"|"worker"|"controller")
+ echo "Building base image first..."
+ docker compose build base
+ echo "Building $service..."
+ docker compose build $service
+ ;;
+ "base")
+ echo "Building base image..."
+ docker compose build base
+ ;;
+ *)
+ echo "Building $service..."
+ docker compose build $service
+ ;;
+ esac
+}
+
+if [ $# -eq 0 ]; then
+ echo "Usage: $0 "
+ echo "Available services: base, dashboard, api, worker, controller, db, redis"
+ echo "Example: $0 dashboard"
+ exit 1
+fi
+
+build_service $1
+
+echo "Build completed successfully!"
diff --git a/apps/roomote/scripts/dashboard.ts b/apps/roomote/scripts/dashboard.ts
new file mode 100644
index 0000000000..7600bf2251
--- /dev/null
+++ b/apps/roomote/scripts/dashboard.ts
@@ -0,0 +1,24 @@
+import IORedis from 'ioredis';
+import { Queue } from 'bullmq';
+import { ExpressAdapter } from '@bull-board/express';
+import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
+import { createBullBoard } from '@bull-board/api';
+import express from 'express';
+import type { Express, Request, Response } from 'express';
+
+const redis = new IORedis(process.env.REDIS_URL || 'redis://localhost:6380', {
+ maxRetriesPerRequest: null,
+});
+const queue = new Queue('roomote', { connection: redis });
+
+const serverAdapter = new ExpressAdapter();
+serverAdapter.setBasePath('/admin/queues');
+createBullBoard({ queues: [new BullMQAdapter(queue)], serverAdapter });
+
+const port = 3002;
+const app: Express = express();
+app.use('/admin/queues', serverAdapter.getRouter());
+app.use('/', (req: Request, res: Response) => res.redirect('/admin/queues'));
+app.listen(port, () =>
+ console.log(`Bull Board running on: http://localhost:${port}/admin/queues`),
+);
diff --git a/apps/roomote/scripts/enqueue-github-issue-job.sh b/apps/roomote/scripts/enqueue-github-issue-job.sh
new file mode 100755
index 0000000000..5ec7448cc6
--- /dev/null
+++ b/apps/roomote/scripts/enqueue-github-issue-job.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+REPO="RooCodeInc/Roo-Code"
+ISSUE_NUMBER="$1"
+BASE_URL="http://localhost:3001"
+JOBS_ENDPOINT="$BASE_URL/api/jobs"
+
+if [ -z "$ISSUE_NUMBER" ]; then
+ echo "Usage: $0 [repo]"
+ echo ""
+ echo "Examples:"
+ echo " $0 4567 # Fetch issue #4567 from RooCodeInc/Roo-Code"
+ echo " $0 123 owner/repo # Fetch issue #123 from owner/repo"
+ echo ""
+ echo "This script fetches real GitHub issue data and enqueues it as a job."
+ exit 1
+fi
+
+if [ -n "$2" ]; then
+ REPO="$2"
+fi
+
+if ! command -v gh &> /dev/null; then
+ echo "Error: GitHub CLI (gh) is not installed. Please install it first."
+ echo "Visit: https://cli.github.com/"
+ exit 1
+fi
+
+if ! gh auth status &> /dev/null; then
+ echo "Error: Not authenticated with GitHub CLI. Please run 'gh auth login' first."
+ exit 1
+fi
+
+if ! command -v jq &> /dev/null; then
+ echo "Error: jq is not installed. Please install it first."
+ echo "Visit: https://jqlang.github.io/jq/download/"
+ exit 1
+fi
+
+echo "Fetching issue #${ISSUE_NUMBER} from ${REPO}..."
+
+ISSUE_DATA=$(gh issue view ${ISSUE_NUMBER} --repo ${REPO} --json title,body,labels 2>/dev/null)
+
+if [ $? -ne 0 ]; then
+ echo "Error: Failed to fetch issue #${ISSUE_NUMBER} from ${REPO}"
+ echo "Please check that the issue exists and you have access to the repository."
+ exit 1
+fi
+
+TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
+BODY=$(echo "$ISSUE_DATA" | jq -r '.body // ""')
+LABELS=$(echo "$ISSUE_DATA" | jq -r '[.labels[].name] | @json')
+
+JSON_PAYLOAD=$(jq -n \
+ --arg type "github.issue.fix" \
+ --arg repo "$REPO" \
+ --argjson issue "$ISSUE_NUMBER" \
+ --arg title "$TITLE" \
+ --arg body "$BODY" \
+ --argjson labels "$LABELS" \
+ '{
+ type: $type,
+ payload: {
+ repo: $repo,
+ issue: $issue,
+ title: $title,
+ body: $body,
+ labels: $labels
+ }
+ }')
+
+echo "curl -X POST \"$JOBS_ENDPOINT\" -H \"Content-Type: application/json\" -d \"$JSON_PAYLOAD\" -w \"\nStatus: %{http_code}\n\n\""
+
+curl -X POST "$JOBS_ENDPOINT" -H "Content-Type: application/json" -d "$JSON_PAYLOAD" -w "\nStatus: %{http_code}\n\n"
diff --git a/apps/roomote/src/app/api/health/route.ts b/apps/roomote/src/app/api/health/route.ts
new file mode 100644
index 0000000000..8141a28259
--- /dev/null
+++ b/apps/roomote/src/app/api/health/route.ts
@@ -0,0 +1,36 @@
+import { NextResponse } from 'next/server';
+
+import { db } from '@/db';
+import { redis } from '@/lib';
+
+export async function GET() {
+ try {
+ const services = { database: false, redis: false };
+
+ try {
+ await db.execute('SELECT 1');
+ services.database = true;
+ } catch (error) {
+ console.error('Database health check failed:', error);
+ }
+
+ try {
+ await redis.ping();
+ services.redis = true;
+ } catch (error) {
+ console.error('Redis health check failed:', error);
+ }
+
+ const allHealthy = Object.values(services).every(Boolean);
+ return NextResponse.json(
+ { status: allHealthy ? 'ok' : 'error', services },
+ { status: allHealthy ? 200 : 500 },
+ );
+ } catch (error) {
+ console.error('Health check error:', error);
+ return NextResponse.json(
+ { status: 'error', error: 'Internal server error' },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/roomote/src/app/api/jobs/[id]/route.ts b/apps/roomote/src/app/api/jobs/[id]/route.ts
new file mode 100644
index 0000000000..05c02c869f
--- /dev/null
+++ b/apps/roomote/src/app/api/jobs/[id]/route.ts
@@ -0,0 +1,48 @@
+import { NextRequest, NextResponse } from 'next/server';
+import { eq } from 'drizzle-orm';
+
+import { db, cloudJobs } from '@/db';
+
+type Params = Promise<{ id: string }>;
+
+export async function GET(
+ request: NextRequest,
+ { params }: { params: Params },
+) {
+ try {
+ const { id } = await params;
+ const jobId = parseInt(id, 10);
+
+ if (isNaN(jobId)) {
+ return NextResponse.json({ error: 'Invalid job ID' }, { status: 400 });
+ }
+
+ const [job] = await db
+ .select()
+ .from(cloudJobs)
+ .where(eq(cloudJobs.id, jobId))
+ .limit(1);
+
+ if (!job) {
+ return NextResponse.json({ error: 'Job not found' }, { status: 404 });
+ }
+
+ return NextResponse.json({
+ id: job.id,
+ type: job.type,
+ status: job.status,
+ payload: job.payload,
+ result: job.result,
+ error: job.error,
+ createdAt: job.createdAt,
+ startedAt: job.startedAt,
+ completedAt: job.completedAt,
+ });
+ } catch (error) {
+ console.error('Error fetching job:', error);
+ return NextResponse.json(
+ { error: 'Internal server error' },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/roomote/src/app/api/jobs/route.ts b/apps/roomote/src/app/api/jobs/route.ts
new file mode 100644
index 0000000000..50bdc20e24
--- /dev/null
+++ b/apps/roomote/src/app/api/jobs/route.ts
@@ -0,0 +1,44 @@
+import { NextRequest, NextResponse } from 'next/server';
+import { z } from 'zod';
+
+import { createJobSchema } from '@/types';
+import { db, cloudJobs } from '@/db';
+import { enqueue } from '@/lib';
+
+export async function POST(request: NextRequest) {
+ try {
+ const body = await request.json();
+ const values = createJobSchema.parse(body);
+
+ const [job] = await db
+ .insert(cloudJobs)
+ .values({ ...values, status: 'pending' })
+ .returning();
+
+ if (!job) {
+ throw new Error('Failed to create `cloudJobs` record.');
+ }
+
+ const enqueuedJob = await enqueue({ jobId: job.id, ...values });
+
+ return NextResponse.json({
+ message: 'job_enqueued',
+ jobId: job.id,
+ enqueuedJobId: enqueuedJob.id,
+ });
+ } catch (error) {
+ console.error('Create Job Error:', error);
+
+ if (error instanceof z.ZodError) {
+ return NextResponse.json(
+ { error: 'bad_request', details: error.errors },
+ { status: 400 },
+ );
+ }
+
+ return NextResponse.json(
+ { error: 'internal_server_error' },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/__tests__/route.test.ts b/apps/roomote/src/app/api/webhooks/github/__tests__/route.test.ts
new file mode 100644
index 0000000000..f778d44001
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/__tests__/route.test.ts
@@ -0,0 +1,376 @@
+// npx vitest src/app/api/webhooks/github/__tests__/route.test.ts
+
+import { NextRequest, NextResponse } from 'next/server';
+import { z } from 'zod';
+
+const mockVerifySignature = vi.fn();
+const mockHandleIssueEvent = vi.fn();
+const mockHandlePullRequestEvent = vi.fn();
+const mockHandleIssueCommentEvent = vi.fn();
+const mockHandlePullRequestReviewCommentEvent = vi.fn();
+
+vi.mock('../handlers', () => ({
+ verifySignature: mockVerifySignature,
+ handleIssueEvent: mockHandleIssueEvent,
+ handlePullRequestEvent: mockHandlePullRequestEvent,
+ handleIssueCommentEvent: mockHandleIssueCommentEvent,
+ handlePullRequestReviewCommentEvent: mockHandlePullRequestReviewCommentEvent,
+}));
+
+vi.mock('next/server', async () => {
+ const actual = await vi.importActual('next/server');
+ return {
+ ...actual,
+ NextResponse: {
+ json: vi.fn().mockReturnValue({ mocked: true }),
+ },
+ };
+});
+
+describe('GitHub Webhook Route', () => {
+ let POST: typeof import('../route').POST;
+
+ const validSignature = 'sha256=test-signature';
+ const validBody = JSON.stringify({ action: 'opened', number: 123 });
+ const webhookSecret = 'test-secret';
+
+ beforeEach(async () => {
+ vi.clearAllMocks();
+ process.env.GH_WEBHOOK_SECRET = webhookSecret;
+ // Import the POST function after mocks are set up.
+ const routeModule = await import('../route');
+ POST = routeModule.POST;
+ });
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ delete process.env.GH_WEBHOOK_SECRET;
+ });
+
+ const createMockRequest = (
+ headers: Record,
+ body: string = validBody,
+ ) => {
+ return {
+ headers: {
+ get: vi.fn((name: string) => headers[name] || null),
+ },
+ text: vi.fn().mockResolvedValue(body),
+ } as unknown as NextRequest;
+ };
+
+ describe('signature validation', () => {
+ it('should return 400 when signature header is missing', async () => {
+ const request = createMockRequest({});
+
+ await POST(request);
+
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ { error: 'missing_signature' },
+ { status: 400 },
+ );
+ });
+
+ it('should return 401 when signature is invalid', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ });
+ mockVerifySignature.mockReturnValue(false);
+
+ await POST(request);
+
+ expect(mockVerifySignature).toHaveBeenCalledWith(
+ validBody,
+ validSignature,
+ webhookSecret,
+ );
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ { error: 'invalid_signature' },
+ { status: 401 },
+ );
+ });
+
+ it('should proceed when signature is valid', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ });
+ mockVerifySignature.mockReturnValue(true);
+ mockHandleIssueEvent.mockResolvedValue({ status: 200 });
+
+ await POST(request);
+
+ expect(mockVerifySignature).toHaveBeenCalledWith(
+ validBody,
+ validSignature,
+ webhookSecret,
+ );
+ expect(mockHandleIssueEvent).toHaveBeenCalledWith(validBody);
+ });
+ });
+
+ describe('event handling', () => {
+ beforeEach(() => {
+ mockVerifySignature.mockReturnValue(true);
+ });
+
+ it('should handle issues event', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ });
+ const expectedResponse = { status: 200, data: 'success' };
+ mockHandleIssueEvent.mockResolvedValue(expectedResponse);
+
+ const result = await POST(request);
+
+ expect(mockHandleIssueEvent).toHaveBeenCalledWith(validBody);
+ expect(result).toBe(expectedResponse);
+ });
+
+ it('should handle pull_request event', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'pull_request',
+ });
+ const expectedResponse = { status: 200, data: 'success' };
+ mockHandlePullRequestEvent.mockResolvedValue(expectedResponse);
+
+ const result = await POST(request);
+
+ expect(mockHandlePullRequestEvent).toHaveBeenCalledWith(validBody);
+ expect(result).toBe(expectedResponse);
+ });
+
+ it('should handle issue_comment event', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issue_comment',
+ });
+ const expectedResponse = { status: 200, data: 'success' };
+ mockHandleIssueCommentEvent.mockResolvedValue(expectedResponse);
+
+ const result = await POST(request);
+
+ expect(mockHandleIssueCommentEvent).toHaveBeenCalledWith(validBody);
+ expect(result).toBe(expectedResponse);
+ });
+
+ it('should handle pull_request_review_comment event', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'pull_request_review_comment',
+ });
+ const expectedResponse = { status: 200, data: 'success' };
+ mockHandlePullRequestReviewCommentEvent.mockResolvedValue(
+ expectedResponse,
+ );
+
+ const result = await POST(request);
+
+ expect(mockHandlePullRequestReviewCommentEvent).toHaveBeenCalledWith(
+ validBody,
+ );
+ expect(result).toBe(expectedResponse);
+ });
+
+ it('should ignore unknown events', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'unknown_event',
+ });
+
+ await POST(request);
+
+ expect(NextResponse.json).toHaveBeenCalledWith({
+ message: 'event_ignored',
+ });
+ expect(mockHandleIssueEvent).not.toHaveBeenCalled();
+ expect(mockHandlePullRequestEvent).not.toHaveBeenCalled();
+ expect(mockHandleIssueCommentEvent).not.toHaveBeenCalled();
+ expect(mockHandlePullRequestReviewCommentEvent).not.toHaveBeenCalled();
+ });
+
+ it('should handle missing event header', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ });
+
+ await POST(request);
+
+ expect(NextResponse.json).toHaveBeenCalledWith({
+ message: 'event_ignored',
+ });
+ });
+ });
+
+ describe('error handling', () => {
+ beforeEach(() => {
+ mockVerifySignature.mockReturnValue(true);
+ });
+
+ it('should handle ZodError with 400 status', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ });
+ const zodError = new z.ZodError([
+ {
+ code: 'invalid_type',
+ expected: 'string',
+ received: 'number',
+ path: ['test'],
+ message: 'Expected string, received number',
+ },
+ ]);
+ mockHandleIssueEvent.mockRejectedValue(zodError);
+
+ await POST(request);
+
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ {
+ error: 'bad_request',
+ details: zodError.errors,
+ },
+ { status: 400 },
+ );
+ });
+
+ it('should handle generic errors with 500 status', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ });
+ const genericError = new Error('Database connection failed');
+ mockHandleIssueEvent.mockRejectedValue(genericError);
+
+ const consoleSpy = vi
+ .spyOn(console, 'error')
+ .mockImplementation(() => {});
+
+ await POST(request);
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ 'GitHub Webhook Error:',
+ genericError,
+ );
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ { error: 'internal_server_error' },
+ { status: 500 },
+ );
+
+ consoleSpy.mockRestore();
+ });
+
+ it('should handle errors during signature verification', async () => {
+ const request = createMockRequest({
+ 'x-hub-signature-256': validSignature,
+ });
+ mockVerifySignature.mockImplementation(() => {
+ throw new Error('Signature verification failed');
+ });
+
+ const consoleSpy = vi
+ .spyOn(console, 'error')
+ .mockImplementation(() => {});
+
+ await POST(request);
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ 'GitHub Webhook Error:',
+ expect.any(Error),
+ );
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ { error: 'internal_server_error' },
+ { status: 500 },
+ );
+
+ consoleSpy.mockRestore();
+ });
+
+ it('should handle errors when reading request body', async () => {
+ const request = {
+ headers: {
+ get: vi.fn().mockReturnValue(validSignature),
+ },
+ text: vi.fn().mockRejectedValue(new Error('Failed to read body')),
+ } as unknown as NextRequest;
+
+ const consoleSpy = vi
+ .spyOn(console, 'error')
+ .mockImplementation(() => {});
+
+ await POST(request);
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ 'GitHub Webhook Error:',
+ expect.any(Error),
+ );
+ expect(NextResponse.json).toHaveBeenCalledWith(
+ { error: 'internal_server_error' },
+ { status: 500 },
+ );
+
+ consoleSpy.mockRestore();
+ });
+ });
+
+ describe('integration scenarios', () => {
+ beforeEach(() => {
+ mockVerifySignature.mockReturnValue(true);
+ });
+
+ it('should process a complete valid webhook request', async () => {
+ const issuePayload = {
+ action: 'opened',
+ issue: {
+ number: 123,
+ title: 'Test issue',
+ body: 'This is a test issue',
+ },
+ };
+ const request = createMockRequest(
+ {
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ },
+ JSON.stringify(issuePayload),
+ );
+ const expectedResponse = { status: 200, jobId: 'job-123' };
+ mockHandleIssueEvent.mockResolvedValue(expectedResponse);
+
+ const result = await POST(request);
+
+ expect(request.text).toHaveBeenCalled();
+ expect(mockVerifySignature).toHaveBeenCalledWith(
+ JSON.stringify(issuePayload),
+ validSignature,
+ webhookSecret,
+ );
+ expect(mockHandleIssueEvent).toHaveBeenCalledWith(
+ JSON.stringify(issuePayload),
+ );
+ expect(result).toBe(expectedResponse);
+ });
+
+ it('should handle empty request body', async () => {
+ const request = createMockRequest(
+ {
+ 'x-hub-signature-256': validSignature,
+ 'x-github-event': 'issues',
+ },
+ '',
+ );
+ mockHandleIssueEvent.mockResolvedValue({ status: 200 });
+
+ await POST(request);
+
+ expect(mockVerifySignature).toHaveBeenCalledWith(
+ '',
+ validSignature,
+ webhookSecret,
+ );
+ expect(mockHandleIssueEvent).toHaveBeenCalledWith('');
+ });
+ });
+});
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/__tests__/utils.test.ts b/apps/roomote/src/app/api/webhooks/github/handlers/__tests__/utils.test.ts
new file mode 100644
index 0000000000..d535591a5a
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/__tests__/utils.test.ts
@@ -0,0 +1,294 @@
+// npx vitest src/app/api/webhooks/github/handlers/__tests__/utils.test.ts
+
+import { createHmac } from 'crypto';
+
+vi.mock('@/db', () => ({
+ db: {
+ insert: vi.fn(),
+ },
+ cloudJobs: {},
+}));
+
+vi.mock('@/lib', () => ({
+ enqueue: vi.fn(),
+}));
+
+describe('GitHub Webhook Utils', () => {
+ let verifySignature: typeof import('../utils').verifySignature;
+ let createAndEnqueueJob: typeof import('../utils').createAndEnqueueJob;
+ let mockDb: { insert: ReturnType };
+ let mockEnqueue: ReturnType;
+
+ beforeEach(async () => {
+ vi.clearAllMocks();
+
+ const dbModule = await import('@/db');
+ const libModule = await import('@/lib');
+ mockDb = dbModule.db as unknown as { insert: ReturnType };
+ mockEnqueue = libModule.enqueue as unknown as ReturnType;
+
+ const utilsModule = await import('../utils');
+ verifySignature = utilsModule.verifySignature;
+ createAndEnqueueJob = utilsModule.createAndEnqueueJob;
+ });
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ describe('verifySignature', () => {
+ const secret = 'test-secret';
+
+ it('should return true for valid signature', () => {
+ const body = 'test body';
+ // Calculate the actual HMAC for this body and secret.
+ const actualHash = createHmac('sha256', secret)
+ .update(body, 'utf8')
+ .digest('hex');
+ const validSignature = `sha256=${actualHash}`;
+
+ const result = verifySignature(body, validSignature, secret);
+
+ expect(result).toBe(true);
+ });
+
+ it('should return false for invalid signature', () => {
+ const body = 'test body';
+ const invalidSignature = 'sha256=invalid';
+
+ const result = verifySignature(body, invalidSignature, secret);
+
+ expect(result).toBe(false);
+ });
+
+ it('should handle signature without sha256= prefix', () => {
+ const body = 'test body';
+ const signature = '1234567890abcdef';
+
+ const result = verifySignature(body, signature, secret);
+
+ // This will be false since we're not mocking crypto properly for this test.
+ expect(typeof result).toBe('boolean');
+ });
+
+ it('should work with empty body', () => {
+ const body = '';
+ const signature = 'sha256=somehash';
+
+ const result = verifySignature(body, signature, secret);
+
+ expect(typeof result).toBe('boolean');
+ });
+
+ it('should work with special characters in body', () => {
+ const body = '{"test": "value with 特殊字符 and émojis 🎉"}';
+ const signature = 'sha256=somehash';
+
+ const result = verifySignature(body, signature, secret);
+
+ expect(typeof result).toBe('boolean');
+ });
+ });
+
+ describe('createAndEnqueueJob', () => {
+ const mockJob = { id: 123 };
+ const mockEnqueuedJob = { id: 'enqueued-123' };
+ const mockCloudJobs = {};
+
+ beforeEach(() => {
+ mockDb.insert.mockReturnValue({
+ values: vi.fn().mockReturnValue({
+ returning: vi.fn().mockResolvedValue([mockJob]),
+ }),
+ });
+ mockEnqueue.mockResolvedValue(mockEnqueuedJob);
+ });
+
+ it('should create and enqueue a job successfully', async () => {
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test issue',
+ body: 'Test body',
+ };
+
+ const result = await createAndEnqueueJob(type, payload);
+
+ expect(mockDb.insert).toHaveBeenCalledWith(mockCloudJobs);
+ expect(mockEnqueue).toHaveBeenCalledWith({
+ jobId: mockJob.id,
+ type,
+ payload,
+ });
+ expect(result).toEqual({
+ jobId: mockJob.id,
+ enqueuedJobId: mockEnqueuedJob.id,
+ });
+ });
+
+ it('should throw error when database insert fails', async () => {
+ mockDb.insert.mockReturnValue({
+ values: vi.fn().mockReturnValue({
+ returning: vi.fn().mockResolvedValue([]),
+ }),
+ });
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
+ 'Failed to create `cloudJobs` record.',
+ );
+ });
+
+ it('should throw error when enqueue fails to return job ID', async () => {
+ mockEnqueue.mockResolvedValue({ id: null });
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
+ 'Failed to get enqueued job ID.',
+ );
+ });
+
+ it('should throw error when enqueue returns undefined', async () => {
+ mockEnqueue.mockResolvedValue({});
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
+ 'Failed to get enqueued job ID.',
+ );
+ });
+
+ it('should handle different job types', async () => {
+ const type = 'github.pr.comment.respond';
+ const payload = {
+ repo: 'test/repo',
+ prNumber: 456,
+ prTitle: 'Test PR',
+ prBody: 'Test PR body',
+ prBranch: 'feature/test',
+ baseRef: 'main',
+ commentId: 789,
+ commentBody: 'Test comment',
+ commentAuthor: 'testuser',
+ commentType: 'issue_comment' as const,
+ commentUrl: 'https://github.com/test/repo/issues/456#issuecomment-789',
+ };
+
+ const result = await createAndEnqueueJob(type, payload);
+
+ expect(mockEnqueue).toHaveBeenCalledWith({
+ jobId: mockJob.id,
+ type,
+ payload,
+ });
+ expect(result).toEqual({
+ jobId: mockJob.id,
+ enqueuedJobId: mockEnqueuedJob.id,
+ });
+ });
+
+ it('should log the enqueued job', async () => {
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await createAndEnqueueJob(type, payload);
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ `🔗 Enqueued ${type} job (id: ${mockJob.id}) ->`,
+ payload,
+ );
+
+ consoleSpy.mockRestore();
+ });
+
+ it('should handle database connection errors', async () => {
+ mockDb.insert.mockImplementation(() => {
+ throw new Error('Database connection failed');
+ });
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
+ 'Database connection failed',
+ );
+ });
+
+ it('should handle enqueue service errors', async () => {
+ mockEnqueue.mockRejectedValue(new Error('Queue service unavailable'));
+
+ const type = 'github.issue.fix';
+ const payload = {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test',
+ body: 'Test',
+ };
+
+ await expect(createAndEnqueueJob(type, payload)).rejects.toThrow(
+ 'Queue service unavailable',
+ );
+ });
+ });
+
+ describe('integration tests', () => {
+ it('should work together in a realistic scenario', async () => {
+ // Test job creation in a realistic webhook scenario.
+ const mockJob = { id: 456 };
+ const mockEnqueuedJob = { id: 'job-456' };
+
+ mockDb.insert.mockReturnValue({
+ values: vi.fn().mockReturnValue({
+ returning: vi.fn().mockResolvedValue([mockJob]),
+ }),
+ });
+ mockEnqueue.mockResolvedValue(mockEnqueuedJob);
+
+ // Create job after successful verification.
+ const result = await createAndEnqueueJob('github.issue.fix', {
+ repo: 'test/repo',
+ issue: 123,
+ title: 'Test issue',
+ body: 'Test issue body',
+ });
+
+ expect(result).toEqual({
+ jobId: mockJob.id,
+ enqueuedJobId: mockEnqueuedJob.id,
+ });
+ });
+ });
+});
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/index.ts b/apps/roomote/src/app/api/webhooks/github/handlers/index.ts
new file mode 100644
index 0000000000..b077304145
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/index.ts
@@ -0,0 +1,5 @@
+export { verifySignature } from './utils';
+export { handleIssueEvent } from './issueHandler';
+export { handlePullRequestEvent } from './pullRequestHandler';
+export { handleIssueCommentEvent } from './issueCommentHandler';
+export { handlePullRequestReviewCommentEvent } from './pullRequestReviewCommentHandler';
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/issueCommentHandler.ts b/apps/roomote/src/app/api/webhooks/github/handlers/issueCommentHandler.ts
new file mode 100644
index 0000000000..08e4c440b2
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/issueCommentHandler.ts
@@ -0,0 +1,109 @@
+import { NextResponse } from 'next/server';
+import { z } from 'zod';
+
+import type { JobPayload } from '@/types';
+
+import { createAndEnqueueJob } from './utils';
+
+const githubIssueCommentWebhookSchema = z.object({
+ action: z.string(),
+ issue: z.object({
+ number: z.number(),
+ title: z.string(),
+ body: z.string().nullable(),
+ pull_request: z.object({ url: z.string() }).optional(),
+ }),
+ comment: z.object({
+ id: z.number(),
+ body: z.string(),
+ html_url: z.string(),
+ user: z.object({ login: z.string() }),
+ }),
+ repository: z.object({
+ full_name: z.string(),
+ }),
+});
+
+const githubPullRequestWebhookSchema = z.object({
+ number: z.number(),
+ title: z.string(),
+ body: z.string().nullable(),
+ head: z.object({ ref: z.string() }),
+ base: z.object({ ref: z.string() }),
+});
+
+export async function handleIssueCommentEvent(body: string) {
+ const data = githubIssueCommentWebhookSchema.parse(JSON.parse(body));
+ const { action, comment, issue, repository } = data;
+
+ if (action !== 'created') {
+ return NextResponse.json({ message: 'action_ignored' });
+ }
+
+ if (!comment.body.includes('@roomote')) {
+ return NextResponse.json({ message: 'no_roomote_mention' });
+ }
+
+ console.log('🗄️ Issue Comment Webhook ->', data);
+
+ // Handle PR comments (when comment is on a pull request)
+ if (issue.pull_request) {
+ const response = await fetch(issue.pull_request.url);
+
+ if (!response.ok) {
+ return NextResponse.json({ message: 'failed_to_fetch_pull_request' });
+ }
+
+ // Example:
+ // https://api.github.com/repos/RooCodeInc/Roo-Code/pulls/4796
+ const pull_request = githubPullRequestWebhookSchema.parse(
+ await response.json(),
+ );
+ console.log(`🗄️ Pull Request -> ${issue.pull_request.url}`, pull_request);
+
+ const payload: JobPayload<'github.pr.comment.respond'> = {
+ repo: repository.full_name,
+ prNumber: pull_request.number,
+ prTitle: pull_request.title,
+ prBody: pull_request.body || '',
+ prBranch: pull_request.head.ref,
+ baseRef: pull_request.base.ref,
+ commentId: comment.id,
+ commentBody: comment.body,
+ commentAuthor: comment.user.login,
+ commentType: 'issue_comment',
+ commentUrl: comment.html_url,
+ };
+
+ const { jobId, enqueuedJobId } = await createAndEnqueueJob(
+ 'github.pr.comment.respond',
+ payload,
+ );
+ return NextResponse.json({
+ message: 'pr_comment_job_enqueued',
+ jobId,
+ enqueuedJobId,
+ });
+ }
+
+ // Handle issue comments (when comment is on a regular issue)
+ const type = 'github.issue.comment.respond' as const;
+
+ const payload: JobPayload = {
+ repo: repository.full_name,
+ issueNumber: issue.number,
+ issueTitle: issue.title,
+ issueBody: issue.body || '',
+ commentId: comment.id,
+ commentBody: comment.body,
+ commentAuthor: comment.user.login,
+ commentUrl: comment.html_url,
+ };
+
+ const { jobId, enqueuedJobId } = await createAndEnqueueJob(type, payload);
+ return NextResponse.json({
+ message: 'issue_comment_job_enqueued',
+ jobId,
+ enqueuedJobId,
+ });
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/issueHandler.ts b/apps/roomote/src/app/api/webhooks/github/handlers/issueHandler.ts
new file mode 100644
index 0000000000..6e58795d87
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/issueHandler.ts
@@ -0,0 +1,45 @@
+import { NextResponse } from 'next/server';
+import { z } from 'zod';
+
+import type { JobPayload } from '@/types';
+
+import { createAndEnqueueJob } from './utils';
+
+const githubIssueWebhookSchema = z.object({
+ action: z.string(),
+ issue: z.object({
+ number: z.number(),
+ title: z.string(),
+ body: z.string().nullable(),
+ labels: z.array(z.object({ name: z.string() })),
+ }),
+ repository: z.object({
+ full_name: z.string(),
+ }),
+});
+
+export async function handleIssueEvent(body: string) {
+ const data = githubIssueWebhookSchema.parse(JSON.parse(body));
+ const { action, repository, issue } = data;
+
+ if (action !== 'opened') {
+ return NextResponse.json({ message: 'action_ignored' });
+ }
+
+ console.log('🗄️ Issue Webhook ->', data);
+
+ const payload: JobPayload<'github.issue.fix'> = {
+ repo: repository.full_name,
+ issue: issue.number,
+ title: issue.title,
+ body: issue.body || '',
+ labels: issue.labels.map(({ name }) => name),
+ };
+
+ const { jobId, enqueuedJobId } = await createAndEnqueueJob(
+ 'github.issue.fix',
+ payload,
+ );
+
+ return NextResponse.json({ message: 'job_enqueued', jobId, enqueuedJobId });
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestHandler.ts b/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestHandler.ts
new file mode 100644
index 0000000000..c762f7db3b
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestHandler.ts
@@ -0,0 +1,71 @@
+import { NextResponse } from 'next/server';
+import { eq } from 'drizzle-orm';
+import { z } from 'zod';
+
+import { db, cloudJobs } from '@/db';
+import { SlackNotifier } from '@/lib/slack';
+
+const githubPullRequestWebhookSchema = z.object({
+ action: z.string(),
+ pull_request: z.object({
+ number: z.number(),
+ title: z.string(),
+ body: z.string().nullable(),
+ html_url: z.string(),
+ }),
+ repository: z.object({
+ full_name: z.string(),
+ }),
+});
+
+export async function handlePullRequestEvent(body: string) {
+ const data = githubPullRequestWebhookSchema.parse(JSON.parse(body));
+ const { action, pull_request, repository } = data;
+
+ if (action !== 'opened') {
+ return NextResponse.json({ message: 'action_ignored' });
+ }
+
+ console.log('🗄️ PR Webhook ->', data);
+
+ // Extract issue number from PR title or body (looking for "Fixes #123" pattern).
+ const issueNumberMatch =
+ pull_request.title.match(/(?:fixes|closes|resolves)\s+#(\d+)/i) ||
+ (pull_request.body &&
+ pull_request.body.match(/(?:fixes|closes|resolves)\s+#(\d+)/i));
+
+ if (!issueNumberMatch) {
+ return NextResponse.json({ message: 'no_issue_reference_found' });
+ }
+
+ const issueNumber = parseInt(issueNumberMatch[1]!, 10);
+
+ // Find the job that corresponds to this issue.
+ const jobs = await db
+ .select()
+ .from(cloudJobs)
+ .where(eq(cloudJobs.type, 'github.issue.fix'));
+
+ // Filter jobs to find the one matching this repo and issue.
+ const job = jobs.find((j) => {
+ const payload = j.payload as { repo: string; issue: number };
+ return (
+ payload.repo === repository.full_name && payload.issue === issueNumber
+ );
+ });
+
+ if (!job || !job.slackThreadTs) {
+ console.log('No job found or no slack thread for issue', issueNumber);
+ return NextResponse.json({ message: 'no_job_or_slack_thread_found' });
+ }
+
+ const notifier = new SlackNotifier();
+
+ await notifier.postTaskUpdated(
+ job.slackThreadTs,
+ `🎉 Pull request created: <${pull_request.html_url}|PR #${pull_request.number}>\n*${pull_request.title}*`,
+ 'success',
+ );
+
+ return NextResponse.json({ message: 'slack_notification_sent' });
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestReviewCommentHandler.ts b/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestReviewCommentHandler.ts
new file mode 100644
index 0000000000..bd83cfd092
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/pullRequestReviewCommentHandler.ts
@@ -0,0 +1,70 @@
+import { NextResponse } from 'next/server';
+import { z } from 'zod';
+
+import type { JobPayload } from '@/types';
+
+import { createAndEnqueueJob } from './utils';
+
+export const githubPullRequestReviewCommentWebhookSchema = z.object({
+ action: z.string(),
+ comment: z.object({
+ id: z.number(),
+ body: z.string(),
+ html_url: z.string(),
+ user: z.object({
+ login: z.string(),
+ }),
+ }),
+ pull_request: z.object({
+ number: z.number(),
+ title: z.string(),
+ body: z.string().nullable(),
+ head: z.object({
+ ref: z.string(),
+ }),
+ base: z.object({
+ ref: z.string(),
+ }),
+ }),
+ repository: z.object({
+ full_name: z.string(),
+ }),
+});
+
+export async function handlePullRequestReviewCommentEvent(body: string) {
+ const data = githubPullRequestReviewCommentWebhookSchema.parse(
+ JSON.parse(body),
+ );
+ const { action, comment, pull_request, repository } = data;
+
+ if (action !== 'created') {
+ return NextResponse.json({ message: 'action_ignored' });
+ }
+
+ if (!comment.body.includes('@roomote')) {
+ return NextResponse.json({ message: 'no_roomote_mention' });
+ }
+
+ console.log('🗄️ PR Review Comment Webhook ->', data);
+
+ const payload: JobPayload<'github.pr.comment.respond'> = {
+ repo: repository.full_name,
+ prNumber: pull_request.number,
+ prTitle: pull_request.title,
+ prBody: pull_request.body || '',
+ prBranch: pull_request.head.ref,
+ baseRef: pull_request.base.ref,
+ commentId: comment.id,
+ commentBody: comment.body,
+ commentAuthor: comment.user.login,
+ commentType: 'review_comment',
+ commentUrl: comment.html_url,
+ };
+
+ const { jobId, enqueuedJobId } = await createAndEnqueueJob(
+ 'github.pr.comment.respond',
+ payload,
+ );
+
+ return NextResponse.json({ message: 'job_enqueued', jobId, enqueuedJobId });
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/handlers/utils.ts b/apps/roomote/src/app/api/webhooks/github/handlers/utils.ts
new file mode 100644
index 0000000000..0e600fe7f5
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/handlers/utils.ts
@@ -0,0 +1,40 @@
+import { createHmac } from 'crypto';
+
+import type { JobType, JobPayload } from '@/types';
+import { db, cloudJobs } from '@/db';
+import { enqueue } from '@/lib';
+
+export function verifySignature(
+ body: string,
+ signature: string,
+ secret: string,
+): boolean {
+ const expectedSignature = createHmac('sha256', secret)
+ .update(body, 'utf8')
+ .digest('hex');
+ const receivedSignature = signature.replace('sha256=', '');
+ return expectedSignature === receivedSignature;
+}
+
+export async function createAndEnqueueJob(
+ type: T,
+ payload: JobPayload,
+): Promise<{ jobId: number; enqueuedJobId: string }> {
+ const [job] = await db
+ .insert(cloudJobs)
+ .values({ type, payload, status: 'pending' })
+ .returning();
+
+ if (!job) {
+ throw new Error('Failed to create `cloudJobs` record.');
+ }
+
+ const enqueuedJob = await enqueue({ jobId: job.id, type, payload });
+ console.log(`🔗 Enqueued ${type} job (id: ${job.id}) ->`, payload);
+
+ if (!enqueuedJob.id) {
+ throw new Error('Failed to get enqueued job ID.');
+ }
+
+ return { jobId: job.id, enqueuedJobId: enqueuedJob.id };
+}
diff --git a/apps/roomote/src/app/api/webhooks/github/route.ts b/apps/roomote/src/app/api/webhooks/github/route.ts
new file mode 100644
index 0000000000..7e75f10029
--- /dev/null
+++ b/apps/roomote/src/app/api/webhooks/github/route.ts
@@ -0,0 +1,55 @@
+import { NextRequest, NextResponse } from 'next/server';
+import { z } from 'zod';
+
+import {
+ verifySignature,
+ handleIssueEvent,
+ handlePullRequestEvent,
+ handleIssueCommentEvent,
+ handlePullRequestReviewCommentEvent,
+} from './handlers';
+
+export async function POST(request: NextRequest) {
+ try {
+ const signature = request.headers.get('x-hub-signature-256');
+
+ if (!signature) {
+ return NextResponse.json({ error: 'missing_signature' }, { status: 400 });
+ }
+
+ const body = await request.text();
+
+ if (!verifySignature(body, signature, process.env.GH_WEBHOOK_SECRET!)) {
+ return NextResponse.json({ error: 'invalid_signature' }, { status: 401 });
+ }
+
+ const event = request.headers.get('x-github-event');
+ console.log(`🛎️ GitHub Webhook Event -> ${event}`);
+
+ if (event === 'issues') {
+ return await handleIssueEvent(body);
+ } else if (event === 'pull_request') {
+ return await handlePullRequestEvent(body);
+ } else if (event === 'issue_comment') {
+ return await handleIssueCommentEvent(body);
+ } else if (event === 'pull_request_review_comment') {
+ return await handlePullRequestReviewCommentEvent(body);
+ } else {
+ return NextResponse.json({ message: 'event_ignored' });
+ }
+ } catch (error) {
+ console.error('GitHub Webhook Error:', error);
+
+ if (error instanceof z.ZodError) {
+ return NextResponse.json(
+ { error: 'bad_request', details: error.errors },
+ { status: 400 },
+ );
+ }
+
+ return NextResponse.json(
+ { error: 'internal_server_error' },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/roomote/src/app/layout.tsx b/apps/roomote/src/app/layout.tsx
new file mode 100644
index 0000000000..7b8fca91bd
--- /dev/null
+++ b/apps/roomote/src/app/layout.tsx
@@ -0,0 +1,18 @@
+import type { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Cloud Agents',
+ description: 'Roo Code task execution service',
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/apps/roomote/src/app/page.tsx b/apps/roomote/src/app/page.tsx
new file mode 100644
index 0000000000..5806dda291
--- /dev/null
+++ b/apps/roomote/src/app/page.tsx
@@ -0,0 +1,3 @@
+export default function Page() {
+ return Hello, World!
;
+}
diff --git a/apps/roomote/src/db/index.ts b/apps/roomote/src/db/index.ts
new file mode 100644
index 0000000000..526c25304c
--- /dev/null
+++ b/apps/roomote/src/db/index.ts
@@ -0,0 +1,11 @@
+import { drizzle } from 'drizzle-orm/postgres-js';
+import postgres from 'postgres';
+
+import { schema } from './schema';
+
+export const db = drizzle(
+ postgres(process.env.DATABASE_URL!, { prepare: false }),
+ { schema },
+);
+
+export * from './schema';
diff --git a/apps/roomote/src/db/schema.ts b/apps/roomote/src/db/schema.ts
new file mode 100644
index 0000000000..5eb82dbbd7
--- /dev/null
+++ b/apps/roomote/src/db/schema.ts
@@ -0,0 +1,34 @@
+import { pgTable, text, timestamp, integer, jsonb } from 'drizzle-orm/pg-core';
+
+import type { JobType, JobStatus, JobPayload } from '@/types';
+
+/**
+ * cloudJobs
+ */
+
+export const cloudJobs = pgTable('cloud_jobs', {
+ id: integer().primaryKey().generatedAlwaysAsIdentity(),
+ type: text().notNull().$type(),
+ status: text().notNull().default('pending').$type(),
+ payload: jsonb().notNull().$type(),
+ result: jsonb(),
+ error: text(),
+ slackThreadTs: text('slack_thread_ts'),
+ startedAt: timestamp('started_at'),
+ completedAt: timestamp('completed_at'),
+ createdAt: timestamp('created_at').notNull().defaultNow(),
+});
+
+export type CloudJob = typeof cloudJobs.$inferSelect;
+
+export type InsertCloudJob = typeof cloudJobs.$inferInsert;
+
+export type UpdateCloudJob = Partial>;
+
+/**
+ * schema
+ */
+
+export const schema = {
+ cloudJobs,
+};
diff --git a/apps/roomote/src/lib/__tests__/controller.test.ts b/apps/roomote/src/lib/__tests__/controller.test.ts
new file mode 100644
index 0000000000..e2c12f4935
--- /dev/null
+++ b/apps/roomote/src/lib/__tests__/controller.test.ts
@@ -0,0 +1,95 @@
+// npx vitest src/lib/__tests__/controller.test.ts
+
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
+
+const mockQueue = {
+ getWaiting: vi.fn(() => Promise.resolve([])),
+ getActive: vi.fn(() => Promise.resolve([])),
+ close: vi.fn(() => Promise.resolve()),
+ on: vi.fn(),
+};
+
+const mockSpawn = vi.fn(() => ({
+ stdout: { pipe: vi.fn() },
+ stderr: { pipe: vi.fn() },
+ on: vi.fn(),
+ unref: vi.fn(),
+}));
+
+const mockCreateWriteStream = vi.fn(() => ({
+ end: vi.fn(),
+}));
+
+vi.mock('../redis', () => ({
+ redis: { host: 'localhost', port: 6379 },
+}));
+
+vi.mock('child_process', () => ({
+ spawn: mockSpawn,
+}));
+
+vi.mock('fs', () => ({
+ default: {
+ existsSync: vi.fn(() => false),
+ createWriteStream: mockCreateWriteStream,
+ },
+}));
+
+const mockQueueConstructor = vi.fn(() => mockQueue);
+
+vi.mock('bullmq', () => ({
+ Queue: mockQueueConstructor,
+}));
+
+describe('WorkerController', () => {
+ let WorkerController: typeof import('../controller').WorkerController;
+
+ beforeEach(async () => {
+ vi.clearAllMocks();
+ const controllerModule = await import('../controller');
+ WorkerController = controllerModule.WorkerController;
+ });
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ it('should create a Queue instance with correct configuration', () => {
+ const controller = new WorkerController();
+
+ expect(mockQueueConstructor).toHaveBeenCalledWith('roomote', {
+ connection: { host: 'localhost', port: 6379 },
+ });
+
+ expect(controller).toBeDefined();
+ });
+
+ it('should handle queue monitoring without errors', async () => {
+ const controller = new WorkerController();
+
+ await controller.start();
+ expect(controller).toBeDefined();
+
+ await controller.stop();
+ expect(mockQueue.close).toHaveBeenCalled();
+ });
+
+ it('should handle worker spawning logic', () => {
+ const controller = new WorkerController();
+ expect(mockSpawn).toBeDefined();
+ expect(mockCreateWriteStream).toBeDefined();
+ expect(controller).toBeDefined();
+ });
+
+ it('should track running state correctly', async () => {
+ const controller = new WorkerController();
+
+ expect(controller.isRunning).toBeFalsy();
+
+ await controller.start();
+ expect(controller.isRunning).toBeTruthy();
+
+ await controller.stop();
+ expect(controller.isRunning).toBeFalsy();
+ });
+});
diff --git a/apps/roomote/src/lib/controller.ts b/apps/roomote/src/lib/controller.ts
new file mode 100644
index 0000000000..12bd78e457
--- /dev/null
+++ b/apps/roomote/src/lib/controller.ts
@@ -0,0 +1,159 @@
+import { spawn } from 'child_process';
+import fs from 'fs';
+import { Queue } from 'bullmq';
+
+import { redis } from './redis';
+
+export class WorkerController {
+ private readonly POLL_INTERVAL_MS = 5000;
+ private readonly MAX_WORKERS = 5;
+
+ private queue: Queue;
+ public isRunning = false;
+ private pollingInterval: NodeJS.Timeout | null = null;
+ private activeWorkers = new Set();
+
+ constructor() {
+ this.queue = new Queue('roomote', { connection: redis });
+ }
+
+ async start() {
+ if (this.isRunning) {
+ console.log('Controller is already running');
+ return;
+ }
+
+ this.isRunning = true;
+ console.log('Worker controller started');
+
+ await this.checkAndSpawnWorker();
+
+ this.pollingInterval = setInterval(async () => {
+ await this.checkAndSpawnWorker();
+ }, this.POLL_INTERVAL_MS);
+ }
+
+ async stop() {
+ if (!this.isRunning) {
+ return;
+ }
+
+ this.isRunning = false;
+ console.log('Stopping worker controller...');
+
+ if (this.pollingInterval) {
+ clearInterval(this.pollingInterval);
+ this.pollingInterval = null;
+ }
+
+ await this.queue.close();
+ console.log('Worker controller stopped');
+ }
+
+ private async checkAndSpawnWorker() {
+ try {
+ const waiting = await this.queue.getWaiting();
+ const active = await this.queue.getActive();
+
+ const waitingCount = waiting.length;
+ const activeCount = active.length;
+
+ console.log(
+ `Queue status: ${waitingCount} waiting, ${activeCount} active, ${this.activeWorkers.size} spawned workers`,
+ );
+
+ if (waitingCount > 0 && this.activeWorkers.size < this.MAX_WORKERS) {
+ await this.spawnWorker();
+ }
+ } catch (error) {
+ console.error('Error checking queue status:', error);
+ }
+ }
+
+ private async spawnWorker() {
+ const workerId = `worker-${Date.now()}`;
+
+ try {
+ console.log(`Spawning worker: ${workerId}`);
+ const isRunningInDocker = fs.existsSync('/.dockerenv');
+
+ const dockerArgs = [
+ `--name roomote-${workerId}`,
+ '--rm',
+ '--network roo-code-cloud_default',
+ '-e HOST_EXECUTION_METHOD=docker',
+ `-e GH_TOKEN=${process.env.GH_TOKEN}`,
+ `-e DATABASE_URL=${process.env.DATABASE_URL}`,
+ `-e REDIS_URL=${process.env.REDIS_URL}`,
+ `-e NODE_ENV=${process.env.NODE_ENV}`,
+ '-v /var/run/docker.sock:/var/run/docker.sock',
+ '-v /tmp/roomote:/var/log/roomote',
+ ];
+
+ const cliCommand = 'pnpm worker';
+
+ const command = isRunningInDocker
+ ? `docker run ${dockerArgs.join(' ')} roomote-worker sh -c "${cliCommand}"`
+ : cliCommand;
+
+ console.log('Spawning worker with command:', command);
+
+ const childProcess = spawn('sh', ['-c', command], {
+ detached: true,
+ stdio: ['ignore', 'pipe', 'pipe'],
+ });
+
+ if (childProcess.stdout) {
+ childProcess.stdout.on('data', (data) => {
+ console.log(data.toString());
+ });
+ }
+
+ if (childProcess.stderr) {
+ childProcess.stderr.on('data', (data) => {
+ console.error(data.toString());
+ });
+ }
+
+ this.activeWorkers.add(workerId);
+
+ childProcess.on('exit', (code) => {
+ console.log(`Worker ${workerId} exited with code ${code}`);
+ this.activeWorkers.delete(workerId);
+ });
+
+ childProcess.on('error', (error) => {
+ console.error(`Worker ${workerId} error:`, error);
+ this.activeWorkers.delete(workerId);
+ });
+
+ // Detach the process so it can run independently.
+ childProcess.unref();
+ } catch (error) {
+ console.error(`Failed to spawn worker ${workerId}:`, error);
+ this.activeWorkers.delete(workerId);
+ }
+ }
+}
+
+// Only run if this file is executed directly (not imported).
+if (import.meta.url === `file://${process.argv[1]}`) {
+ const controller = new WorkerController();
+
+ process.on('SIGTERM', async () => {
+ console.log('SIGTERM -> shutting down controller gracefully...');
+ await controller.stop();
+ process.exit(0);
+ });
+
+ process.on('SIGINT', async () => {
+ console.log('SIGINT -> shutting down controller gracefully...');
+ await controller.stop();
+ process.exit(0);
+ });
+
+ controller.start().catch((error) => {
+ console.error('Failed to start controller:', error);
+ process.exit(1);
+ });
+}
diff --git a/apps/roomote/src/lib/index.ts b/apps/roomote/src/lib/index.ts
new file mode 100644
index 0000000000..ce0efeaefe
--- /dev/null
+++ b/apps/roomote/src/lib/index.ts
@@ -0,0 +1,2 @@
+export { redis } from './redis';
+export { enqueue } from './queue';
diff --git a/apps/roomote/src/lib/job.ts b/apps/roomote/src/lib/job.ts
new file mode 100644
index 0000000000..8f45335de6
--- /dev/null
+++ b/apps/roomote/src/lib/job.ts
@@ -0,0 +1,133 @@
+import { eq } from 'drizzle-orm';
+import { Job } from 'bullmq';
+
+import { db, cloudJobs, type UpdateCloudJob } from '@/db';
+import type { JobType, JobStatus, JobParams, JobPayload } from '@/types';
+
+import { fixGitHubIssue } from './jobs/fixGitHubIssue';
+import { processPullRequestComment } from './jobs/processPullRequestComment';
+import { processIssueComment } from './jobs/processIssueComment';
+
+export async function processJob({
+ data: { type, payload, jobId },
+ ...job
+}: Job>) {
+ console.log(
+ `[${job.name} | ${job.id}] Processing job ${jobId} of type ${type}`,
+ );
+
+ try {
+ let result: unknown;
+
+ switch (type) {
+ case 'github.issue.fix':
+ result = await fixGitHubIssue(
+ payload as JobPayload<'github.issue.fix'>,
+ {
+ onTaskStarted: async (
+ slackThreadTs: string | null,
+ _rooTaskId: string,
+ ) => {
+ if (slackThreadTs) {
+ await updateJobStatus(
+ jobId,
+ 'processing',
+ undefined,
+ undefined,
+ slackThreadTs,
+ );
+ }
+ },
+ },
+ );
+
+ break;
+ case 'github.issue.comment.respond':
+ result = await processIssueComment(
+ payload as JobPayload<'github.issue.comment.respond'>,
+ {
+ onTaskStarted: async (
+ slackThreadTs: string | null,
+ _rooTaskId: string,
+ ) => {
+ if (slackThreadTs) {
+ await updateJobStatus(
+ jobId,
+ 'processing',
+ undefined,
+ undefined,
+ slackThreadTs,
+ );
+ }
+ },
+ },
+ );
+
+ break;
+ case 'github.pr.comment.respond':
+ result = await processPullRequestComment(
+ payload as JobPayload<'github.pr.comment.respond'>,
+ {
+ onTaskStarted: async (
+ slackThreadTs: string | null,
+ _rooTaskId: string,
+ ) => {
+ if (slackThreadTs) {
+ await updateJobStatus(
+ jobId,
+ 'processing',
+ undefined,
+ undefined,
+ slackThreadTs,
+ );
+ }
+ },
+ },
+ );
+
+ break;
+ default:
+ throw new Error(`Unknown job type: ${type}`);
+ }
+
+ await updateJobStatus(jobId, 'completed', result);
+ console.log(
+ `[${job.name} | ${job.id}] Job ${jobId} completed successfully`,
+ );
+ } catch (error) {
+ console.error(`[${job.name} | ${job.id}] Job ${jobId} failed:`, error);
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ await updateJobStatus(jobId, 'failed', undefined, errorMessage);
+ throw error; // Re-throw to mark job as failed in BullMQ.
+ }
+}
+
+async function updateJobStatus(
+ jobId: number,
+ status: JobStatus,
+ result?: unknown,
+ error?: string,
+ slackThreadTs?: string,
+) {
+ const values: UpdateCloudJob = { status };
+
+ if (status === 'processing') {
+ values.startedAt = new Date();
+ } else if (status === 'completed' || status === 'failed') {
+ values.completedAt = new Date();
+
+ if (result) {
+ values.result = result;
+ }
+
+ if (error) {
+ values.error = error;
+ }
+ }
+
+ if (slackThreadTs) {
+ values.slackThreadTs = slackThreadTs;
+ }
+
+ await db.update(cloudJobs).set(values).where(eq(cloudJobs.id, jobId));
+}
diff --git a/apps/roomote/src/lib/jobs/fixGitHubIssue.ts b/apps/roomote/src/lib/jobs/fixGitHubIssue.ts
new file mode 100644
index 0000000000..49dfc3f1b5
--- /dev/null
+++ b/apps/roomote/src/lib/jobs/fixGitHubIssue.ts
@@ -0,0 +1,59 @@
+import * as path from 'path';
+import * as os from 'node:os';
+
+import type { JobType, JobPayload } from '@/types';
+
+import { runTask, type RunTaskCallbacks } from '../runTask';
+import { Logger } from '../logger';
+
+const jobType: JobType = 'github.issue.fix';
+
+type FixGitHubIssueJobPayload = JobPayload<'github.issue.fix'>;
+
+export async function fixGitHubIssue(
+ jobPayload: FixGitHubIssueJobPayload,
+ callbacks?: RunTaskCallbacks,
+): Promise<{
+ repo: string;
+ issue: number;
+ result: unknown;
+}> {
+ const prompt = `
+Fix the following GitHub issue:
+
+Repository: ${jobPayload.repo}
+Issue #${jobPayload.issue}: ${jobPayload.title}
+
+Description:
+${jobPayload.body}
+
+${jobPayload.labels && jobPayload.labels.length > 0 ? `Labels: ${jobPayload.labels.join(', ')}` : ''}
+
+Please analyze the issue, understand what needs to be fixed, and implement a solution.
+
+When you're finished:
+- Create a git branch to store your work (git checkout -b fix-${jobPayload.issue})
+- Commit your changes to this branch (git commit -m "Fixes #${jobPayload.issue}")
+- Push your branch to the remote repository (git push --set-upstream origin fix-${jobPayload.issue})
+- Submit a pull request using the "gh" command line tool (gh pr create --title "Fixes #${jobPayload.issue}\n\n[Your PR description here.]" --fill)
+
+Your job isn't done until you've created a pull request. Try to solve any git issues that arise while creating your branch and submitting your pull request.
+`.trim();
+
+ const { repo, issue } = jobPayload;
+
+ const result = await runTask({
+ jobType,
+ jobPayload,
+ prompt,
+ publish: async () => {},
+ logger: new Logger({
+ logDir: path.resolve(os.tmpdir(), 'logs'),
+ filename: 'worker.log',
+ tag: 'worker',
+ }),
+ callbacks,
+ });
+
+ return { repo, issue, result };
+}
diff --git a/apps/roomote/src/lib/jobs/processIssueComment.ts b/apps/roomote/src/lib/jobs/processIssueComment.ts
new file mode 100644
index 0000000000..309706fd84
--- /dev/null
+++ b/apps/roomote/src/lib/jobs/processIssueComment.ts
@@ -0,0 +1,71 @@
+import * as path from 'path';
+import * as os from 'node:os';
+
+import type { JobType, JobPayload } from '@/types';
+
+import { runTask, type RunTaskCallbacks } from '../runTask';
+import { Logger } from '../logger';
+
+const jobType: JobType = 'github.issue.comment.respond';
+
+type ProcessIssueCommentJobPayload = JobPayload<'github.issue.comment.respond'>;
+
+export async function processIssueComment(
+ jobPayload: ProcessIssueCommentJobPayload,
+ callbacks?: RunTaskCallbacks,
+): Promise<{
+ repo: string;
+ issueNumber: number;
+ commentId: number;
+ result: unknown;
+}> {
+ const prompt = `
+Respond to the following GitHub Issue comment:
+
+Repository: ${jobPayload.repo}
+Issue #${jobPayload.issueNumber}: ${jobPayload.issueTitle}
+
+Issue Description:
+${jobPayload.issueBody || 'No description provided'}
+
+Comment by @${jobPayload.commentAuthor}:
+${jobPayload.commentBody}
+
+Comment URL: ${jobPayload.commentUrl}
+
+Please analyze the comment and provide a helpful response. The comment mentions @roomote, which means the user wants you to engage with their question or request.
+
+Instructions:
+1. Read and understand the context of the issue and the specific comment
+2. Provide a thoughtful, helpful response to the comment
+3. If the comment asks a question, try to answer it based on your knowledge
+4. If the comment requests an action, explain what you can do or suggest next steps
+5. If the comment is unclear, ask for clarification
+6. Use the GitHub CLI or API to respond to the comment with your message
+
+Your goal is to be helpful and engage meaningfully with the community member who mentioned @roomote.
+
+Use the "gh" command line tool to respond to the comment:
+gh api repos/${jobPayload.repo}/issues/comments/${jobPayload.commentId} --method PATCH --field body="Your response here"
+
+Or create a new comment response:
+gh api repos/${jobPayload.repo}/issues/${jobPayload.issueNumber}/comments --method POST --field body="Your response here"
+`.trim();
+
+ const { repo, issueNumber, commentId } = jobPayload;
+
+ const result = await runTask({
+ jobType,
+ jobPayload,
+ prompt,
+ publish: async () => {},
+ logger: new Logger({
+ logDir: path.resolve(os.tmpdir(), 'logs'),
+ filename: 'worker.log',
+ tag: 'worker',
+ }),
+ callbacks,
+ });
+
+ return { repo, issueNumber, commentId, result };
+}
diff --git a/apps/roomote/src/lib/jobs/processPullRequestComment.ts b/apps/roomote/src/lib/jobs/processPullRequestComment.ts
new file mode 100644
index 0000000000..e2cadd88cb
--- /dev/null
+++ b/apps/roomote/src/lib/jobs/processPullRequestComment.ts
@@ -0,0 +1,85 @@
+import * as path from 'path';
+import * as os from 'node:os';
+
+import type { JobType, JobPayload } from '@/types';
+
+import { runTask, type RunTaskCallbacks } from '../runTask';
+import { Logger } from '../logger';
+
+const jobType: JobType = 'github.pr.comment.respond';
+
+type ProcessPullRequestCommentJobPayload =
+ JobPayload<'github.pr.comment.respond'>;
+
+export async function processPullRequestComment(
+ jobPayload: ProcessPullRequestCommentJobPayload,
+ callbacks?: RunTaskCallbacks,
+): Promise<{
+ repo: string;
+ prNumber: number;
+ commentId: number;
+ result: unknown;
+}> {
+ const prompt = `
+Process the following GitHub Pull Request comment:
+
+Repository: ${jobPayload.repo}
+Pull Request #${jobPayload.prNumber}: ${jobPayload.prTitle}
+
+PR Description:
+${jobPayload.prBody || 'No description provided'}
+
+Comment by @${jobPayload.commentAuthor}:
+${jobPayload.commentBody}
+
+Comment Type: ${jobPayload.commentType}
+Comment URL: ${jobPayload.commentUrl}
+
+PR Branch: ${jobPayload.prBranch}
+Base Branch: ${jobPayload.baseRef}
+
+Please analyze the comment and understand what changes are being requested. Then implement the requested changes directly on the PR branch AND respond to the comment.
+
+Instructions:
+1. First, respond to the comment to acknowledge the request and explain what you'll do
+2. Check out the PR branch: git checkout ${jobPayload.prBranch}
+3. Analyze the comment in the context of the pull request
+4. Make the appropriate changes based on the comment
+5. Commit your changes with a clear message referencing the comment
+6. Push the changes to the same PR branch: git push origin ${jobPayload.prBranch}
+7. After completing the changes, update your response or add a follow-up comment with the results
+
+The comment mentions @roomote, which means the user wants you to process this request. Make sure to:
+- Respond to the comment first to acknowledge the request
+- Understand the context of the PR and the specific request in the comment
+- Implement the requested changes thoughtfully
+- Test your changes if applicable
+- Write clear commit messages that reference the comment
+- Provide updates on the progress and results
+
+Use the GitHub CLI to respond to the comment:
+gh api repos/${jobPayload.repo}/issues/comments/${jobPayload.commentId} --method PATCH --field body="Your response here"
+
+Or create a new comment response:
+gh api repos/${jobPayload.repo}/issues/${jobPayload.prNumber}/comments --method POST --field body="Your response here"
+
+Do not create a new pull request - work directly on the existing PR branch.
+`.trim();
+
+ const { repo, prNumber, commentId } = jobPayload;
+
+ const result = await runTask({
+ jobType,
+ jobPayload,
+ prompt,
+ publish: async () => {},
+ logger: new Logger({
+ logDir: path.resolve(os.tmpdir(), 'logs'),
+ filename: 'worker.log',
+ tag: 'worker',
+ }),
+ callbacks,
+ });
+
+ return { repo, prNumber, commentId, result };
+}
diff --git a/apps/roomote/src/lib/logger.ts b/apps/roomote/src/lib/logger.ts
new file mode 100644
index 0000000000..35a84b27c1
--- /dev/null
+++ b/apps/roomote/src/lib/logger.ts
@@ -0,0 +1,86 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+enum LogLevel {
+ INFO = 'INFO',
+ ERROR = 'ERROR',
+ WARN = 'WARN',
+ DEBUG = 'DEBUG',
+}
+
+interface LoggerOptions {
+ logDir: string;
+ filename: string;
+ tag: string;
+}
+
+export class Logger {
+ private logStream: fs.WriteStream | undefined;
+ private logFilePath: string;
+ private tag: string;
+
+ constructor({ logDir, filename, tag }: LoggerOptions) {
+ this.tag = tag;
+ this.logFilePath = path.join(logDir, filename);
+ this.initializeLogger(logDir);
+ }
+
+ private initializeLogger(logDir: string): void {
+ try {
+ fs.mkdirSync(logDir, { recursive: true });
+ } catch (error) {
+ console.error(`Failed to create log directory ${logDir}:`, error);
+ }
+
+ try {
+ this.logStream = fs.createWriteStream(this.logFilePath, { flags: 'a' });
+ } catch (error) {
+ console.error(`Failed to create log file ${this.logFilePath}:`, error);
+ }
+ }
+
+ private writeToLog(level: LogLevel, message: string, ...args: unknown[]) {
+ try {
+ const timestamp = new Date().toISOString();
+
+ const logLine = `[${timestamp} | ${level} | ${this.tag}] ${message} ${
+ args.length > 0 ? JSON.stringify(args) : ''
+ }\n`;
+
+ console.log(logLine.trim());
+
+ if (this.logStream) {
+ this.logStream.write(logLine);
+ }
+ } catch (error) {
+ console.error(`Failed to write to log file ${this.logFilePath}:`, error);
+ }
+ }
+
+ public info(message: string, ...args: unknown[]): void {
+ this.writeToLog(LogLevel.INFO, message, ...args);
+ }
+
+ public error(message: string, ...args: unknown[]): void {
+ this.writeToLog(LogLevel.ERROR, message, ...args);
+ }
+
+ public warn(message: string, ...args: unknown[]): void {
+ this.writeToLog(LogLevel.WARN, message, ...args);
+ }
+
+ public debug(message: string, ...args: unknown[]): void {
+ this.writeToLog(LogLevel.DEBUG, message, ...args);
+ }
+
+ public log(message: string, ...args: unknown[]): void {
+ this.info(message, ...args);
+ }
+
+ public close(): void {
+ if (this.logStream) {
+ this.logStream.end();
+ this.logStream = undefined;
+ }
+ }
+}
diff --git a/apps/roomote/src/lib/queue.ts b/apps/roomote/src/lib/queue.ts
new file mode 100644
index 0000000000..a36fd79c10
--- /dev/null
+++ b/apps/roomote/src/lib/queue.ts
@@ -0,0 +1,23 @@
+import { Queue, Job } from 'bullmq';
+
+import type { JobTypes, JobPayload, JobParams } from '@/types';
+
+import { redis } from './redis';
+
+const queue = new Queue('roomote', {
+ connection: redis,
+ defaultJobOptions: {
+ removeOnComplete: 100,
+ removeOnFail: 50,
+ attempts: 3,
+ backoff: { type: 'exponential', delay: 2000 },
+ },
+});
+
+export async function enqueue(
+ params: JobParams,
+): Promise>> {
+ return queue.add(params.type, params, {
+ jobId: `${params.type}-${params.jobId}`,
+ });
+}
diff --git a/apps/roomote/src/lib/redis.ts b/apps/roomote/src/lib/redis.ts
new file mode 100644
index 0000000000..7a3554f7fa
--- /dev/null
+++ b/apps/roomote/src/lib/redis.ts
@@ -0,0 +1,8 @@
+import IORedis from 'ioredis';
+
+export const redis = new IORedis(
+ process.env.REDIS_URL || 'redis://localhost:6379',
+ {
+ maxRetriesPerRequest: null,
+ },
+);
diff --git a/apps/roomote/src/lib/runTask.ts b/apps/roomote/src/lib/runTask.ts
new file mode 100644
index 0000000000..92a14f7b61
--- /dev/null
+++ b/apps/roomote/src/lib/runTask.ts
@@ -0,0 +1,334 @@
+import * as path from 'path';
+import * as os from 'node:os';
+import * as crypto from 'node:crypto';
+
+import pWaitFor from 'p-wait-for';
+import { execa } from 'execa';
+
+import {
+ type TaskEvent,
+ TaskCommandName,
+ RooCodeEventName,
+ IpcMessageType,
+ EVALS_SETTINGS,
+} from '@roo-code/types';
+import { IpcClient } from '@roo-code-cloud/ipc';
+
+import type { JobPayload, JobType } from '@/types';
+
+import { Logger } from './logger';
+import { isDockerContainer } from './utils';
+import { SlackNotifier } from './slack';
+
+const TIMEOUT = 30 * 60 * 1_000;
+
+class SubprocessTimeoutError extends Error {
+ constructor(timeout: number) {
+ super(`Subprocess timeout after ${timeout}ms`);
+ this.name = 'SubprocessTimeoutError';
+ }
+}
+
+export type RunTaskCallbacks = {
+ onTaskStarted?: (
+ slackThreadTs: string | null,
+ rooTaskId: string,
+ ) => Promise;
+ onTaskAborted?: (slackThreadTs: string | null) => Promise;
+ onTaskCompleted?: (
+ slackThreadTs: string | null,
+ success: boolean,
+ duration: number,
+ rooTaskId?: string,
+ ) => Promise;
+ onTaskTimedOut?: (slackThreadTs: string | null) => Promise;
+ onClientDisconnected?: (slackThreadTs: string | null) => Promise;
+};
+
+type RunTaskOptions = {
+ jobType: T;
+ jobPayload: JobPayload;
+ prompt: string;
+ publish: (taskEvent: TaskEvent) => Promise;
+ logger: Logger;
+ callbacks?: RunTaskCallbacks;
+};
+
+export const runTask = async ({
+ jobType,
+ jobPayload,
+ prompt,
+ publish,
+ logger,
+ callbacks,
+}: RunTaskOptions) => {
+ const workspacePath = '/roo/repos/Roo-Code'; // findGitRoot(process.cwd())
+ const ipcSocketPath = path.resolve(
+ os.tmpdir(),
+ `${crypto.randomUUID().slice(0, 8)}.sock`,
+ );
+ const env = { ROO_CODE_IPC_SOCKET_PATH: ipcSocketPath };
+ const controller = new AbortController();
+ const cancelSignal = controller.signal;
+ const containerized = isDockerContainer();
+
+ const codeCommand = containerized
+ ? `xvfb-run --auto-servernum --server-num=1 code --wait --log trace --disable-workspace-trust --disable-gpu --disable-lcd-text --no-sandbox --user-data-dir /roo/.vscode --password-store="basic" -n ${workspacePath}`
+ : `code --disable-workspace-trust -n ${workspacePath}`;
+
+ logger.info(codeCommand);
+
+ // Sleep for a random amount of time between 5 and 10 seconds, unless we're
+ // running in a container, in which case there are no issues with flooding
+ // VSCode with new windows.
+ if (!containerized) {
+ await new Promise((resolve) =>
+ setTimeout(resolve, Math.random() * 5_000 + 5_000),
+ );
+ }
+
+ const subprocess = execa({
+ env,
+ shell: '/bin/bash',
+ cancelSignal,
+ })`${codeCommand}`;
+
+ // If debugging, add `--verbose` to `command` and uncomment the following line.
+ // subprocess.stdout.pipe(process.stdout)
+
+ // Give VSCode some time to spawn before connecting to its unix socket.
+ await new Promise((resolve) => setTimeout(resolve, 3_000));
+ let client: IpcClient | undefined = undefined;
+ let attempts = 5;
+
+ while (true) {
+ try {
+ client = new IpcClient(ipcSocketPath);
+ await pWaitFor(() => client!.isReady, { interval: 250, timeout: 1_000 });
+ break;
+ } catch (_error) {
+ client?.disconnect();
+ attempts--;
+
+ if (attempts <= 0) {
+ logger.error(`unable to connect to IPC socket -> ${ipcSocketPath}`);
+ throw new Error('Unable to connect.');
+ }
+ }
+ }
+
+ let taskStartedAt = Date.now();
+ let taskFinishedAt: number | undefined;
+ let taskAbortedAt: number | undefined;
+ let taskTimedOut: boolean = false;
+ let rooTaskId: string | undefined;
+ let isClientDisconnected = false;
+
+ const slackNotifier = new SlackNotifier(logger);
+ let slackThreadTs: string | null = null;
+
+ const ignoreEvents: Record<'broadcast' | 'log', RooCodeEventName[]> = {
+ broadcast: [RooCodeEventName.Message],
+ log: [
+ RooCodeEventName.TaskTokenUsageUpdated,
+ RooCodeEventName.TaskAskResponded,
+ ],
+ };
+
+ client.on(IpcMessageType.TaskEvent, async (taskEvent) => {
+ const { eventName, payload } = taskEvent;
+
+ // Publish all events except for these to Redis.
+ if (!ignoreEvents.broadcast.includes(eventName)) {
+ await publish({ ...taskEvent });
+ }
+
+ // Log all events except for these.
+ // For message events we only log non-partial messages.
+ if (
+ !ignoreEvents.log.includes(eventName) &&
+ (eventName !== RooCodeEventName.Message ||
+ payload[0].message.partial !== true)
+ ) {
+ logger.info(`${eventName} ->`, payload);
+ }
+
+ if (eventName === RooCodeEventName.TaskStarted) {
+ taskStartedAt = Date.now();
+ rooTaskId = payload[0];
+
+ if (rooTaskId) {
+ slackThreadTs = await slackNotifier.postTaskStarted({
+ jobType,
+ jobPayload,
+ rooTaskId,
+ });
+
+ if (callbacks?.onTaskStarted) {
+ await callbacks.onTaskStarted(slackThreadTs, rooTaskId);
+ }
+ }
+ }
+
+ if (eventName === RooCodeEventName.TaskAborted) {
+ taskAbortedAt = Date.now();
+
+ if (slackThreadTs) {
+ await slackNotifier.postTaskUpdated(
+ slackThreadTs,
+ 'Task was aborted',
+ 'warning',
+ );
+ }
+
+ if (callbacks?.onTaskAborted) {
+ await callbacks.onTaskAborted(slackThreadTs);
+ }
+ }
+
+ if (eventName === RooCodeEventName.TaskCompleted) {
+ taskFinishedAt = Date.now();
+
+ if (slackThreadTs) {
+ await slackNotifier.postTaskCompleted(
+ slackThreadTs,
+ true,
+ taskFinishedAt - taskStartedAt,
+ rooTaskId,
+ );
+ }
+
+ if (callbacks?.onTaskCompleted) {
+ await callbacks.onTaskCompleted(
+ slackThreadTs,
+ true,
+ taskFinishedAt - taskStartedAt,
+ rooTaskId,
+ );
+ }
+ }
+ });
+
+ client.on(IpcMessageType.Disconnect, async () => {
+ logger.info(`disconnected from IPC socket -> ${ipcSocketPath}`);
+ isClientDisconnected = true;
+ });
+
+ client.sendCommand({
+ commandName: TaskCommandName.StartNewTask,
+ data: {
+ configuration: {
+ ...EVALS_SETTINGS,
+ openRouterApiKey: process.env.OPENROUTER_API_KEY,
+ },
+ text: prompt,
+ newTab: true,
+ },
+ });
+
+ try {
+ await pWaitFor(
+ () => !!taskFinishedAt || !!taskAbortedAt || isClientDisconnected,
+ {
+ interval: 1_000,
+ timeout: TIMEOUT,
+ },
+ );
+ } catch (_error) {
+ taskTimedOut = true;
+ logger.error('time limit reached');
+
+ if (slackThreadTs) {
+ await slackNotifier.postTaskUpdated(
+ slackThreadTs,
+ 'Task timed out after 30 minutes',
+ 'error',
+ );
+ }
+
+ if (callbacks?.onTaskTimedOut) {
+ await callbacks.onTaskTimedOut(slackThreadTs);
+ }
+
+ if (rooTaskId && !isClientDisconnected) {
+ logger.info('cancelling task');
+ client.sendCommand({
+ commandName: TaskCommandName.CancelTask,
+ data: rooTaskId,
+ });
+ await new Promise((resolve) => setTimeout(resolve, 5_000)); // Allow some time for the task to cancel.
+ }
+
+ taskFinishedAt = Date.now();
+ }
+
+ if (!taskFinishedAt && !taskTimedOut) {
+ logger.error('client disconnected before task finished');
+
+ if (slackThreadTs) {
+ await slackNotifier.postTaskUpdated(
+ slackThreadTs,
+ 'Client disconnected before task completion',
+ 'error',
+ );
+ }
+
+ if (callbacks?.onClientDisconnected) {
+ await callbacks.onClientDisconnected(slackThreadTs);
+ }
+
+ throw new Error('Client disconnected before task completion.');
+ }
+
+ if (rooTaskId && !isClientDisconnected) {
+ logger.info('closing task');
+ client.sendCommand({
+ commandName: TaskCommandName.CloseTask,
+ data: rooTaskId,
+ });
+ await new Promise((resolve) => setTimeout(resolve, 2_000)); // Allow some time for the window to close.
+ }
+
+ if (!isClientDisconnected) {
+ logger.info('disconnecting client');
+ client.disconnect();
+ }
+
+ logger.info('waiting for subprocess to finish');
+ controller.abort();
+
+ // Wait for subprocess to finish gracefully, with a timeout.
+ const SUBPROCESS_TIMEOUT = 10_000;
+
+ try {
+ await Promise.race([
+ subprocess,
+ new Promise((_, reject) =>
+ setTimeout(
+ () => reject(new SubprocessTimeoutError(SUBPROCESS_TIMEOUT)),
+ SUBPROCESS_TIMEOUT,
+ ),
+ ),
+ ]);
+
+ logger.info('subprocess finished gracefully');
+ } catch (error) {
+ if (error instanceof SubprocessTimeoutError) {
+ logger.error('subprocess did not finish within timeout, force killing');
+
+ try {
+ if (subprocess.kill('SIGKILL')) {
+ logger.info('SIGKILL sent to subprocess');
+ } else {
+ logger.error('failed to send SIGKILL to subprocess');
+ }
+ } catch (killError) {
+ logger.error('subprocess.kill(SIGKILL) failed:', killError);
+ }
+ } else {
+ throw error;
+ }
+ }
+
+ logger.close();
+};
diff --git a/apps/roomote/src/lib/slack.ts b/apps/roomote/src/lib/slack.ts
new file mode 100644
index 0000000000..62c4de191b
--- /dev/null
+++ b/apps/roomote/src/lib/slack.ts
@@ -0,0 +1,159 @@
+import { JobPayload, JobType } from '@/types';
+import { Logger } from './logger';
+
+export interface SlackMessage {
+ text: string;
+ blocks?: unknown[];
+ attachments?: unknown[];
+ thread_ts?: string;
+ channel?: string;
+}
+
+export interface SlackResponse {
+ ok: boolean;
+ channel?: string;
+ ts?: string;
+ error?: string;
+ message?: Record;
+}
+
+export class SlackNotifier {
+ private readonly logger?: Logger;
+ private readonly token: string;
+
+ constructor(logger?: Logger, token: string = process.env.SLACK_API_TOKEN!) {
+ this.logger = logger;
+ this.token = token;
+ }
+
+ private async postMessage(message: SlackMessage): Promise {
+ try {
+ const messageWithChannel = {
+ ...message,
+ channel: message.channel || '#roomote-control',
+ };
+
+ const response = await fetch('https://slack.com/api/chat.postMessage', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.token}`,
+ },
+ body: JSON.stringify(messageWithChannel),
+ });
+
+ if (!response.ok) {
+ this.logger?.error(
+ `Slack API failed: ${response.status} ${response.statusText}`,
+ );
+ return null;
+ }
+
+ const result: SlackResponse = await response.json();
+
+ if (!result.ok) {
+ this.logger?.error(`Slack API error: ${result.error}`);
+ }
+
+ return result.ts ?? null;
+ } catch (error) {
+ this.logger?.error('Failed to send Slack message:', error);
+ return null;
+ }
+ }
+
+ public async postTaskStarted({
+ jobType,
+ jobPayload,
+ }: {
+ jobType: T;
+ jobPayload: JobPayload;
+ rooTaskId: string;
+ }) {
+ switch (jobType) {
+ case 'github.issue.fix': {
+ const payload = jobPayload as JobPayload<'github.issue.fix'>;
+ return await this.postMessage({
+ text: `🚀 Task Started`,
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: `🚀 *Task Started*\nAttempting to fix `,
+ },
+ },
+ ],
+ });
+ }
+ case 'github.issue.comment.respond': {
+ const payload =
+ jobPayload as JobPayload<'github.issue.comment.respond'>;
+ return await this.postMessage({
+ text: `🚀 Task Started`,
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: `🚀 *Task Started*\nResponding to comment on \n*Comment:* ${payload.commentBody.slice(0, 100)}${payload.commentBody.length > 100 ? '...' : ''}`,
+ },
+ },
+ ],
+ });
+ }
+ case 'github.pr.comment.respond': {
+ const payload = jobPayload as JobPayload<'github.pr.comment.respond'>;
+ return await this.postMessage({
+ text: `🚀 Task Started`,
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: `🚀 *Task Started*\nResponding to comment on \n*Comment:* ${payload.commentBody.slice(0, 100)}${payload.commentBody.length > 100 ? '...' : ''}`,
+ },
+ },
+ ],
+ });
+ }
+ default:
+ throw new Error(`Unknown job type: ${jobType}`);
+ }
+ }
+
+ public async postTaskUpdated(
+ threadTs: string,
+ text: string,
+ status?: 'info' | 'success' | 'warning' | 'error',
+ ): Promise {
+ const emoji = { info: 'ℹ️', success: '✅', warning: '⚠️', error: '❌' }[
+ status || 'info'
+ ];
+ await this.postMessage({ text: `${emoji} ${text}`, thread_ts: threadTs });
+ }
+
+ public async postTaskCompleted(
+ threadTs: string,
+ success: boolean,
+ duration: number,
+ taskId?: string,
+ ): Promise {
+ const status = success ? '✅ Completed' : '❌ Failed';
+ const durationText = `${Math.round(duration / 1000)}s`;
+
+ await this.postMessage({
+ text: `${status} Task finished in ${durationText}`,
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: `*${status}*\n*Task ID:* ${taskId || 'Unknown'}\n*Duration:* ${durationText}`,
+ },
+ },
+ ],
+ thread_ts: threadTs,
+ });
+ }
+}
diff --git a/apps/roomote/src/lib/utils.ts b/apps/roomote/src/lib/utils.ts
new file mode 100644
index 0000000000..ab6b1a671a
--- /dev/null
+++ b/apps/roomote/src/lib/utils.ts
@@ -0,0 +1,37 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+export const isDockerContainer = () => {
+ try {
+ return fs.existsSync('/.dockerenv');
+ } catch (_error) {
+ return false;
+ }
+};
+
+/**
+ * Traverses up the directory tree to find an ancestor directory that contains a .git directory
+ * @param startPath The starting directory path
+ * @returns The path to the git repository root
+ * @throws Error if no .git directory is found
+ */
+export const findGitRoot = (startPath: string): string => {
+ let currentPath = path.resolve(startPath);
+ const root = path.parse(currentPath).root;
+
+ while (currentPath !== root) {
+ const gitPath = path.join(currentPath, '.git');
+ if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {
+ return currentPath;
+ }
+ currentPath = path.dirname(currentPath);
+ }
+
+ const gitPath = path.join(root, '.git');
+
+ if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {
+ return root;
+ }
+
+ throw new Error('No .git directory found in any ancestor directory');
+};
diff --git a/apps/roomote/src/lib/worker.ts b/apps/roomote/src/lib/worker.ts
new file mode 100644
index 0000000000..b61573a960
--- /dev/null
+++ b/apps/roomote/src/lib/worker.ts
@@ -0,0 +1,72 @@
+import { Worker } from 'bullmq';
+
+import { redis } from './redis';
+import { processJob } from './job';
+
+// docker compose build worker
+// docker run \
+// --name roomote-worker \
+// --rm \
+// --interactive \
+// --tty \
+// --network roo-code-cloud_default \
+// -e HOST_EXECUTION_METHOD=docker \
+// -e GH_TOKEN=$GH_TOKEN \
+// -e DATABASE_URL=postgresql://postgres:password@db:5432/cloud_agents \
+// -e REDIS_URL=redis://redis:6379 \
+// -e NODE_ENV=production \
+// -v /var/run/docker.sock:/var/run/docker.sock \
+// -v /tmp/roomote:/var/log/roomote \
+// roomote-worker sh -c "bash"
+
+async function processSingleJob() {
+ const worker = new Worker('roomote', undefined, {
+ autorun: false,
+ connection: redis,
+ lockDuration: 30 * 60 * 1_000, // 30 minutes
+ });
+
+ const token = crypto.randomUUID();
+
+ try {
+ const job = await worker.getNextJob(token);
+
+ if (!job) {
+ console.log('No jobs available, exiting...');
+ await worker.close();
+ process.exit(0);
+ }
+
+ console.log(`Processing job ${job.id}...`);
+
+ try {
+ await processJob(job);
+ await job.moveToCompleted(undefined, token, false);
+ console.log(`Job ${job.id} completed successfully`);
+ } catch (error) {
+ await job.moveToFailed(error as Error, token, false);
+ console.error(`Job ${job.id} failed:`, error);
+ }
+ } catch (error) {
+ console.error('Error processing job:', error);
+ } finally {
+ await worker.close();
+ process.exit(0);
+ }
+}
+
+process.on('SIGTERM', async () => {
+ console.log('SIGTERM -> shutting down gracefully...');
+ process.exit(0);
+});
+
+process.on('SIGINT', async () => {
+ console.log('SIGINT -> shutting down gracefully...');
+ process.exit(0);
+});
+
+if (!process.env.GH_TOKEN) {
+ throw new Error('GH_TOKEN is not set');
+}
+
+processSingleJob();
diff --git a/apps/roomote/src/types/index.ts b/apps/roomote/src/types/index.ts
new file mode 100644
index 0000000000..14ff057be2
--- /dev/null
+++ b/apps/roomote/src/types/index.ts
@@ -0,0 +1,61 @@
+import { z } from 'zod';
+
+export const createJobSchema = z.discriminatedUnion('type', [
+ z.object({
+ type: z.literal('github.issue.fix'),
+ payload: z.object({
+ repo: z.string(),
+ issue: z.number(),
+ title: z.string(),
+ body: z.string(),
+ labels: z.array(z.string()).optional(),
+ }),
+ }),
+ z.object({
+ type: z.literal('github.issue.comment.respond'),
+ payload: z.object({
+ repo: z.string(),
+ issueNumber: z.number(),
+ issueTitle: z.string(),
+ issueBody: z.string(),
+ commentId: z.number(),
+ commentBody: z.string(),
+ commentAuthor: z.string(),
+ commentUrl: z.string(),
+ }),
+ }),
+ z.object({
+ type: z.literal('github.pr.comment.respond'),
+ payload: z.object({
+ repo: z.string(),
+ prNumber: z.number(),
+ prTitle: z.string(),
+ prBody: z.string(),
+ prBranch: z.string(),
+ baseRef: z.string(),
+ commentId: z.number(),
+ commentBody: z.string(),
+ commentAuthor: z.string(),
+ commentType: z.enum(['issue_comment', 'review_comment']),
+ commentUrl: z.string(),
+ }),
+ }),
+]);
+
+export type CreateJob = z.infer;
+
+export type JobTypes = {
+ [K in CreateJob['type']]: Extract['payload'];
+};
+
+export type JobType = keyof JobTypes;
+
+export type JobStatus = 'pending' | 'processing' | 'completed' | 'failed';
+
+export type JobPayload = JobTypes[T];
+
+export type JobParams = {
+ jobId: number;
+ type: T;
+ payload: JobPayload;
+};
diff --git a/apps/roomote/tsconfig.json b/apps/roomote/tsconfig.json
new file mode 100644
index 0000000000..473167e0c4
--- /dev/null
+++ b/apps/roomote/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "@roo-code-cloud/config-typescript/nextjs.json",
+ "compilerOptions": {
+ "types": ["vitest/globals"],
+ "paths": { "@/*": ["./src/*"] }
+ },
+ "include": [
+ "next-env.d.ts",
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ ".next/types/**/*.ts",
+ "drizzle.config.ts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/apps/web/vitest.config.mts b/apps/roomote/vitest.config.ts
similarity index 57%
rename from apps/web/vitest.config.mts
rename to apps/roomote/vitest.config.ts
index 2e4497186a..da651da521 100644
--- a/apps/web/vitest.config.mts
+++ b/apps/roomote/vitest.config.ts
@@ -5,9 +5,5 @@ export default defineConfig({
globals: true,
watch: false,
reporters: ['dot'],
- coverage: {
- include: ['src/**/*'],
- exclude: ['src/**/*.stories.{js,jsx,ts,tsx}', '**/*.d.ts'],
- },
},
});
diff --git a/apps/web/.gitignore b/apps/web/.gitignore
index d64785b3bf..37799ec24d 100644
--- a/apps/web/.gitignore
+++ b/apps/web/.gitignore
@@ -1,7 +1,3 @@
# next.js
/.next
/out
-
-# docker
-.docker/*
-!.docker/scripts
diff --git a/apps/web/docker-compose.yml b/apps/web/docker-compose.yml
deleted file mode 100644
index ec9f781565..0000000000
--- a/apps/web/docker-compose.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: roo-code-cloud
-
-services:
- postgres:
- container_name: roo-code-cloud-postgres
- image: postgres:17.5
- ports:
- - '5432:5432'
- volumes:
- - ./.docker/data/postgres:/var/lib/postgresql/data
- - ./.docker/scripts/postgres:/docker-entrypoint-initdb.d
- environment:
- - POSTGRES_USER=postgres
- - POSTGRES_PASSWORD=password
- - POSTGRES_DATABASES=roo_code_development,roo_code_test
- healthcheck:
- test: ['CMD-SHELL', 'pg_isready -U postgres -d roo_code_development']
- interval: 5s
- timeout: 5s
- retries: 5
- start_period: 30s
-
- clickhouse:
- container_name: roo-code-cloud-clickhouse
- image: clickhouse/clickhouse-server
- ports:
- - '8123:8123'
- - '9000:9000'
- volumes:
- - ./.docker/data/clickhouse:/var/lib/clickhouse/
- - ./.docker/logs/clickhouse:/var/log/clickhouse-server/
- - ./.docker/scripts/clickhouse:/docker-entrypoint-initdb.d
- environment:
- - CLICKHOUSE_DB=default
- - CLICKHOUSE_USER=default
- - CLICKHOUSE_PASSWORD=password
- healthcheck:
- test: ['CMD-SHELL', 'wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1']
- interval: 5s
- timeout: 5s
- retries: 5
- start_period: 30s
diff --git a/apps/web/eslint.config.mjs b/apps/web/eslint.config.mjs
index 5999738c76..00b53054bd 100644
--- a/apps/web/eslint.config.mjs
+++ b/apps/web/eslint.config.mjs
@@ -1,74 +1,4 @@
-import globals from 'globals';
-
-import js from '@eslint/js';
-import eslintConfigPrettier from 'eslint-config-prettier';
-import tseslint from 'typescript-eslint';
-import pluginReactHooks from 'eslint-plugin-react-hooks';
-import pluginReact from 'eslint-plugin-react';
-import pluginNext from '@next/eslint-plugin-next';
-// import turboPlugin from 'eslint-plugin-turbo';
-import onlyWarn from 'eslint-plugin-only-warn';
+import { nextJsConfig } from '@roo-code-cloud/config-eslint/next-js';
/** @type {import("eslint").Linter.Config} */
-export default [
- js.configs.recommended,
- eslintConfigPrettier,
- ...tseslint.configs.recommended,
- // {
- // plugins: {
- // turbo: turboPlugin,
- // },
- // rules: {
- // 'turbo/no-undeclared-env-vars': 'warn',
- // },
- // },
- {
- plugins: {
- onlyWarn,
- },
- },
- {
- ignores: ['dist/**', '.next'],
- },
- {
- ...pluginReact.configs.flat.recommended,
- languageOptions: {
- ...pluginReact.configs.flat.recommended.languageOptions,
- globals: {
- ...globals.serviceworker,
- },
- },
- },
- {
- plugins: {
- '@next/next': pluginNext,
- },
- rules: {
- ...pluginNext.configs.recommended.rules,
- ...pluginNext.configs['core-web-vitals'].rules,
- },
- },
- {
- plugins: {
- 'react-hooks': pluginReactHooks,
- },
- settings: { react: { version: 'detect' } },
- rules: {
- ...pluginReactHooks.configs.recommended.rules,
- // React scope no longer necessary with new JSX transform.
- 'react/react-in-jsx-scope': 'off',
- },
- },
- {
- rules: {
- 'no-unused-vars': 'off',
- '@typescript-eslint/no-unused-vars': [
- 'error',
- {
- caughtErrorsIgnorePattern: '^_',
- argsIgnorePattern: '^_',
- },
- ],
- },
- },
-];
+export default [...nextJsConfig];
diff --git a/apps/web/package.json b/apps/web/package.json
index b9565e27ef..3b7651a975 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -2,20 +2,17 @@
"name": "@roo-code-cloud/web",
"private": true,
"scripts": {
- "lint": "eslint .",
- "check-types": "tsc --noEmit --pretty",
+ "lint": "next lint --max-warnings 0",
+ "check-types": "tsc --noEmit",
"test": "dotenvx run -f .env.test -f .env -- vitest run",
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
- "clean": "rimraf .next out coverage",
+ "clean": "rimraf .next .turbo out",
"db:generate": "dotenvx run -f .env.development -- drizzle-kit generate",
"db:migrate": "dotenvx run -f .env.development -- drizzle-kit migrate",
"db:push": "dotenvx run -f .env.development -- drizzle-kit push",
- "db:test:push": "dotenvx run -f .env.test -- drizzle-kit push",
- "db:up": "docker compose up -d --wait && pnpm db:push --force && pnpm db:test:push --force",
- "db:down": "docker compose down",
- "db:reset": "pnpm db:down && rimraf .docker/data .docker/logs && pnpm db:up"
+ "db:test:push": "dotenvx run -f .env.test -- drizzle-kit push"
},
"dependencies": {
"@clerk/localizations": "^3.16.3",
@@ -81,15 +78,16 @@
"@eslint/js": "^9.27.0",
"@next/bundle-analyzer": "^15.3.3",
"@next/eslint-plugin-next": "^15.3.3",
+ "@roo-code-cloud/config-eslint": "workspace:^",
+ "@roo-code-cloud/config-typescript": "workspace:^",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^22.15.27",
"@types/pg": "^8.15.2",
"@types/react": "^19.1.6",
- "@vitejs/plugin-react": "^4.5.0",
- "@vitest/coverage-v8": "^3.1.4",
- "@vitest/expect": "^3.1.4",
+ "@types/react-dom": "^19.1.6",
+ "@vitejs/plugin-react": "^4.5.2",
"drizzle-kit": "^0.31.1",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-only-warn": "^1.1.0",
@@ -103,6 +101,6 @@
"tailwindcss-animate": "^1.0.7",
"typescript-eslint": "^8.33.0",
"vite-tsconfig-paths": "^5.1.4",
- "vitest": "^3.1.4"
+ "vitest": "^3.2.3"
}
}
diff --git a/apps/web/src/db/db.ts b/apps/web/src/db/db.ts
index dde0bd73d8..16943eb346 100644
--- a/apps/web/src/db/db.ts
+++ b/apps/web/src/db/db.ts
@@ -4,11 +4,8 @@ import postgres from 'postgres';
import { Env } from '@/lib/server';
import * as schema from './schema';
-const pgClient = postgres(Env.DATABASE_URL, { prepare: false });
-
-const client = drizzle({ client: pgClient, schema });
-
-let testDb: typeof client | undefined = undefined;
+const postgresClient = postgres(Env.DATABASE_URL, { prepare: false });
+const client = drizzle({ client: postgresClient, schema });
if (process.env.NODE_ENV === 'test') {
if (
@@ -17,16 +14,12 @@ if (process.env.NODE_ENV === 'test') {
) {
throw new Error('DATABASE_URL is not a test database');
}
-
- testDb = client;
}
-const disconnect = async () => {
- await pgClient.end();
-};
+const disconnect = async () => postgresClient.end();
type DatabaseOrTransaction =
| typeof client
| Parameters[0]>[0];
-export { client, testDb, disconnect, type DatabaseOrTransaction };
+export { client, disconnect, type DatabaseOrTransaction };
diff --git a/apps/web/src/i18n/locale.ts b/apps/web/src/i18n/locale.ts
index ee8716c846..808960fb5e 100644
--- a/apps/web/src/i18n/locale.ts
+++ b/apps/web/src/i18n/locale.ts
@@ -12,7 +12,9 @@ export const Locales: Record = {
fr: 'Français',
};
-export const getClerkLocale = (locale: string) => {
+type ClerkLocalization = typeof enUS;
+
+export const getClerkLocale = (locale: string): ClerkLocalization => {
if (!isLocale(locale)) {
return enUS;
}
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index 8562834e52..1e93d2beca 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -1,46 +1,16 @@
{
+ "extends": "@roo-code-cloud/config-typescript/nextjs.json",
"compilerOptions": {
- "lib": ["dom", "dom.iterable", "esnext"],
- "module": "esnext",
- "moduleResolution": "bundler",
- "resolveJsonModule": true,
- "removeComments": true,
- "preserveConstEnums": true,
- "strict": true,
- "alwaysStrict": true,
- "strictNullChecks": true,
- "noUncheckedIndexedAccess": true,
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noImplicitThis": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "allowUnreachableCode": false,
- "noFallthroughCasesInSwitch": true,
- "target": "es2017",
- "outDir": "out",
- "sourceMap": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "allowJs": true,
- "checkJs": true,
- "skipLibCheck": true,
- "forceConsistentCasingInFileNames": true,
- "jsx": "preserve",
- "noEmit": true,
- "isolatedModules": true,
- "incremental": true,
- "types": ["vitest/globals"],
- "baseUrl": ".",
- "paths": { "@/*": ["src/*"] },
- "plugins": [{ "name": "next" }]
+ "types": ["vitest/globals", "@testing-library/jest-dom"],
+ "paths": { "@/*": ["./src/*"] }
},
- "exclude": ["./out/**/*", "./node_modules/**/*", ".next/**/*"],
"include": [
- "**/*.mts",
- "**/*.ts",
- "**/*.tsx",
"next-env.d.ts",
- ".next/types/**/*.ts"
- ]
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ ".next/types/**/*.ts",
+ "drizzle.config.ts",
+ "vitest*.ts"
+ ],
+ "exclude": ["node_modules"]
}
diff --git a/apps/web/vitest-global-setup.ts b/apps/web/vitest-global-setup.ts
deleted file mode 100644
index 366540e719..0000000000
--- a/apps/web/vitest-global-setup.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { sql } from 'drizzle-orm';
-
-import { Env } from 'src/lib/server';
-import { testDb, disconnect } from 'src/db/server';
-
-async function resetTestDatabase() {
- const db = testDb;
-
- // Skip database reset if no database connection is available
- if (!db) {
- console.log('No database connection available, skipping database reset');
- return;
- }
-
- try {
- const tables = await db.execute<{ table_name: string }>(sql`
- SELECT table_name
- FROM information_schema.tables
- WHERE table_schema = 'public'
- AND table_type = 'BASE TABLE';
- `);
-
- const tableNames = tables.map((t) => t.table_name);
-
- for (const tableName of tableNames) {
- await db.execute(sql`TRUNCATE TABLE "${sql.raw(tableName)}" CASCADE;`);
- }
-
- console.log(`[${Env.DATABASE_URL}] TRUNCATE ${tableNames.join(', ')}`);
- } catch (error) {
- console.error('Error resetting database:', error);
- throw error;
- }
-}
-
-export default async function () {
- await resetTestDatabase();
-
- return async () => {
- await disconnect();
- };
-}
diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts
new file mode 100644
index 0000000000..1d0253416d
--- /dev/null
+++ b/apps/web/vitest.config.ts
@@ -0,0 +1,41 @@
+import { resolve } from 'path';
+
+import { defineConfig } from 'vitest/config';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ '@': resolve(__dirname, './src'),
+ },
+ },
+ test: {
+ globals: true,
+ watch: false,
+ reporters: ['dot'],
+ projects: [
+ {
+ extends: true,
+ test: {
+ name: 'server',
+ include: [
+ 'src/**/*.test.{js,jsx,ts,tsx}',
+ '!src/{hooks,components}/**/*.test.{js,jsx,ts,tsx}',
+ ],
+ environment: 'node',
+ globalSetup: './vitest.setup.server.ts',
+ },
+ },
+ {
+ extends: true,
+ test: {
+ name: 'client',
+ include: ['src/{hooks,components}/**/*.test.{js,jsx,ts,tsx}'],
+ environment: 'jsdom',
+ setupFiles: './vitest.setup.client.ts',
+ },
+ },
+ ],
+ },
+});
diff --git a/apps/web/vitest-setup.ts b/apps/web/vitest.setup.client.ts
similarity index 100%
rename from apps/web/vitest-setup.ts
rename to apps/web/vitest.setup.client.ts
diff --git a/apps/web/vitest.setup.server.ts b/apps/web/vitest.setup.server.ts
new file mode 100644
index 0000000000..2dcb4bd497
--- /dev/null
+++ b/apps/web/vitest.setup.server.ts
@@ -0,0 +1,38 @@
+import postgres from 'postgres';
+import { drizzle } from 'drizzle-orm/postgres-js';
+import { sql } from 'drizzle-orm';
+
+let pgClient: ReturnType | undefined = undefined;
+
+async function resetTestDatabase() {
+ pgClient = postgres(
+ 'postgres://postgres:password@localhost:5432/roo_code_test',
+ {
+ prepare: false,
+ onnotice: () => {}, // Suppress NOTICE logs.
+ },
+ );
+
+ const db = drizzle({ client: pgClient });
+
+ const tables = await db.execute<{ table_name: string }>(sql`
+ SELECT table_name
+ FROM information_schema.tables
+ WHERE table_schema = 'public'
+ AND table_type = 'BASE TABLE';
+ `);
+
+ const tableNames = tables.map((t) => t.table_name);
+
+ for (const tableName of tableNames) {
+ await db.execute(sql`TRUNCATE TABLE "${sql.raw(tableName)}" CASCADE;`);
+ }
+}
+
+export default async function () {
+ await resetTestDatabase();
+
+ return async () => {
+ await pgClient?.end();
+ };
+}
diff --git a/apps/web/vitest.workspace.ts b/apps/web/vitest.workspace.ts
deleted file mode 100644
index eaef921fba..0000000000
--- a/apps/web/vitest.workspace.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { defineWorkspace } from 'vitest/config';
-import react from '@vitejs/plugin-react';
-import tsconfigPaths from 'vite-tsconfig-paths';
-
-export default defineWorkspace([
- // Server-side tests (node environment).
- {
- plugins: [react(), tsconfigPaths()],
- test: {
- name: 'server',
- globals: true,
- include: [
- 'src/**/*.test.{js,jsx,ts,tsx}',
- '!src/hooks/**/*.test.{js,jsx,ts,tsx}', // Exclude hooks tests.
- '!src/components/**/*.test.{js,jsx,ts,tsx}', // Exclude component tests.
- ],
- environment: 'node',
- setupFiles: './vitest-setup.ts',
- globalSetup: './vitest-global-setup.ts',
- },
- },
- // Client-side tests (jsdom environment).
- {
- plugins: [react(), tsconfigPaths()],
- test: {
- name: 'client',
- globals: true,
- include: [
- 'src/hooks/**/*.test.{js,jsx,ts,tsx}',
- 'src/components/**/*.test.{js,jsx,ts,tsx}',
- ],
- environment: 'jsdom',
- setupFiles: './vitest-setup.ts',
- // No globalSetup for client tests to avoid database connection issues.
- },
- },
-]);
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000..15455d3fe0
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,148 @@
+name: roo-code-cloud
+
+services:
+ base:
+ build:
+ context: ../../
+ dockerfile: .docker/Dockerfile.base
+ image: roo-code-cloud-base
+
+ postgres:
+ container_name: roo-code-cloud-postgres
+ image: postgres:17.5
+ ports:
+ - "5432:5432"
+ volumes:
+ - ./.docker/data/postgres:/var/lib/postgresql/data
+ - ./.docker/scripts/postgres:/docker-entrypoint-initdb.d
+ environment:
+ - POSTGRES_USER=postgres
+ - POSTGRES_PASSWORD=password
+ - POSTGRES_DATABASES=roo_code_development,roo_code_test
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres -d roo_code_development"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+ start_period: 30s
+
+ clickhouse:
+ container_name: roo-code-cloud-clickhouse
+ image: clickhouse/clickhouse-server
+ ports:
+ - "8123:8123"
+ - "9000:9000"
+ volumes:
+ - ./.docker/data/clickhouse:/var/lib/clickhouse/
+ - ./.docker/logs/clickhouse:/var/log/clickhouse-server/
+ - ./.docker/scripts/clickhouse:/docker-entrypoint-initdb.d
+ environment:
+ - CLICKHOUSE_DB=default
+ - CLICKHOUSE_USER=default
+ - CLICKHOUSE_PASSWORD=password
+ healthcheck:
+ test:
+ [
+ "CMD-SHELL",
+ "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1",
+ ]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+ start_period: 30s
+
+ redis:
+ container_name: roo-code-cloud-redis
+ image: redis:7-alpine
+ ports:
+ - "6380:6379"
+ volumes:
+ - ./.docker/data/redis:/data
+ command: redis-server --appendonly yes
+
+ roomote-dashboard:
+ container_name: roo-code-cloud-roomote-dashboard
+ build:
+ context: ../../
+ dockerfile: .docker/Dockerfile.dashboard
+ image: roo-code-cloud-roomote-dashboard
+ ports:
+ - "3002:3002"
+ environment:
+ - REDIS_URL=redis://redis:6379
+ - NODE_ENV=production
+ depends_on:
+ redis:
+ condition: service_started
+
+ roomote-api:
+ container_name: roo-code-cloud-roomote-api
+ build:
+ context: ../../
+ dockerfile: .docker/Dockerfile.api
+ image: roo-code-cloud-roomote-api
+ ports:
+ - "3001:3001"
+ environment:
+ - DATABASE_URL=postgresql://postgres:password@db:5432/cloud_agents
+ - REDIS_URL=redis://redis:6379
+ - NODE_ENV=production
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_started
+
+ roomote-controller:
+ container_name: roo-code-cloud-roomote-controller
+ build:
+ context: ../../
+ dockerfile: .docker/Dockerfile.controller
+ args:
+ - GH_TOKEN=${GH_TOKEN}
+ image: roo-code-cloud-roomote-controller
+ env_file:
+ - .env
+ environment:
+ - HOST_EXECUTION_METHOD=docker
+ - DATABASE_URL=postgresql://postgres:password@db:5432/cloud_agents
+ - REDIS_URL=redis://redis:6379
+ - NODE_ENV=production
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - /tmp/roomote/controller:/var/log/roomote
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_started
+ restart: unless-stopped
+
+ roomote-worker:
+ build:
+ context: ../../
+ dockerfile: .docker/Dockerfile.worker
+ args:
+ - GH_TOKEN=${GH_TOKEN}
+ image: roomote-worker
+ env_file:
+ - .env
+ environment:
+ - HOST_EXECUTION_METHOD=docker
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - /tmp/roomote/worker:/var/log/roomote
+ stdin_open: true
+ tty: true
+ depends_on:
+ postgres:
+ condition: service_healthy
+ redis:
+ condition: service_started
+
+networks:
+ default:
+ name: roo-code-cloud_default
+ driver: bridge
diff --git a/package.json b/package.json
index 9379725793..136c572d1a 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,13 @@
"check-types": "turbo check-types --log-order grouped --output-logs new-only",
"test": "turbo test --log-order grouped --output-logs new-only",
"build": "turbo build --log-order grouped --output-logs new-only",
- "clean": "turbo clean --log-order grouped --output-logs new-only && rimraf .turbo"
+ "clean": "turbo clean --log-order grouped --output-logs new-only && rimraf .turbo",
+ "services:up": "docker compose up postgres clickhouse redis roomote-dashboard -d --wait && pnpm db:push",
+ "services:down": "docker compose down postgres clickhouse redis roomote-dashboard",
+ "db:up": "docker compose up postgres clickhouse -d --wait && pnpm db:push",
+ "db:down": "docker compose down postgres clickhouse",
+ "db:push": "pnpm --filter @roo-code-cloud/web db:push --force && pnpm --filter @roo-code-cloud/web db:test:push --force",
+ "db:reset": "pnpm db:down && rimraf .docker/data .docker/logs && pnpm db:up"
},
"devDependencies": {
"@dotenvx/dotenvx": "^1.44.2",
diff --git a/packages/config-eslint/base.js b/packages/config-eslint/base.js
new file mode 100644
index 0000000000..cb7b805c79
--- /dev/null
+++ b/packages/config-eslint/base.js
@@ -0,0 +1,44 @@
+import js from '@eslint/js';
+import eslintConfigPrettier from 'eslint-config-prettier';
+import turboPlugin from 'eslint-plugin-turbo';
+import tseslint from 'typescript-eslint';
+import onlyWarn from 'eslint-plugin-only-warn';
+
+/**
+ * A shared ESLint configuration for the repository.
+ *
+ * @type {import("eslint").Linter.Config[]}
+ * */
+export const config = [
+ js.configs.recommended,
+ eslintConfigPrettier,
+ ...tseslint.configs.recommended,
+ {
+ plugins: {
+ turbo: turboPlugin,
+ },
+ rules: {
+ 'turbo/no-undeclared-env-vars': 'off',
+ },
+ },
+ {
+ plugins: {
+ onlyWarn,
+ },
+ },
+ {
+ ignores: ['dist/**'],
+ },
+ {
+ rules: {
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ varsIgnorePattern: '^_',
+ caughtErrorsIgnorePattern: '^_',
+ },
+ ],
+ },
+ },
+];
diff --git a/packages/config-eslint/next.js b/packages/config-eslint/next.js
new file mode 100644
index 0000000000..8b2440c148
--- /dev/null
+++ b/packages/config-eslint/next.js
@@ -0,0 +1,22 @@
+import pluginNext from '@next/eslint-plugin-next';
+
+import { reactConfig } from './react.js';
+
+/**
+ * @type {import("eslint").Linter.Config[]}
+ */
+export const nextJsConfig = [
+ ...reactConfig,
+ {
+ ignores: ['.next/**'],
+ },
+ {
+ plugins: {
+ '@next/next': pluginNext,
+ },
+ rules: {
+ ...pluginNext.configs.recommended.rules,
+ ...pluginNext.configs['core-web-vitals'].rules,
+ },
+ },
+];
diff --git a/packages/config-eslint/package.json b/packages/config-eslint/package.json
index a5d5e7c17b..649716b166 100644
--- a/packages/config-eslint/package.json
+++ b/packages/config-eslint/package.json
@@ -1,4 +1,22 @@
{
"name": "@roo-code-cloud/config-eslint",
- "private": true
+ "private": true,
+ "type": "module",
+ "exports": {
+ "./base": "./base.js",
+ "./react": "./react.js",
+ "./next-js": "./next.js"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.22.0",
+ "@next/eslint-plugin-next": "^15.2.1",
+ "eslint": "^9.27.0",
+ "eslint-config-prettier": "^10.1.1",
+ "eslint-plugin-only-warn": "^1.1.0",
+ "eslint-plugin-react": "^7.37.4",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-turbo": "^2.4.4",
+ "globals": "^16.0.0",
+ "typescript-eslint": "^8.26.0"
+ }
}
diff --git a/packages/config-eslint/react.js b/packages/config-eslint/react.js
new file mode 100644
index 0000000000..2cae96332a
--- /dev/null
+++ b/packages/config-eslint/react.js
@@ -0,0 +1,38 @@
+import js from '@eslint/js';
+import eslintConfigPrettier from 'eslint-config-prettier';
+import typescriptEslint from 'typescript-eslint';
+import pluginReactHooks from 'eslint-plugin-react-hooks';
+import pluginReact from 'eslint-plugin-react';
+import globals from 'globals';
+
+import { config } from './base.js';
+
+/**
+ * @type {import("eslint").Linter.Config[]}
+ */
+export const reactConfig = [
+ ...config,
+ js.configs.recommended,
+ eslintConfigPrettier,
+ ...typescriptEslint.configs.recommended,
+ {
+ ...pluginReact.configs.flat.recommended,
+ languageOptions: {
+ ...pluginReact.configs.flat.recommended.languageOptions,
+ globals: {
+ ...globals.serviceworker,
+ },
+ },
+ },
+ {
+ plugins: {
+ 'react-hooks': pluginReactHooks,
+ },
+ settings: { react: { version: 'detect' } },
+ rules: {
+ ...pluginReactHooks.configs.recommended.rules,
+ // React scope no longer necessary with new JSX transform.
+ 'react/react-in-jsx-scope': 'off',
+ },
+ },
+];
diff --git a/packages/config-typescript/base.json b/packages/config-typescript/base.json
new file mode 100644
index 0000000000..5117f2a3d1
--- /dev/null
+++ b/packages/config-typescript/base.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "esModuleInterop": true,
+ "incremental": false,
+ "isolatedModules": true,
+ "lib": ["es2022", "DOM", "DOM.Iterable"],
+ "module": "NodeNext",
+ "moduleDetection": "force",
+ "moduleResolution": "NodeNext",
+ "noUncheckedIndexedAccess": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "target": "ES2022"
+ }
+}
diff --git a/packages/config-typescript/cjs.json b/packages/config-typescript/cjs.json
new file mode 100644
index 0000000000..6b30cbd0ed
--- /dev/null
+++ b/packages/config-typescript/cjs.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "module": "CommonJS",
+ "moduleResolution": "Node",
+ "esModuleInterop": true,
+ "target": "ES2022",
+ "lib": ["ES2022", "ESNext.Disposable", "DOM"],
+ "sourceMap": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "useUnknownInCatchVariables": false
+ }
+}
diff --git a/packages/config-typescript/nextjs.json b/packages/config-typescript/nextjs.json
new file mode 100644
index 0000000000..03c9a953bb
--- /dev/null
+++ b/packages/config-typescript/nextjs.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "./base.json",
+ "compilerOptions": {
+ "plugins": [{ "name": "next" }],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowJs": true,
+ "jsx": "preserve",
+ "noEmit": true
+ }
+}
diff --git a/packages/config-typescript/package.json b/packages/config-typescript/package.json
index 86a319a98a..5bdc715974 100644
--- a/packages/config-typescript/package.json
+++ b/packages/config-typescript/package.json
@@ -1,4 +1,7 @@
{
"name": "@roo-code-cloud/config-typescript",
- "private": true
+ "private": true,
+ "publishConfig": {
+ "access": "public"
+ }
}
diff --git a/packages/config-typescript/vscode-library.json b/packages/config-typescript/vscode-library.json
new file mode 100644
index 0000000000..9de0aa75cf
--- /dev/null
+++ b/packages/config-typescript/vscode-library.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "./base.json",
+ "compilerOptions": {
+ "types": ["vitest/globals"],
+ "outDir": "dist",
+ "module": "esnext",
+ "moduleResolution": "Bundler",
+ "noUncheckedIndexedAccess": false,
+ "useUnknownInCatchVariables": false
+ }
+}
diff --git a/packages/ipc/eslint.config.mjs b/packages/ipc/eslint.config.mjs
new file mode 100644
index 0000000000..c072244298
--- /dev/null
+++ b/packages/ipc/eslint.config.mjs
@@ -0,0 +1,4 @@
+import { config } from "@roo-code-cloud/config-eslint/base"
+
+/** @type {import("eslint").Linter.Config} */
+export default [...config]
diff --git a/packages/ipc/package.json b/packages/ipc/package.json
new file mode 100644
index 0000000000..ebfbd641fe
--- /dev/null
+++ b/packages/ipc/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "@roo-code-cloud/ipc",
+ "private": true,
+ "type": "module",
+ "exports": "./src/index.ts",
+ "scripts": {
+ "lint": "eslint src --ext=ts --max-warnings=0",
+ "check-types": "tsc --noEmit",
+ "clean": "rimraf .turbo"
+ },
+ "dependencies": {
+ "@roo-code/types": "^1.26.0",
+ "node-ipc": "^12.0.0"
+ },
+ "devDependencies": {
+ "@roo-code-cloud/config-eslint": "workspace:^",
+ "@roo-code-cloud/config-typescript": "workspace:^",
+ "@types/node": "20.x",
+ "@types/node-ipc": "^9.2.3",
+ "vitest": "^3.2.3"
+ }
+}
diff --git a/packages/ipc/src/index.ts b/packages/ipc/src/index.ts
new file mode 100644
index 0000000000..1acebbac64
--- /dev/null
+++ b/packages/ipc/src/index.ts
@@ -0,0 +1,2 @@
+export * from './ipc-client.js';
+export * from './ipc-server.js';
diff --git a/packages/ipc/src/ipc-client.ts b/packages/ipc/src/ipc-client.ts
new file mode 100644
index 0000000000..a99928d4e9
--- /dev/null
+++ b/packages/ipc/src/ipc-client.ts
@@ -0,0 +1,129 @@
+import EventEmitter from 'node:events';
+import * as crypto from 'node:crypto';
+
+import ipc from 'node-ipc';
+
+import {
+ type TaskCommand,
+ type IpcClientEvents,
+ type IpcMessage,
+ IpcOrigin,
+ IpcMessageType,
+ ipcMessageSchema,
+} from '@roo-code/types';
+
+export class IpcClient extends EventEmitter {
+ private readonly _socketPath: string;
+ private readonly _id: string;
+ private readonly _log: (...args: unknown[]) => void;
+ private _isConnected = false;
+ private _clientId?: string;
+
+ constructor(socketPath: string, log = console.log) {
+ super();
+
+ this._socketPath = socketPath;
+ this._id = `roo-code-evals-${crypto.randomBytes(6).toString('hex')}`;
+ this._log = log;
+
+ ipc.config.silent = true;
+
+ ipc.connectTo(this._id, this.socketPath, () => {
+ ipc.of[this._id]?.on('connect', () => this.onConnect());
+ ipc.of[this._id]?.on('disconnect', () => this.onDisconnect());
+ ipc.of[this._id]?.on('message', (data) => this.onMessage(data));
+ });
+ }
+
+ private onConnect() {
+ if (this._isConnected) {
+ return;
+ }
+
+ this.log('[client#onConnect]');
+ this._isConnected = true;
+ this.emit(IpcMessageType.Connect);
+ }
+
+ private onDisconnect() {
+ if (!this._isConnected) {
+ return;
+ }
+
+ this.log('[client#onDisconnect]');
+ this._isConnected = false;
+ this.emit(IpcMessageType.Disconnect);
+ }
+
+ private onMessage(data: unknown) {
+ if (typeof data !== 'object') {
+ this._log('[client#onMessage] invalid data', data);
+ return;
+ }
+
+ const result = ipcMessageSchema.safeParse(data);
+
+ if (!result.success) {
+ this.log('[client#onMessage] invalid payload', result.error, data);
+ return;
+ }
+
+ const payload = result.data;
+
+ if (payload.origin === IpcOrigin.Server) {
+ switch (payload.type) {
+ case IpcMessageType.Ack:
+ this._clientId = payload.data.clientId;
+ this.emit(IpcMessageType.Ack, payload.data);
+ break;
+ case IpcMessageType.TaskEvent:
+ this.emit(IpcMessageType.TaskEvent, payload.data);
+ break;
+ }
+ }
+ }
+
+ private log(...args: unknown[]) {
+ this._log(...args);
+ }
+
+ public sendCommand(command: TaskCommand) {
+ const message: IpcMessage = {
+ type: IpcMessageType.TaskCommand,
+ origin: IpcOrigin.Client,
+ clientId: this._clientId!,
+ data: command,
+ };
+
+ this.sendMessage(message);
+ }
+
+ public sendMessage(message: IpcMessage) {
+ ipc.of[this._id]?.emit('message', message);
+ }
+
+ public disconnect() {
+ try {
+ ipc.disconnect(this._id);
+ // @TODO: Should we set _disconnect here?
+ } catch (error) {
+ this.log('[client#disconnect] error disconnecting', error);
+ }
+ }
+
+ public get socketPath() {
+ return this._socketPath;
+ }
+
+ public get clientId() {
+ return this._clientId;
+ }
+
+ public get isConnected() {
+ return this._isConnected;
+ }
+
+ public get isReady() {
+ return this._isConnected && this._clientId !== undefined;
+ }
+}
diff --git a/packages/ipc/src/ipc-server.ts b/packages/ipc/src/ipc-server.ts
new file mode 100644
index 0000000000..379fb01aae
--- /dev/null
+++ b/packages/ipc/src/ipc-server.ts
@@ -0,0 +1,149 @@
+import EventEmitter from 'node:events';
+import { Socket } from 'node:net';
+import * as crypto from 'node:crypto';
+
+import ipc from 'node-ipc';
+
+import {
+ type IpcServerEvents,
+ type RooCodeIpcServer,
+ IpcOrigin,
+ IpcMessageType,
+ type IpcMessage,
+ ipcMessageSchema,
+} from '@roo-code/types';
+
+export class IpcServer
+ extends EventEmitter
+ implements RooCodeIpcServer
+{
+ private readonly _socketPath: string;
+ private readonly _log: (...args: unknown[]) => void;
+ private readonly _clients: Map;
+
+ private _isListening = false;
+
+ constructor(socketPath: string, log = console.log) {
+ super();
+
+ this._socketPath = socketPath;
+ this._log = log;
+ this._clients = new Map();
+ }
+
+ public listen() {
+ this._isListening = true;
+
+ ipc.config.silent = true;
+
+ ipc.serve(this.socketPath, () => {
+ ipc.server.on('connect', (socket) => this.onConnect(socket));
+ ipc.server.on('socket.disconnected', (socket) =>
+ this.onDisconnect(socket),
+ );
+ ipc.server.on('message', (data) => this.onMessage(data));
+ });
+
+ ipc.server.start();
+ }
+
+ private onConnect(socket: Socket) {
+ const clientId = crypto.randomBytes(6).toString('hex');
+ this._clients.set(clientId, socket);
+ this.log(
+ `[server#onConnect] clientId = ${clientId}, # clients = ${this._clients.size}`,
+ );
+
+ this.send(socket, {
+ type: IpcMessageType.Ack,
+ origin: IpcOrigin.Server,
+ data: { clientId, pid: process.pid, ppid: process.ppid },
+ });
+
+ this.emit(IpcMessageType.Connect, clientId);
+ }
+
+ private onDisconnect(destroyedSocket: Socket) {
+ let disconnectedClientId: string | undefined;
+
+ for (const [clientId, socket] of this._clients.entries()) {
+ if (socket === destroyedSocket) {
+ disconnectedClientId = clientId;
+ this._clients.delete(clientId);
+ break;
+ }
+ }
+
+ this.log(
+ `[server#socket.disconnected] clientId = ${disconnectedClientId}, # clients = ${this._clients.size}`,
+ );
+
+ if (disconnectedClientId) {
+ this.emit(IpcMessageType.Disconnect, disconnectedClientId);
+ }
+ }
+
+ private onMessage(data: unknown) {
+ if (typeof data !== 'object') {
+ this.log('[server#onMessage] invalid data', data);
+ return;
+ }
+
+ const result = ipcMessageSchema.safeParse(data);
+
+ if (!result.success) {
+ this.log(
+ '[server#onMessage] invalid payload',
+ result.error.format(),
+ data,
+ );
+ return;
+ }
+
+ const payload = result.data;
+
+ if (payload.origin === IpcOrigin.Client) {
+ switch (payload.type) {
+ case IpcMessageType.TaskCommand:
+ this.emit(IpcMessageType.TaskCommand, payload.clientId, payload.data);
+ break;
+ default:
+ this.log(
+ `[server#onMessage] unhandled payload: ${JSON.stringify(payload)}`,
+ );
+ break;
+ }
+ }
+ }
+
+ private log(...args: unknown[]) {
+ this._log(...args);
+ }
+
+ public broadcast(message: IpcMessage) {
+ // this.log("[server#broadcast] message =", message)
+ ipc.server.broadcast('message', message);
+ }
+
+ public send(client: string | Socket, message: IpcMessage) {
+ // this.log("[server#send] message =", message)
+
+ if (typeof client === 'string') {
+ const socket = this._clients.get(client);
+
+ if (socket) {
+ ipc.server.emit(socket, 'message', message);
+ }
+ } else {
+ ipc.server.emit(client, 'message', message);
+ }
+ }
+
+ public get socketPath() {
+ return this._socketPath;
+ }
+
+ public get isListening() {
+ return this._isListening;
+ }
+}
diff --git a/packages/ipc/tsconfig.json b/packages/ipc/tsconfig.json
new file mode 100644
index 0000000000..49f9f64bcd
--- /dev/null
+++ b/packages/ipc/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@roo-code-cloud/config-typescript/base.json",
+ "compilerOptions": {
+ "types": ["vitest/globals"]
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 57809fbb3c..6dbe762f5a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -37,7 +37,87 @@ importers:
specifier: ^5.8.3
version: 5.8.3
- apps/roomote: {}
+ apps/roomote:
+ dependencies:
+ '@bull-board/api':
+ specifier: ^6.10.1
+ version: 6.10.1(@bull-board/ui@6.10.1)
+ '@bull-board/express':
+ specifier: ^6.10.1
+ version: 6.10.1
+ '@bull-board/ui':
+ specifier: ^6.10.1
+ version: 6.10.1
+ '@roo-code-cloud/ipc':
+ specifier: workspace:^
+ version: link:../../packages/ipc
+ '@roo-code/types':
+ specifier: ^1.26.0
+ version: 1.26.0
+ bullmq:
+ specifier: ^5.37.0
+ version: 5.54.3
+ drizzle-orm:
+ specifier: ^0.44.1
+ version: 0.44.2(@electric-sql/pglite@0.3.0)(@libsql/client-wasm@0.15.5)(@opentelemetry/api@1.9.0)(@types/pg@8.15.2)(pg@8.15.6)(postgres@3.4.7)
+ execa:
+ specifier: ^9.6.0
+ version: 9.6.0
+ express:
+ specifier: ^5.1.0
+ version: 5.1.0
+ ioredis:
+ specifier: ^5.4.3
+ version: 5.6.1
+ next:
+ specifier: ^15.3.3
+ version: 15.3.3(@babel/core@7.27.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ p-wait-for:
+ specifier: ^5.0.2
+ version: 5.0.2
+ postgres:
+ specifier: ^3.4.7
+ version: 3.4.7
+ react:
+ specifier: ^19.1.0
+ version: 19.1.0
+ react-dom:
+ specifier: ^19.1.0
+ version: 19.1.0(react@19.1.0)
+ zod:
+ specifier: ^3.25.41
+ version: 3.25.41
+ devDependencies:
+ '@roo-code-cloud/config-eslint':
+ specifier: workspace:^
+ version: link:../../packages/config-eslint
+ '@roo-code-cloud/config-typescript':
+ specifier: workspace:^
+ version: link:../../packages/config-typescript
+ '@types/express':
+ specifier: ^5.0.3
+ version: 5.0.3
+ '@types/node':
+ specifier: ^22.15.20
+ version: 22.15.32
+ '@types/react':
+ specifier: ^19.1.6
+ version: 19.1.6
+ '@types/react-dom':
+ specifier: ^19.1.6
+ version: 19.1.6(@types/react@19.1.6)
+ concurrently:
+ specifier: ^9.1.0
+ version: 9.1.2
+ drizzle-kit:
+ specifier: ^0.31.1
+ version: 0.31.1
+ tsx:
+ specifier: ^4.19.3
+ version: 4.20.3
+ vitest:
+ specifier: ^3.2.3
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@22.15.32)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
apps/web:
dependencies:
@@ -61,46 +141,46 @@ importers:
version: 0.5.5(pino@9.7.0)
'@radix-ui/react-accordion':
specifier: ^1.2.11
- version: 1.2.11(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.2.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-checkbox':
specifier: ^1.3.2
- version: 1.3.2(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.3.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-dialog':
specifier: ^1.1.14
- version: 1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.15
- version: 2.1.15(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-icons':
specifier: ^1.3.2
version: 1.3.2(react@19.1.0)
'@radix-ui/react-label':
specifier: ^2.1.7
- version: 2.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 2.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-popover':
specifier: ^1.1.14
- version: 1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-separator':
specifier: ^1.1.7
- version: 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slider':
specifier: ^1.3.5
- version: 1.3.5(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.3.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot':
specifier: ^1.2.3
version: 1.2.3(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-switch':
specifier: ^1.2.5
- version: 1.2.5(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.2.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-tabs':
specifier: ^1.1.12
- version: 1.1.12(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.12(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-toast':
specifier: ^1.2.14
- version: 1.2.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.2.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-tooltip':
specifier: ^1.2.7
- version: 1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@roo-code/types':
specifier: ^1.26.0
version: 1.26.0
@@ -130,7 +210,7 @@ importers:
version: 2.1.1
cmdk:
specifier: ^1.1.1
- version: 1.1.1(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.1(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
date-fns:
specifier: ^4.1.0
version: 4.1.0
@@ -208,7 +288,7 @@ importers:
version: 11.1.0
vaul:
specifier: ^1.1.2
- version: 1.1.2(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 1.1.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
zod:
specifier: ^3.25.41
version: 3.25.41
@@ -225,12 +305,18 @@ importers:
'@next/eslint-plugin-next':
specifier: ^15.3.3
version: 15.3.3
+ '@roo-code-cloud/config-eslint':
+ specifier: workspace:^
+ version: link:../../packages/config-eslint
+ '@roo-code-cloud/config-typescript':
+ specifier: workspace:^
+ version: link:../../packages/config-typescript
'@testing-library/jest-dom':
specifier: ^6.6.3
version: 6.6.3
'@testing-library/react':
specifier: ^16.3.0
- version: 16.3.0(@testing-library/dom@10.4.0)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@testing-library/user-event':
specifier: ^14.6.1
version: 14.6.1(@testing-library/dom@10.4.0)
@@ -243,15 +329,12 @@ importers:
'@types/react':
specifier: ^19.1.6
version: 19.1.6
+ '@types/react-dom':
+ specifier: ^19.1.6
+ version: 19.1.6(@types/react@19.1.6)
'@vitejs/plugin-react':
- specifier: ^4.5.0
- version: 4.5.0(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
- '@vitest/coverage-v8':
- specifier: ^3.1.4
- version: 3.1.4(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
- '@vitest/expect':
- specifier: ^3.1.4
- version: 3.1.4
+ specifier: ^4.5.2
+ version: 4.5.2(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
drizzle-kit:
specifier: ^0.31.1
version: 0.31.1
@@ -292,15 +375,71 @@ importers:
specifier: ^5.1.4
version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
vitest:
- specifier: ^3.1.4
- version: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ specifier: ^3.2.3
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
- packages/config-eslint: {}
+ packages/config-eslint:
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.22.0
+ version: 9.29.0
+ '@next/eslint-plugin-next':
+ specifier: ^15.2.1
+ version: 15.3.3
+ eslint:
+ specifier: ^9.27.0
+ version: 9.29.0(jiti@2.4.2)
+ eslint-config-prettier:
+ specifier: ^10.1.1
+ version: 10.1.5(eslint@9.29.0(jiti@2.4.2))
+ eslint-plugin-only-warn:
+ specifier: ^1.1.0
+ version: 1.1.0
+ eslint-plugin-react:
+ specifier: ^7.37.4
+ version: 7.37.5(eslint@9.29.0(jiti@2.4.2))
+ eslint-plugin-react-hooks:
+ specifier: ^5.2.0
+ version: 5.2.0(eslint@9.29.0(jiti@2.4.2))
+ eslint-plugin-turbo:
+ specifier: ^2.4.4
+ version: 2.5.3(eslint@9.29.0(jiti@2.4.2))(turbo@2.5.4)
+ globals:
+ specifier: ^16.0.0
+ version: 16.2.0
+ typescript-eslint:
+ specifier: ^8.26.0
+ version: 8.33.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
packages/config-typescript: {}
packages/db: {}
+ packages/ipc:
+ dependencies:
+ '@roo-code/types':
+ specifier: ^1.26.0
+ version: 1.26.0
+ node-ipc:
+ specifier: ^12.0.0
+ version: 12.0.0
+ devDependencies:
+ '@roo-code-cloud/config-eslint':
+ specifier: workspace:^
+ version: link:../config-eslint
+ '@roo-code-cloud/config-typescript':
+ specifier: workspace:^
+ version: link:../config-typescript
+ '@types/node':
+ specifier: 20.x
+ version: 20.19.1
+ '@types/node-ipc':
+ specifier: ^9.2.3
+ version: 9.2.3
+ vitest:
+ specifier: ^3.2.3
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+
packages:
'@adobe/css-tools@4.4.3':
@@ -335,6 +474,10 @@ packages:
resolution: {integrity: sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==}
engines: {node: '>=6.9.0'}
+ '@babel/core@7.27.4':
+ resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==}
+ engines: {node: '>=6.9.0'}
+
'@babel/generator@7.27.3':
resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==}
engines: {node: '>=6.9.0'}
@@ -373,11 +516,20 @@ packages:
resolution: {integrity: sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==}
engines: {node: '>=6.9.0'}
+ '@babel/helpers@7.27.6':
+ resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
+ engines: {node: '>=6.9.0'}
+
'@babel/parser@7.27.3':
resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==}
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.27.5':
+ resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/plugin-transform-react-jsx-self@7.27.1':
resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
engines: {node: '>=6.9.0'}
@@ -406,13 +558,28 @@ packages:
resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==}
engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.27.4':
+ resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.27.3':
resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==}
engines: {node: '>=6.9.0'}
- '@bcoe/v8-coverage@1.0.2':
- resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
- engines: {node: '>=18'}
+ '@babel/types@7.27.6':
+ resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@bull-board/api@6.10.1':
+ resolution: {integrity: sha512-VPkZa2XZI2Wk2MqK1XyiiS+tOhNan54mnm2fpv2KA0fdZ92mQqNjhKkOpsykhQv9XUEc8cCRlZqGxf67YCMJbQ==}
+ peerDependencies:
+ '@bull-board/ui': 6.10.1
+
+ '@bull-board/express@6.10.1':
+ resolution: {integrity: sha512-IZl+t6B8bGCHqd/8Mbvit9RXqndXBe2Kx7pYHq7PZRrEKjK9b643Uizlc+OVqmWpLSjpQMP96K1SO5/Nq24o+A==}
+
+ '@bull-board/ui@6.10.1':
+ resolution: {integrity: sha512-b6z6MBid/0DEShAMFPjPVZoPSoWqRBHCvTknyaxr/m8gL2/C+QP7jlCXut+L7uTFbCj9qs+CreAP0x/VdLI/Ig==}
'@clerk/backend@1.34.0':
resolution: {integrity: sha512-9rZ8hQJVpX5KX2bEpiuVXfpjhojQCiqCWADJDdCI0PCeKxn58Ep0JPYiIcczg4VKUc3a7jve9vXylykG2XajLQ==}
@@ -1038,6 +1205,9 @@ packages:
cpu: [x64]
os: [win32]
+ '@ioredis/commands@1.2.0':
+ resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
+
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -1046,10 +1216,6 @@ packages:
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
engines: {node: '>=18.0.0'}
- '@istanbuljs/schema@0.1.3':
- resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
- engines: {node: '>=8'}
-
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
@@ -1100,6 +1266,36 @@ packages:
resolution: {integrity: sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==}
engines: {node: '>= 10'}
+ '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3':
+ resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3':
+ resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3':
+ resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3':
+ resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3':
+ resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3':
+ resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==}
+ cpu: [x64]
+ os: [win32]
+
'@next/bundle-analyzer@15.3.3':
resolution: {integrity: sha512-9gddnjACK6yOa5IkmeFyzcwZh2rscsb6ZspTd7tymPYKQM96fJuKjn9HrRtPNKiMm7ExKNadAJqREmHdBgHZ9A==}
@@ -1369,10 +1565,6 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.1.0
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
'@playwright/test@1.52.0':
resolution: {integrity: sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==}
engines: {node: '>=18'}
@@ -1838,8 +2030,8 @@ packages:
'@radix-ui/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
- '@rolldown/pluginutils@1.0.0-beta.9':
- resolution: {integrity: sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==}
+ '@rolldown/pluginutils@1.0.0-beta.11':
+ resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==}
'@rollup/plugin-commonjs@28.0.1':
resolution: {integrity: sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==}
@@ -2060,6 +2252,9 @@ packages:
'@schummar/icu-type-parser@1.21.5':
resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
+ '@sec-ant/readable-stream@0.4.1':
+ resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
+
'@sentry-internal/browser-utils@9.23.0':
resolution: {integrity: sha512-hyN2Q6mh7ggw8sDVHeRyWz5LR6gjvf8zHSzQnMaF7QkeSyaeGM/SVSL4ODwqR9TRH7U2ku6nZFMbKhaBPV+Hfg==}
engines: {node: '>=18'}
@@ -2175,6 +2370,10 @@ packages:
peerDependencies:
webpack: '>=4.40.0'
+ '@sindresorhus/merge-streams@4.0.0':
+ resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
+ engines: {node: '>=18'}
+
'@standard-schema/utils@0.3.0':
resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
@@ -2369,6 +2568,12 @@ packages:
'@types/babel__traverse@7.20.7':
resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
+ '@types/body-parser@1.19.6':
+ resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
+
+ '@types/chai@5.2.2':
+ resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
+
'@types/connect@3.4.38':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
@@ -2402,6 +2607,9 @@ packages:
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
'@types/eslint-scope@3.7.7':
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
@@ -2420,9 +2628,18 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/express-serve-static-core@5.0.6':
+ resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==}
+
+ '@types/express@5.0.3':
+ resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==}
+
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+ '@types/http-errors@2.0.5':
+ resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
+
'@types/js-cookie@2.2.7':
resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==}
@@ -2435,6 +2652,9 @@ packages:
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+ '@types/mime@1.3.5':
+ resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
+
'@types/minimist@1.2.5':
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
@@ -2444,6 +2664,12 @@ packages:
'@types/mysql@2.15.26':
resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
+ '@types/node-ipc@9.2.3':
+ resolution: {integrity: sha512-/MvSiF71fYf3+zwqkh/zkVkZj1hl1Uobre9EMFy08mqfJNAmpR0vmPgOUdEIDVgifxHj6G1vYMPLSBLLxoDACQ==}
+
+ '@types/node@20.19.1':
+ resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==}
+
'@types/node@22.15.27':
resolution: {integrity: sha512-5fF+eu5mwihV2BeVtX5vijhdaZOfkQTATrePEaXTcKqI16LhJ7gi2/Vhd9OZM0UojcdmiOCVg5rrax+i1MdoQQ==}
@@ -2462,9 +2688,26 @@ packages:
'@types/pg@8.6.1':
resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==}
+ '@types/qs@6.14.0':
+ resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
+
+ '@types/range-parser@1.2.7':
+ resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
+
+ '@types/react-dom@19.1.6':
+ resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==}
+ peerDependencies:
+ '@types/react': ^19.0.0
+
'@types/react@19.1.6':
resolution: {integrity: sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==}
+ '@types/send@0.17.5':
+ resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==}
+
+ '@types/serve-static@1.15.8':
+ resolution: {integrity: sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==}
+
'@types/shimmer@1.2.0':
resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==}
@@ -2540,49 +2783,40 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
- '@vitejs/plugin-react@4.5.0':
- resolution: {integrity: sha512-JuLWaEqypaJmOJPLWwO335Ig6jSgC1FTONCWAxnqcQthLTK/Yc9aH6hr9z/87xciejbQcnP3GnA1FWUSWeXaeg==}
+ '@vitejs/plugin-react@4.5.2':
+ resolution: {integrity: sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
- vite: ^4.2.0 || ^5.0.0 || ^6.0.0
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0
- '@vitest/coverage-v8@3.1.4':
- resolution: {integrity: sha512-G4p6OtioySL+hPV7Y6JHlhpsODbJzt1ndwHAFkyk6vVjpK03PFsKnauZIzcd0PrK4zAbc5lc+jeZ+eNGiMA+iw==}
- peerDependencies:
- '@vitest/browser': 3.1.4
- vitest: 3.1.4
- peerDependenciesMeta:
- '@vitest/browser':
- optional: true
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
- '@vitest/expect@3.1.4':
- resolution: {integrity: sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA==}
-
- '@vitest/mocker@3.1.4':
- resolution: {integrity: sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA==}
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
peerDependencies:
msw: ^2.4.9
- vite: ^5.0.0 || ^6.0.0
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
- '@vitest/pretty-format@3.1.4':
- resolution: {integrity: sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==}
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
- '@vitest/runner@3.1.4':
- resolution: {integrity: sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==}
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
- '@vitest/snapshot@3.1.4':
- resolution: {integrity: sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg==}
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
- '@vitest/spy@3.1.4':
- resolution: {integrity: sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg==}
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
- '@vitest/utils@3.1.4':
- resolution: {integrity: sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg==}
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -2642,6 +2876,10 @@ packages:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
+ accepts@2.0.0:
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+ engines: {node: '>= 0.6'}
+
acorn-import-attributes@1.9.5:
resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
peerDependencies:
@@ -2778,6 +3016,9 @@ packages:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
+ async@3.2.6:
+ resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
+
atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
@@ -2799,6 +3040,10 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
+ body-parser@2.2.0:
+ resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
+ engines: {node: '>=18'}
+
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
@@ -2823,10 +3068,17 @@ packages:
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
+ bullmq@5.54.3:
+ resolution: {integrity: sha512-MVK2pOkB3hvrIcubwI8dS4qWHJLNKakKPpgRBTw91sIpPZArmvZ4t2hvryyEaJXJbAS/JHd6pKYOUd+RGRkWQQ==}
+
busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'}
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -2922,10 +3174,21 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ cliui@7.0.4:
+ resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ cluster-key-slot@1.1.2:
+ resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
+ engines: {node: '>=0.10.0'}
+
cmdk@1.1.1:
resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==}
peerDependencies:
@@ -2973,9 +3236,30 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ concurrently@9.1.2:
+ resolution: {integrity: sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ content-disposition@1.0.0:
+ resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
+ engines: {node: '>= 0.6'}
+
+ content-type@1.0.5:
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+ engines: {node: '>= 0.6'}
+
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie-signature@1.2.2:
+ resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
+ engines: {node: '>=6.6.0'}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
cookie@1.0.2:
resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==}
engines: {node: '>=18'}
@@ -2983,6 +3267,17 @@ packages:
copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
+ copyfiles@2.4.1:
+ resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==}
+ hasBin: true
+
+ core-util-is@1.0.3:
+ resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
+
+ cron-parser@4.9.0:
+ resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==}
+ engines: {node: '>=12.0.0'}
+
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
@@ -3114,6 +3409,14 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
+ denque@2.1.0:
+ resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
+ engines: {node: '>=0.10'}
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
@@ -3249,6 +3552,98 @@ packages:
sqlite3:
optional: true
+ drizzle-orm@0.44.2:
+ resolution: {integrity: sha512-zGAqBzWWkVSFjZpwPOrmCrgO++1kZ5H/rZ4qTGeGOe18iXGVJWf3WPfHOVwFIbmi8kHjfJstC6rJomzGx8g/dQ==}
+ peerDependencies:
+ '@aws-sdk/client-rds-data': '>=3'
+ '@cloudflare/workers-types': '>=4'
+ '@electric-sql/pglite': '>=0.2.0'
+ '@libsql/client': '>=0.10.0'
+ '@libsql/client-wasm': '>=0.10.0'
+ '@neondatabase/serverless': '>=0.10.0'
+ '@op-engineering/op-sqlite': '>=2'
+ '@opentelemetry/api': ^1.4.1
+ '@planetscale/database': '>=1.13'
+ '@prisma/client': '*'
+ '@tidbcloud/serverless': '*'
+ '@types/better-sqlite3': '*'
+ '@types/pg': '*'
+ '@types/sql.js': '*'
+ '@upstash/redis': '>=1.34.7'
+ '@vercel/postgres': '>=0.8.0'
+ '@xata.io/client': '*'
+ better-sqlite3: '>=7'
+ bun-types: '*'
+ expo-sqlite: '>=14.0.0'
+ gel: '>=2'
+ knex: '*'
+ kysely: '*'
+ mysql2: '>=2'
+ pg: '>=8'
+ postgres: '>=3'
+ prisma: '*'
+ sql.js: '>=1'
+ sqlite3: '>=5'
+ peerDependenciesMeta:
+ '@aws-sdk/client-rds-data':
+ optional: true
+ '@cloudflare/workers-types':
+ optional: true
+ '@electric-sql/pglite':
+ optional: true
+ '@libsql/client':
+ optional: true
+ '@libsql/client-wasm':
+ optional: true
+ '@neondatabase/serverless':
+ optional: true
+ '@op-engineering/op-sqlite':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@prisma/client':
+ optional: true
+ '@tidbcloud/serverless':
+ optional: true
+ '@types/better-sqlite3':
+ optional: true
+ '@types/pg':
+ optional: true
+ '@types/sql.js':
+ optional: true
+ '@upstash/redis':
+ optional: true
+ '@vercel/postgres':
+ optional: true
+ '@xata.io/client':
+ optional: true
+ better-sqlite3:
+ optional: true
+ bun-types:
+ optional: true
+ expo-sqlite:
+ optional: true
+ gel:
+ optional: true
+ knex:
+ optional: true
+ kysely:
+ optional: true
+ mysql2:
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+ prisma:
+ optional: true
+ sql.js:
+ optional: true
+ sqlite3:
+ optional: true
+
drizzle-zod@0.7.1:
resolution: {integrity: sha512-nZzALOdz44/AL2U005UlmMqaQ1qe5JfanvLujiTHiiT8+vZJTBFhj3pY4Vk+L6UWyKFfNmLhk602Hn4kCTynKQ==}
peerDependencies:
@@ -3265,6 +3660,10 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ easy-stack@1.0.1:
+ resolution: {integrity: sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==}
+ engines: {node: '>=6.0.0'}
+
ecdsa-sig-formatter@1.0.11:
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
@@ -3272,6 +3671,14 @@ packages:
resolution: {integrity: sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==}
engines: {bun: '>=1', deno: '>=2', node: '>=16'}
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+ ejs@3.1.10:
+ resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+
electron-to-chromium@1.5.161:
resolution: {integrity: sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==}
@@ -3284,6 +3691,10 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
end-of-stream@1.4.4:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
@@ -3359,6 +3770,9 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -3450,6 +3864,14 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ event-pubsub@5.0.3:
+ resolution: {integrity: sha512-2QiHxshejKgJrYMzSI9MEHrvhmzxBL+eLyiM5IiyjDBySkgwS2+tdtnO3gbx8pEisu/yOFCIhfCb63gCEu0yBQ==}
+ engines: {node: '>=13.0.0'}
+
event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
@@ -3468,10 +3890,18 @@ packages:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
+ execa@9.6.0:
+ resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==}
+ engines: {node: ^18.19.0 || >=20.5.0}
+
expect-type@1.2.1:
resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
engines: {node: '>=12.0.0'}
+ express@5.1.0:
+ resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
+ engines: {node: '>= 18'}
+
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -3526,14 +3956,25 @@ packages:
picomatch:
optional: true
+ figures@6.1.0:
+ resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
+ engines: {node: '>=18'}
+
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
+ filelist@1.0.4:
+ resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
+ finalhandler@2.1.0:
+ resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
+ engines: {node: '>= 0.8'}
+
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@@ -3560,6 +4001,14 @@ packages:
forwarded-parse@2.1.2:
resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
+
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -3590,6 +4039,10 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
get-east-asian-width@1.3.0:
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
engines: {node: '>=18'}
@@ -3610,6 +4063,10 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
+ get-stream@9.0.1:
+ resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
+ engines: {node: '>=18'}
+
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
@@ -3628,15 +4085,15 @@ packages:
glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
- glob@10.4.5:
- resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
- hasBin: true
-
glob@11.0.2:
resolution: {integrity: sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==}
engines: {node: 20 || >=22}
hasBin: true
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
+
glob@9.3.5:
resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -3734,6 +4191,10 @@ packages:
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+ http-errors@2.0.0:
+ resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+ engines: {node: '>= 0.8'}
+
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@@ -3750,6 +4211,10 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'}
+ human-signals@8.0.1:
+ resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
+ engines: {node: '>=18.18.0'}
+
husky@9.1.7:
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
engines: {node: '>=18'}
@@ -3788,6 +4253,13 @@ packages:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'}
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
@@ -3805,6 +4277,14 @@ packages:
intl-messageformat@10.7.16:
resolution: {integrity: sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==}
+ ioredis@5.6.1:
+ resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==}
+ engines: {node: '>=12.22.0'}
+
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
is-alphabetical@2.0.1:
resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
@@ -3918,6 +4398,9 @@ packages:
is-potential-custom-element-name@1.0.1:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
is-reference@1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
@@ -3937,6 +4420,10 @@ packages:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
+ is-stream@4.0.1:
+ resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
+ engines: {node: '>=18'}
+
is-string@1.1.1:
resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
engines: {node: '>= 0.4'}
@@ -3949,6 +4436,10 @@ packages:
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
engines: {node: '>= 0.4'}
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
is-weakmap@2.0.2:
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
engines: {node: '>= 0.4'}
@@ -3961,6 +4452,12 @@ packages:
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
engines: {node: '>= 0.4'}
+ isarray@0.0.1:
+ resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==}
+
+ isarray@1.0.0:
+ resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+
isarray@2.0.5:
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
@@ -3971,33 +4468,19 @@ packages:
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
engines: {node: '>=16'}
- istanbul-lib-coverage@3.2.2:
- resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
- engines: {node: '>=8'}
-
- istanbul-lib-report@3.0.1:
- resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
- engines: {node: '>=10'}
-
- istanbul-lib-source-maps@5.0.6:
- resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
- engines: {node: '>=10'}
-
- istanbul-reports@3.1.7:
- resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
- engines: {node: '>=8'}
-
iterator.prototype@1.1.5:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
jackspeak@4.1.1:
resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
engines: {node: 20 || >=22}
+ jake@10.9.2:
+ resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
jest-worker@27.5.1:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
@@ -4020,9 +4503,20 @@ packages:
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
engines: {node: '>=14'}
+ js-message@1.0.7:
+ resolution: {integrity: sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==}
+ engines: {node: '>=0.6.0'}
+
+ js-queue@2.0.2:
+ resolution: {integrity: sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==}
+ engines: {node: '>=1.0.0'}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
@@ -4178,9 +4672,15 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash.defaults@4.2.0:
+ resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
+
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+ lodash.isarguments@3.1.0:
+ resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
+
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
@@ -4219,6 +4719,9 @@ packages:
loupe@3.1.3:
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
+ loupe@3.1.4:
+ resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==}
+
lower-case@2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
@@ -4241,6 +4744,10 @@ packages:
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ luxon@3.6.1:
+ resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==}
+ engines: {node: '>=12'}
+
lz-string@1.5.0:
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
hasBin: true
@@ -4252,13 +4759,6 @@ packages:
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
engines: {node: '>=12'}
- magicast@0.3.5:
- resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
-
- make-dir@4.0.0:
- resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
- engines: {node: '>=10'}
-
map-obj@1.0.1:
resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
engines: {node: '>=0.10.0'}
@@ -4298,10 +4798,18 @@ packages:
mdn-data@2.0.14:
resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
+ media-typer@1.1.0:
+ resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
+ engines: {node: '>= 0.8'}
+
meow@9.0.0:
resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==}
engines: {node: '>=10'}
+ merge-descriptors@2.0.0:
+ resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
+ engines: {node: '>=18'}
+
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -4380,10 +4888,18 @@ packages:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mime-types@3.0.1:
+ resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
+ engines: {node: '>= 0.6'}
+
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
@@ -4403,6 +4919,10 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+
minimatch@8.0.4:
resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -4430,6 +4950,11 @@ packages:
resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
engines: {node: '>= 18'}
+ mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+
mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
@@ -4445,6 +4970,13 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ msgpackr-extract@3.0.3:
+ resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==}
+ hasBin: true
+
+ msgpackr@1.11.4:
+ resolution: {integrity: sha512-uaff7RG9VIC4jacFW9xzL3jc0iM32DNHe4jYVycBcjUePT/Klnfj7pqtWJt9khvDFizmjN2TlYniYmSS2LIaZg==}
+
nano-css@5.6.2:
resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==}
peerDependencies:
@@ -4518,6 +5050,9 @@ packages:
no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
+ node-abort-controller@3.1.1:
+ resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
+
node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
@@ -4527,9 +5062,20 @@ packages:
encoding:
optional: true
+ node-gyp-build-optional-packages@5.2.2:
+ resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==}
+ hasBin: true
+
+ node-ipc@12.0.0:
+ resolution: {integrity: sha512-QHJ2gAJiqA3cM7cQiRjLsfCOBRB0TwQ6axYD4FSllQWipEbP6i7Se1dP8EzPKk5J1nCe27W69eqPmCoKyQ61Vg==}
+ engines: {node: '>=14'}
+
node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
+ noms@0.0.0:
+ resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==}
+
normalize-package-data@2.5.0:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
@@ -4545,6 +5091,10 @@ packages:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
+ npm-run-path@6.0.0:
+ resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
+ engines: {node: '>=18'}
+
nwsapi@2.2.20:
resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
@@ -4587,6 +5137,10 @@ packages:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@@ -4626,10 +5180,18 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
+ p-timeout@6.1.4:
+ resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==}
+ engines: {node: '>=14.16'}
+
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
+ p-wait-for@5.0.2:
+ resolution: {integrity: sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA==}
+ engines: {node: '>=12'}
+
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
@@ -4644,17 +5206,33 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
+ parse-ms@4.0.0:
+ resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
+ engines: {node: '>=18'}
+
parse5@7.3.0:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
+ path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@@ -4666,6 +5244,10 @@ packages:
resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
engines: {node: 20 || >=22}
+ path-to-regexp@8.2.0:
+ resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
+ engines: {node: '>=16'}
+
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -4825,6 +5407,13 @@ packages:
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+ pretty-ms@9.2.0:
+ resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==}
+ engines: {node: '>=18'}
+
+ process-nextick-args@2.0.1:
+ resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
@@ -4842,6 +5431,10 @@ packages:
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
@@ -4869,6 +5462,14 @@ packages:
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+ range-parser@1.2.1:
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+ engines: {node: '>= 0.6'}
+
+ raw-body@3.0.0:
+ resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
+ engines: {node: '>= 0.8'}
+
react-dom@19.1.0:
resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==}
peerDependencies:
@@ -4965,6 +5566,12 @@ packages:
resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
engines: {node: '>=8'}
+ readable-stream@1.0.34:
+ resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==}
+
+ readable-stream@2.3.8:
+ resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+
readable-stream@4.7.0:
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4991,6 +5598,17 @@ packages:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'}
+ redis-errors@1.2.0:
+ resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
+ engines: {node: '>=4'}
+
+ redis-info@3.1.0:
+ resolution: {integrity: sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg==}
+
+ redis-parser@3.0.0:
+ resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
+ engines: {node: '>=4'}
+
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@@ -5005,6 +5623,10 @@ packages:
remark-rehype@11.1.2:
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
@@ -5062,6 +5684,10 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ router@2.2.0:
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+ engines: {node: '>= 18'}
+
rrweb-cssom@0.8.0:
resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
@@ -5071,10 +5697,16 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ rxjs@7.8.2:
+ resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
+
safe-array-concat@1.1.3:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
+ safe-buffer@5.1.2:
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -5124,6 +5756,10 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ send@1.2.0:
+ resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
+ engines: {node: '>= 18'}
+
serialize-error@8.1.0:
resolution: {integrity: sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==}
engines: {node: '>=10'}
@@ -5131,6 +5767,10 @@ packages:
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
+ serve-static@2.2.0:
+ resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
+ engines: {node: '>= 18'}
+
server-only@0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
@@ -5150,6 +5790,9 @@ packages:
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
engines: {node: '>= 0.4'}
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
sharp@0.34.2:
resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -5162,6 +5805,10 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
+
shimmer@1.2.1:
resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
@@ -5278,6 +5925,17 @@ packages:
resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==}
engines: {node: '>=6'}
+ standard-as-callback@2.1.0:
+ resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
+
+ statuses@2.0.1:
+ resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
+ engines: {node: '>= 0.8'}
+
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
std-env@3.9.0:
resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
@@ -5324,6 +5982,12 @@ packages:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
engines: {node: '>= 0.4'}
+ string_decoder@0.10.31:
+ resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==}
+
+ 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==}
@@ -5342,6 +6006,10 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
+ strip-final-newline@4.0.0:
+ resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
+ engines: {node: '>=18'}
+
strip-indent@3.0.0:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
engines: {node: '>=8'}
@@ -5350,6 +6018,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
+ strip-literal@3.0.0:
+ resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==}
+
stripe@18.2.0:
resolution: {integrity: sha512-RpOaGh5CLs3SYeVXw1CIQZNwPVADBJtgNyUgu+ZkIvu3u4pkZvNrlKr+WaLoNjSPQWef0dikxDS2AKHBl/l3bg==}
engines: {node: '>=12.*'}
@@ -5359,6 +6030,14 @@ packages:
'@types/node':
optional: true
+ strong-type@0.1.6:
+ resolution: {integrity: sha512-eJe5caH6Pi5oMMeQtIoBPpvNu/s4jiyb63u5tkHNnQXomK+puyQ5i+Z5iTLBr/xUz/pIcps0NSfzzFI34+gAXg==}
+ engines: {node: '>=12.0.0'}
+
+ strong-type@1.1.0:
+ resolution: {integrity: sha512-X5Z6riticuH5GnhUyzijfDi1SoXas8ODDyN7K8lJeQK+Jfi4dKdoJGL4CXTskY/ATBcN+rz5lROGn1tAUkOX7g==}
+ engines: {node: '>=12.21.0'}
+
style-to-js@1.1.16:
resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==}
@@ -5441,10 +6120,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- test-exclude@7.0.1:
- resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
- engines: {node: '>=18'}
-
thread-stream@3.1.0:
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
@@ -5452,6 +6127,9 @@ packages:
resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==}
engines: {node: '>=10'}
+ through2@2.0.5:
+ resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
+
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
@@ -5465,16 +6143,16 @@ packages:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'}
- tinypool@1.0.2:
- resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
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==}
+ tinyspy@4.0.3:
+ resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==}
engines: {node: '>=14.0.0'}
tldts-core@6.1.86:
@@ -5491,6 +6169,10 @@ packages:
toggle-selection@1.0.6:
resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==}
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
@@ -5506,6 +6188,10 @@ packages:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'}
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@@ -5605,6 +6291,10 @@ packages:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
+ type-is@2.0.1:
+ resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
+ engines: {node: '>= 0.6'}
+
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -5640,6 +6330,10 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ unicorn-magic@0.3.0:
+ resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
+ engines: {node: '>=18'}
+
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
@@ -5658,9 +6352,17 @@ packages:
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
unplugin@1.0.1:
resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==}
+ untildify@4.0.0:
+ resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
+ engines: {node: '>=8'}
+
update-browserslist-db@1.1.3:
resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
hasBin: true
@@ -5700,6 +6402,9 @@ packages:
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
uuid@11.1.0:
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
hasBin: true
@@ -5711,6 +6416,10 @@ packages:
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
vaul@1.1.2:
resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==}
peerDependencies:
@@ -5726,8 +6435,8 @@ packages:
victory-vendor@36.9.2:
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
- vite-node@3.1.4:
- resolution: {integrity: sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==}
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
@@ -5779,16 +6488,16 @@ packages:
yaml:
optional: true
- vitest@3.1.4:
- resolution: {integrity: sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ==}
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.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.4
- '@vitest/ui': 3.1.4
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -5948,6 +6657,10 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
@@ -5967,10 +6680,26 @@ packages:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@16.2.0:
+ resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+ engines: {node: '>=10'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ yoctocolors@2.1.1:
+ resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
+ engines: {node: '>=18'}
+
zod@3.25.41:
resolution: {integrity: sha512-8+sDJTGtCYIDBhdqDygp0ffj8kzziRKqAJPhpYObbElJ+3TRe/mnlnwH+/OMa3kKhueS4Drm5UMW00/u1p07zA==}
@@ -6032,9 +6761,29 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/core@7.27.4':
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.27.3
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
+ '@babel/helpers': 7.27.6
+ '@babel/parser': 7.27.5
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.27.4
+ '@babel/types': 7.27.3
+ convert-source-map: 2.0.0
+ debug: 4.4.1
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/generator@7.27.3':
dependencies:
- '@babel/parser': 7.27.3
+ '@babel/parser': 7.27.5
'@babel/types': 7.27.3
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
@@ -6050,7 +6799,7 @@ snapshots:
'@babel/helper-module-imports@7.27.1':
dependencies:
- '@babel/traverse': 7.27.3
+ '@babel/traverse': 7.27.4
'@babel/types': 7.27.3
transitivePeerDependencies:
- supports-color
@@ -6060,7 +6809,16 @@ snapshots:
'@babel/core': 7.27.3
'@babel/helper-module-imports': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.3
+ '@babel/traverse': 7.27.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)':
+ dependencies:
+ '@babel/core': 7.27.4
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+ '@babel/traverse': 7.27.4
transitivePeerDependencies:
- supports-color
@@ -6077,18 +6835,27 @@ snapshots:
'@babel/template': 7.27.2
'@babel/types': 7.27.3
+ '@babel/helpers@7.27.6':
+ dependencies:
+ '@babel/template': 7.27.2
+ '@babel/types': 7.27.6
+
'@babel/parser@7.27.3':
dependencies:
'@babel/types': 7.27.3
- '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.3)':
+ '@babel/parser@7.27.5':
dependencies:
- '@babel/core': 7.27.3
+ '@babel/types': 7.27.3
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.4)':
+ dependencies:
+ '@babel/core': 7.27.4
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.3)':
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.4)':
dependencies:
- '@babel/core': 7.27.3
+ '@babel/core': 7.27.4
'@babel/helper-plugin-utils': 7.27.1
'@babel/runtime@7.27.3': {}
@@ -6098,7 +6865,7 @@ snapshots:
'@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
- '@babel/parser': 7.27.3
+ '@babel/parser': 7.27.5
'@babel/types': 7.27.3
'@babel/traverse@7.27.3':
@@ -6113,12 +6880,45 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/traverse@7.27.4':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.27.3
+ '@babel/parser': 7.27.5
+ '@babel/template': 7.27.2
+ '@babel/types': 7.27.3
+ debug: 4.4.1
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/types@7.27.3':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@bcoe/v8-coverage@1.0.2': {}
+ '@babel/types@7.27.6':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+
+ '@bull-board/api@6.10.1(@bull-board/ui@6.10.1)':
+ dependencies:
+ '@bull-board/ui': 6.10.1
+ redis-info: 3.1.0
+
+ '@bull-board/express@6.10.1':
+ dependencies:
+ '@bull-board/api': 6.10.1(@bull-board/ui@6.10.1)
+ '@bull-board/ui': 6.10.1
+ ejs: 3.1.10
+ express: 5.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@bull-board/ui@6.10.1':
+ dependencies:
+ '@bull-board/api': 6.10.1(@bull-board/ui@6.10.1)
'@clerk/backend@1.34.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
@@ -6588,6 +7388,8 @@ snapshots:
'@img/sharp-win32-x64@0.34.2':
optional: true
+ '@ioredis/commands@1.2.0': {}
+
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
@@ -6601,8 +7403,6 @@ snapshots:
dependencies:
minipass: 7.1.2
- '@istanbuljs/schema@0.1.3': {}
-
'@jridgewell/gen-mapping@0.3.8':
dependencies:
'@jridgewell/set-array': 1.2.1
@@ -6666,6 +7466,24 @@ snapshots:
'@msgpack/msgpack@2.8.0': {}
+ '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3':
+ optional: true
+
+ '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3':
+ optional: true
+
+ '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3':
+ optional: true
+
+ '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3':
+ optional: true
+
+ '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3':
+ optional: true
+
+ '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3':
+ optional: true
+
'@next/bundle-analyzer@15.3.3':
dependencies:
webpack-bundle-analyzer: 4.10.1
@@ -6965,9 +7783,6 @@ snapshots:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0)
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
'@playwright/test@1.52.0':
dependencies:
playwright: 1.52.0
@@ -6986,37 +7801,39 @@ snapshots:
'@radix-ui/primitive@1.1.2': {}
- '@radix-ui/react-accordion@1.2.11(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-accordion@1.2.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
- '@radix-ui/react-collapsible': 1.1.11(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-collection': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collapsible': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-arrow@1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-checkbox@1.3.2(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-checkbox@1.3.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.6)(react@19.1.0)
@@ -7024,32 +7841,35 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-collapsible@1.1.11(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-collapsible@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-collection@1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.6)(react@19.1.0)':
dependencies:
@@ -7063,18 +7883,18 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-dialog@1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-dialog@1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dismissable-layer': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-portal': 1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
aria-hidden: 1.2.6
@@ -7083,6 +7903,7 @@ snapshots:
react-remove-scroll: 2.7.0(@types/react@19.1.6)(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-direction@1.1.1(@types/react@19.1.6)(react@19.1.0)':
dependencies:
@@ -7090,31 +7911,33 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-dismissable-layer@1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-dropdown-menu@2.1.15(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-menu': 2.1.15(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-menu': 2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-focus-guards@1.1.2(@types/react@19.1.6)(react@19.1.0)':
dependencies:
@@ -7122,15 +7945,16 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-focus-scope@1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-icons@1.3.2(react@19.1.0)':
dependencies:
@@ -7143,30 +7967,31 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-label@2.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-label@2.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-menu@2.1.15(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-menu@2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
- '@radix-ui/react-collection': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dismissable-layer': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-popper': 1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-portal': 1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-roving-focus': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
aria-hidden: 1.2.6
@@ -7175,20 +8000,21 @@ snapshots:
react-remove-scroll: 2.7.0(@types/react@19.1.6)(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-popover@1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-popover@1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dismissable-layer': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-popper': 1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-portal': 1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
aria-hidden: 1.2.6
@@ -7197,14 +8023,15 @@ snapshots:
react-remove-scroll: 2.7.0(@types/react@19.1.6)(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-popper@1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-popper@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-arrow': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
@@ -7214,17 +8041,19 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-portal@1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-presence@1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
@@ -7232,48 +8061,52 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-primitive@2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-roving-focus@1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
- '@radix-ui/react-collection': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-separator@1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-slider@1.3.5(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-slider@1.3.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/number': 1.1.1
'@radix-ui/primitive': 1.1.2
- '@radix-ui/react-collection': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.6)(react@19.1.0)
@@ -7282,6 +8115,7 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-slot@1.2.3(@types/react@19.1.6)(react@19.1.0)':
dependencies:
@@ -7290,12 +8124,12 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-switch@1.2.5(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-switch@1.2.5(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.6)(react@19.1.0)
@@ -7303,59 +8137,63 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-tabs@1.1.12(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-tabs@1.1.12(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-roving-focus': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-toast@1.2.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-toast@1.2.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
- '@radix-ui/react-collection': 1.1.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dismissable-layer': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-portal': 1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-visually-hidden': 1.2.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
- '@radix-ui/react-tooltip@1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-tooltip@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@radix-ui/primitive': 1.1.2
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dismissable-layer': 1.1.10(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-popper': 1.2.7(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-portal': 1.1.9(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-presence': 1.1.4(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-popper': 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-visually-hidden': 1.2.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.6)(react@19.1.0)':
dependencies:
@@ -7411,17 +8249,18 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.6
- '@radix-ui/react-visually-hidden@1.2.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@radix-ui/rect@1.1.1': {}
- '@rolldown/pluginutils@1.0.0-beta.9': {}
+ '@rolldown/pluginutils@1.0.0-beta.11': {}
'@rollup/plugin-commonjs@28.0.1(rollup@4.35.0)':
dependencies:
@@ -7564,6 +8403,8 @@ snapshots:
'@schummar/icu-type-parser@1.21.5': {}
+ '@sec-ant/readable-stream@0.4.1': {}
+
'@sentry-internal/browser-utils@9.23.0':
dependencies:
'@sentry/core': 9.23.0
@@ -7746,6 +8587,8 @@ snapshots:
- encoding
- supports-color
+ '@sindresorhus/merge-streams@4.0.0': {}
+
'@standard-schema/utils@0.3.0': {}
'@swc/counter@0.1.3': {}
@@ -7876,7 +8719,7 @@ snapshots:
lodash: 4.17.21
redent: 3.0.0
- '@testing-library/react@16.3.0(@testing-library/dom@10.4.0)(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@testing-library/react@16.3.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.3
'@testing-library/dom': 10.4.0
@@ -7884,6 +8727,7 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@types/react': 19.1.6
+ '@types/react-dom': 19.1.6(@types/react@19.1.6)
'@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)':
dependencies:
@@ -7912,9 +8756,18 @@ snapshots:
dependencies:
'@babel/types': 7.27.3
+ '@types/body-parser@1.19.6':
+ dependencies:
+ '@types/connect': 3.4.38
+ '@types/node': 22.15.32
+
+ '@types/chai@5.2.2':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+
'@types/connect@3.4.38':
dependencies:
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
'@types/d3-array@3.2.1': {}
@@ -7944,6 +8797,8 @@ snapshots:
dependencies:
'@types/ms': 2.1.0
+ '@types/deep-eql@4.0.2': {}
+
'@types/eslint-scope@3.7.7':
dependencies:
'@types/eslint': 9.6.1
@@ -7964,10 +8819,25 @@ snapshots:
'@types/estree@1.0.8': {}
+ '@types/express-serve-static-core@5.0.6':
+ dependencies:
+ '@types/node': 22.15.32
+ '@types/qs': 6.14.0
+ '@types/range-parser': 1.2.7
+ '@types/send': 0.17.5
+
+ '@types/express@5.0.3':
+ dependencies:
+ '@types/body-parser': 1.19.6
+ '@types/express-serve-static-core': 5.0.6
+ '@types/serve-static': 1.15.8
+
'@types/hast@3.0.4':
dependencies:
'@types/unist': 3.0.3
+ '@types/http-errors@2.0.5': {}
+
'@types/js-cookie@2.2.7': {}
'@types/json-schema@7.0.15': {}
@@ -7975,19 +8845,29 @@ snapshots:
'@types/jsonwebtoken@9.0.10':
dependencies:
'@types/ms': 2.1.0
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3
+ '@types/mime@1.3.5': {}
+
'@types/minimist@1.2.5': {}
'@types/ms@2.1.0': {}
'@types/mysql@2.15.26':
dependencies:
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
+
+ '@types/node-ipc@9.2.3':
+ dependencies:
+ '@types/node': 22.15.32
+
+ '@types/node@20.19.1':
+ dependencies:
+ undici-types: 6.21.0
'@types/node@22.15.27':
dependencies:
@@ -8005,27 +8885,46 @@ snapshots:
'@types/pg@8.15.2':
dependencies:
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
pg-protocol: 1.10.0
pg-types: 4.0.2
'@types/pg@8.6.1':
dependencies:
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
pg-protocol: 1.10.0
pg-types: 2.2.0
+ '@types/qs@6.14.0': {}
+
+ '@types/range-parser@1.2.7': {}
+
+ '@types/react-dom@19.1.6(@types/react@19.1.6)':
+ dependencies:
+ '@types/react': 19.1.6
+
'@types/react@19.1.6':
dependencies:
csstype: 3.1.3
+ '@types/send@0.17.5':
+ dependencies:
+ '@types/mime': 1.3.5
+ '@types/node': 22.15.32
+
+ '@types/serve-static@1.15.8':
+ dependencies:
+ '@types/http-errors': 2.0.5
+ '@types/node': 22.15.32
+ '@types/send': 0.17.5
+
'@types/shimmer@1.2.0': {}
'@types/stack-trace@0.0.33': {}
'@types/tedious@4.0.14':
dependencies:
- '@types/node': 22.15.27
+ '@types/node': 22.15.32
'@types/unist@2.0.11': {}
@@ -8125,74 +9024,74 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
- '@vitejs/plugin-react@4.5.0(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
+ '@vitejs/plugin-react@4.5.2(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
- '@babel/core': 7.27.3
- '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.3)
- '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.3)
- '@rolldown/pluginutils': 1.0.0-beta.9
+ '@babel/core': 7.27.4
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.4)
+ '@rolldown/pluginutils': 1.0.0-beta.11
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-v8@3.1.4(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
+ '@vitest/expect@3.2.4':
dependencies:
- '@ampproject/remapping': 2.3.0
- '@bcoe/v8-coverage': 1.0.2
- debug: 4.4.1
- istanbul-lib-coverage: 3.2.2
- istanbul-lib-report: 3.0.1
- istanbul-lib-source-maps: 5.0.6
- istanbul-reports: 3.1.7
- magic-string: 0.30.17
- magicast: 0.3.5
- std-env: 3.9.0
- test-exclude: 7.0.1
- tinyrainbow: 2.0.0
- vitest: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
- transitivePeerDependencies:
- - supports-color
-
- '@vitest/expect@3.1.4':
- dependencies:
- '@vitest/spy': 3.1.4
- '@vitest/utils': 3.1.4
+ '@types/chai': 5.2.2
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
+ '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
- '@vitest/spy': 3.1.4
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.17
+ optionalDependencies:
+ vite: 6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+
+ '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
+ dependencies:
+ '@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
vite: 6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
- '@vitest/pretty-format@3.1.4':
+ '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.17
+ optionalDependencies:
+ vite: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+
+ '@vitest/pretty-format@3.2.4':
dependencies:
tinyrainbow: 2.0.0
- '@vitest/runner@3.1.4':
+ '@vitest/runner@3.2.4':
dependencies:
- '@vitest/utils': 3.1.4
+ '@vitest/utils': 3.2.4
pathe: 2.0.3
+ strip-literal: 3.0.0
- '@vitest/snapshot@3.1.4':
+ '@vitest/snapshot@3.2.4':
dependencies:
- '@vitest/pretty-format': 3.1.4
+ '@vitest/pretty-format': 3.2.4
magic-string: 0.30.17
pathe: 2.0.3
- '@vitest/spy@3.1.4':
+ '@vitest/spy@3.2.4':
dependencies:
- tinyspy: 3.0.2
+ tinyspy: 4.0.3
- '@vitest/utils@3.1.4':
+ '@vitest/utils@3.2.4':
dependencies:
- '@vitest/pretty-format': 3.1.4
- loupe: 3.1.3
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.1.4
tinyrainbow: 2.0.0
'@webassemblyjs/ast@1.14.1':
@@ -8281,6 +9180,11 @@ snapshots:
dependencies:
event-target-shim: 5.0.1
+ accepts@2.0.0:
+ dependencies:
+ mime-types: 3.0.1
+ negotiator: 1.0.0
+
acorn-import-attributes@1.9.5(acorn@8.15.0):
dependencies:
acorn: 8.15.0
@@ -8428,6 +9332,8 @@ snapshots:
async-function@1.0.0: {}
+ async@3.2.6: {}
+
atomic-sleep@1.0.0: {}
available-typed-arrays@1.0.7:
@@ -8442,6 +9348,20 @@ snapshots:
binary-extensions@2.3.0: {}
+ body-parser@2.2.0:
+ dependencies:
+ bytes: 3.1.2
+ content-type: 1.0.5
+ debug: 4.4.1
+ http-errors: 2.0.0
+ iconv-lite: 0.6.3
+ on-finished: 2.4.1
+ qs: 6.14.0
+ raw-body: 3.0.0
+ type-is: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
@@ -8471,10 +9391,24 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
+ bullmq@5.54.3:
+ dependencies:
+ cron-parser: 4.9.0
+ ioredis: 5.6.1
+ msgpackr: 1.11.4
+ node-abort-controller: 3.1.1
+ semver: 7.7.2
+ tslib: 2.8.1
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - supports-color
+
busboy@1.6.0:
dependencies:
streamsearch: 1.1.0
+ bytes@3.1.2: {}
+
cac@6.7.14: {}
call-bind-apply-helpers@1.0.2:
@@ -8571,14 +9505,28 @@ snapshots:
client-only@0.0.1: {}
+ cliui@7.0.4:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
clsx@2.1.1: {}
- cmdk@1.1.1(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ cluster-key-slot@1.1.2: {}
+
+ cmdk@1.1.1(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-dialog': 1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dialog': 1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
- '@radix-ui/react-primitive': 2.1.3(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
transitivePeerDependencies:
@@ -8619,14 +9567,50 @@ snapshots:
concat-map@0.0.1: {}
+ concurrently@9.1.2:
+ dependencies:
+ chalk: 4.1.2
+ lodash: 4.17.21
+ rxjs: 7.8.2
+ shell-quote: 1.8.3
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.7.2
+
+ content-disposition@1.0.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ content-type@1.0.5: {}
+
convert-source-map@2.0.0: {}
+ cookie-signature@1.2.2: {}
+
+ cookie@0.7.2: {}
+
cookie@1.0.2: {}
copy-to-clipboard@3.3.3:
dependencies:
toggle-selection: 1.0.6
+ copyfiles@2.4.1:
+ dependencies:
+ glob: 7.2.3
+ minimatch: 3.1.2
+ mkdirp: 1.0.4
+ noms: 0.0.0
+ through2: 2.0.5
+ untildify: 4.0.0
+ yargs: 16.2.0
+
+ core-util-is@1.0.3: {}
+
+ cron-parser@4.9.0:
+ dependencies:
+ luxon: 3.6.1
+
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
@@ -8753,6 +9737,10 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
+ denque@2.1.0: {}
+
+ depd@2.0.0: {}
+
dequal@2.0.3: {}
detect-libc@2.0.4: {}
@@ -8805,6 +9793,15 @@ snapshots:
pg: 8.15.6
postgres: 3.4.7
+ drizzle-orm@0.44.2(@electric-sql/pglite@0.3.0)(@libsql/client-wasm@0.15.5)(@opentelemetry/api@1.9.0)(@types/pg@8.15.2)(pg@8.15.6)(postgres@3.4.7):
+ optionalDependencies:
+ '@electric-sql/pglite': 0.3.0
+ '@libsql/client-wasm': 0.15.5
+ '@opentelemetry/api': 1.9.0
+ '@types/pg': 8.15.2
+ pg: 8.15.6
+ postgres: 3.4.7
+
drizzle-zod@0.7.1(drizzle-orm@0.43.1(@electric-sql/pglite@0.3.0)(@libsql/client-wasm@0.15.5)(@opentelemetry/api@1.9.0)(@types/pg@8.15.2)(pg@8.15.6)(postgres@3.4.7))(zod@3.25.41):
dependencies:
drizzle-orm: 0.43.1(@electric-sql/pglite@0.3.0)(@libsql/client-wasm@0.15.5)(@opentelemetry/api@1.9.0)(@types/pg@8.15.2)(pg@8.15.6)(postgres@3.4.7)
@@ -8820,6 +9817,8 @@ snapshots:
eastasianwidth@0.2.0: {}
+ easy-stack@1.0.1: {}
+
ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer: 5.2.1
@@ -8831,6 +9830,12 @@ snapshots:
'@noble/curves': 1.9.1
'@noble/hashes': 1.8.0
+ ee-first@1.1.1: {}
+
+ ejs@3.1.10:
+ dependencies:
+ jake: 10.9.2
+
electron-to-chromium@1.5.161: {}
emoji-regex@10.4.0: {}
@@ -8839,6 +9844,8 @@ snapshots:
emoji-regex@9.2.2: {}
+ encodeurl@2.0.0: {}
+
end-of-stream@1.4.4:
dependencies:
once: 1.4.0
@@ -9025,6 +10032,8 @@ snapshots:
escalade@3.2.0: {}
+ escape-html@1.0.3: {}
+
escape-string-regexp@4.0.0: {}
eslint-config-prettier@10.1.5(eslint@9.29.0(jiti@2.4.2)):
@@ -9145,10 +10154,17 @@ snapshots:
estree-walker@3.0.3:
dependencies:
- '@types/estree': 1.0.7
+ '@types/estree': 1.0.8
esutils@2.0.3: {}
+ etag@1.8.1: {}
+
+ event-pubsub@5.0.3:
+ dependencies:
+ copyfiles: 2.4.1
+ strong-type: 0.1.6
+
event-target-shim@5.0.1: {}
eventemitter3@4.0.7: {}
@@ -9169,8 +10185,55 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
+ execa@9.6.0:
+ dependencies:
+ '@sindresorhus/merge-streams': 4.0.0
+ cross-spawn: 7.0.6
+ figures: 6.1.0
+ get-stream: 9.0.1
+ human-signals: 8.0.1
+ is-plain-obj: 4.1.0
+ is-stream: 4.0.1
+ npm-run-path: 6.0.0
+ pretty-ms: 9.2.0
+ signal-exit: 4.1.0
+ strip-final-newline: 4.0.0
+ yoctocolors: 2.1.1
+
expect-type@1.2.1: {}
+ express@5.1.0:
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.2.0
+ content-disposition: 1.0.0
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.2.2
+ debug: 4.4.1
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 2.1.0
+ fresh: 2.0.0
+ http-errors: 2.0.0
+ merge-descriptors: 2.0.0
+ mime-types: 3.0.1
+ on-finished: 2.4.1
+ once: 1.4.0
+ parseurl: 1.3.3
+ proxy-addr: 2.0.7
+ qs: 6.14.0
+ range-parser: 1.2.1
+ router: 2.2.0
+ send: 1.2.0
+ serve-static: 2.2.0
+ statuses: 2.0.2
+ type-is: 2.0.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
extend@3.0.2: {}
fast-copy@3.0.2: {}
@@ -9217,14 +10280,33 @@ snapshots:
optionalDependencies:
picomatch: 4.0.2
+ figures@6.1.0:
+ dependencies:
+ is-unicode-supported: 2.1.0
+
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
+ filelist@1.0.4:
+ dependencies:
+ minimatch: 5.1.6
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
+ finalhandler@2.1.0:
+ dependencies:
+ debug: 4.4.1
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
@@ -9253,6 +10335,10 @@ snapshots:
forwarded-parse@2.1.2: {}
+ forwarded@0.2.0: {}
+
+ fresh@2.0.0: {}
+
fs.realpath@1.0.0: {}
fsevents@2.3.2:
@@ -9278,6 +10364,8 @@ snapshots:
gensync@1.0.0-beta.2: {}
+ get-caller-file@2.0.5: {}
+
get-east-asian-width@1.3.0: {}
get-intrinsic@1.3.0:
@@ -9302,6 +10390,11 @@ snapshots:
get-stream@6.0.1: {}
+ get-stream@9.0.1:
+ dependencies:
+ '@sec-ant/readable-stream': 0.4.1
+ is-stream: 4.0.1
+
get-symbol-description@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -9322,15 +10415,6 @@ snapshots:
glob-to-regexp@0.4.1: {}
- glob@10.4.5:
- dependencies:
- foreground-child: 3.3.1
- jackspeak: 3.4.3
- minimatch: 9.0.5
- minipass: 7.1.2
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
glob@11.0.2:
dependencies:
foreground-child: 3.3.1
@@ -9340,6 +10424,15 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 2.0.0
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
glob@9.3.5:
dependencies:
fs.realpath: 1.0.0
@@ -9438,6 +10531,14 @@ snapshots:
html-url-attributes@3.0.1: {}
+ http-errors@2.0.0:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.1
+ toidentifier: 1.0.1
+
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.3
@@ -9461,6 +10562,8 @@ snapshots:
human-signals@2.1.0: {}
+ human-signals@8.0.1: {}
+
husky@9.1.7: {}
hyphenate-style-name@1.1.0: {}
@@ -9491,6 +10594,13 @@ snapshots:
indent-string@4.0.0: {}
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
inline-style-parser@0.2.4: {}
inline-style-prefixer@7.0.1:
@@ -9512,6 +10622,22 @@ snapshots:
'@formatjs/icu-messageformat-parser': 2.11.2
tslib: 2.8.1
+ ioredis@5.6.1:
+ dependencies:
+ '@ioredis/commands': 1.2.0
+ cluster-key-slot: 1.1.2
+ debug: 4.4.1
+ denque: 2.1.0
+ lodash.defaults: 4.2.0
+ lodash.isarguments: 3.1.0
+ redis-errors: 1.2.0
+ redis-parser: 3.0.0
+ standard-as-callback: 2.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ ipaddr.js@1.9.1: {}
+
is-alphabetical@2.0.1: {}
is-alphanumerical@2.0.1:
@@ -9616,6 +10742,8 @@ snapshots:
is-potential-custom-element-name@1.0.1: {}
+ is-promise@4.0.0: {}
+
is-reference@1.2.1:
dependencies:
'@types/estree': 1.0.7
@@ -9635,6 +10763,8 @@ snapshots:
is-stream@2.0.1: {}
+ is-stream@4.0.1: {}
+
is-string@1.1.1:
dependencies:
call-bound: 1.0.4
@@ -9650,6 +10780,8 @@ snapshots:
dependencies:
which-typed-array: 1.1.19
+ is-unicode-supported@2.1.0: {}
+
is-weakmap@2.0.2: {}
is-weakref@1.1.1:
@@ -9661,33 +10793,16 @@ snapshots:
call-bound: 1.0.4
get-intrinsic: 1.3.0
+ isarray@0.0.1: {}
+
+ isarray@1.0.0: {}
+
isarray@2.0.5: {}
isexe@2.0.0: {}
isexe@3.1.1: {}
- istanbul-lib-coverage@3.2.2: {}
-
- istanbul-lib-report@3.0.1:
- dependencies:
- istanbul-lib-coverage: 3.2.2
- make-dir: 4.0.0
- supports-color: 7.2.0
-
- istanbul-lib-source-maps@5.0.6:
- dependencies:
- '@jridgewell/trace-mapping': 0.3.25
- debug: 4.4.1
- istanbul-lib-coverage: 3.2.2
- transitivePeerDependencies:
- - supports-color
-
- istanbul-reports@3.1.7:
- dependencies:
- html-escaper: 2.0.2
- istanbul-lib-report: 3.0.1
-
iterator.prototype@1.1.5:
dependencies:
define-data-property: 1.1.4
@@ -9697,16 +10812,17 @@ snapshots:
has-symbols: 1.1.0
set-function-name: 2.0.2
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
jackspeak@4.1.1:
dependencies:
'@isaacs/cliui': 8.0.2
+ jake@10.9.2:
+ dependencies:
+ async: 3.2.6
+ chalk: 4.1.2
+ filelist: 1.0.4
+ minimatch: 3.1.2
+
jest-worker@27.5.1:
dependencies:
'@types/node': 22.15.32
@@ -9724,8 +10840,16 @@ snapshots:
js-cookie@3.0.5: {}
+ js-message@1.0.7: {}
+
+ js-queue@2.0.2:
+ dependencies:
+ easy-stack: 1.0.1
+
js-tokens@4.0.0: {}
+ js-tokens@9.0.1: {}
+
js-yaml@4.1.0:
dependencies:
argparse: 2.0.1
@@ -9896,8 +11020,12 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ lodash.defaults@4.2.0: {}
+
lodash.includes@4.3.0: {}
+ lodash.isarguments@3.1.0: {}
+
lodash.isboolean@3.0.3: {}
lodash.isinteger@4.0.4: {}
@@ -9930,6 +11058,8 @@ snapshots:
loupe@3.1.3: {}
+ loupe@3.1.4: {}
+
lower-case@2.0.2:
dependencies:
tslib: 2.8.1
@@ -9950,6 +11080,8 @@ snapshots:
dependencies:
react: 19.1.0
+ luxon@3.6.1: {}
+
lz-string@1.5.0: {}
magic-string@0.30.17:
@@ -9960,16 +11092,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
- magicast@0.3.5:
- dependencies:
- '@babel/parser': 7.27.3
- '@babel/types': 7.27.3
- source-map-js: 1.2.1
-
- make-dir@4.0.0:
- dependencies:
- semver: 7.7.2
-
map-obj@1.0.1: {}
map-obj@4.3.0: {}
@@ -10067,6 +11189,8 @@ snapshots:
mdn-data@2.0.14: {}
+ media-typer@1.1.0: {}
+
meow@9.0.0:
dependencies:
'@types/minimist': 1.2.5
@@ -10082,6 +11206,8 @@ snapshots:
type-fest: 0.18.1
yargs-parser: 20.2.9
+ merge-descriptors@2.0.0: {}
+
merge-stream@2.0.0: {}
merge2@1.4.1: {}
@@ -10226,10 +11352,16 @@ snapshots:
mime-db@1.52.0: {}
+ mime-db@1.54.0: {}
+
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
+ mime-types@3.0.1:
+ dependencies:
+ mime-db: 1.54.0
+
mimic-fn@2.1.0: {}
mimic-function@5.0.1: {}
@@ -10244,6 +11376,10 @@ snapshots:
dependencies:
brace-expansion: 1.1.11
+ minimatch@5.1.6:
+ dependencies:
+ brace-expansion: 2.0.1
+
minimatch@8.0.4:
dependencies:
brace-expansion: 2.0.1
@@ -10268,6 +11404,8 @@ snapshots:
dependencies:
minipass: 7.1.2
+ mkdirp@1.0.4: {}
+
mkdirp@3.0.1: {}
module-details-from-path@1.0.4: {}
@@ -10276,6 +11414,22 @@ snapshots:
ms@2.1.3: {}
+ msgpackr-extract@3.0.3:
+ dependencies:
+ node-gyp-build-optional-packages: 5.2.2
+ optionalDependencies:
+ '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3
+ '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3
+ '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3
+ '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3
+ '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3
+ '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3
+ optional: true
+
+ msgpackr@1.11.4:
+ optionalDependencies:
+ msgpackr-extract: 3.0.3
+
nano-css@5.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
@@ -10354,12 +11508,31 @@ snapshots:
lower-case: 2.0.2
tslib: 2.8.1
+ node-abort-controller@3.1.1: {}
+
node-fetch@2.7.0:
dependencies:
whatwg-url: 5.0.0
+ node-gyp-build-optional-packages@5.2.2:
+ dependencies:
+ detect-libc: 2.0.4
+ optional: true
+
+ node-ipc@12.0.0:
+ dependencies:
+ event-pubsub: 5.0.3
+ js-message: 1.0.7
+ js-queue: 2.0.2
+ strong-type: 1.1.0
+
node-releases@2.0.19: {}
+ noms@0.0.0:
+ dependencies:
+ inherits: 2.0.4
+ readable-stream: 1.0.34
+
normalize-package-data@2.5.0:
dependencies:
hosted-git-info: 2.8.9
@@ -10380,6 +11553,11 @@ snapshots:
dependencies:
path-key: 3.1.1
+ npm-run-path@6.0.0:
+ dependencies:
+ path-key: 4.0.0
+ unicorn-magic: 0.3.0
+
nwsapi@2.2.20: {}
object-assign@4.1.1: {}
@@ -10424,6 +11602,10 @@ snapshots:
on-exit-leak-free@2.1.2: {}
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
once@1.4.0:
dependencies:
wrappy: 1.0.2
@@ -10469,8 +11651,14 @@ snapshots:
dependencies:
p-limit: 3.1.0
+ p-timeout@6.1.4: {}
+
p-try@2.2.0: {}
+ p-wait-for@5.0.2:
+ dependencies:
+ p-timeout: 6.1.4
+
package-json-from-dist@1.0.1: {}
parent-module@1.0.1:
@@ -10494,14 +11682,22 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
+ parse-ms@4.0.0: {}
+
parse5@7.3.0:
dependencies:
entities: 6.0.0
+ parseurl@1.3.3: {}
+
path-exists@4.0.0: {}
+ path-is-absolute@1.0.1: {}
+
path-key@3.1.1: {}
+ path-key@4.0.0: {}
+
path-parse@1.0.7: {}
path-scurry@1.11.1:
@@ -10514,6 +11710,8 @@ snapshots:
lru-cache: 11.1.0
minipass: 7.1.2
+ path-to-regexp@8.2.0: {}
+
pathe@2.0.3: {}
pathval@2.0.0: {}
@@ -10679,6 +11877,12 @@ snapshots:
ansi-styles: 5.2.0
react-is: 17.0.2
+ pretty-ms@9.2.0:
+ dependencies:
+ parse-ms: 4.0.0
+
+ process-nextick-args@2.0.1: {}
+
process-warning@5.0.0: {}
process@0.11.10: {}
@@ -10693,6 +11897,11 @@ snapshots:
property-information@7.1.0: {}
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.1
+
proxy-from-env@1.1.0: {}
pump@3.0.2:
@@ -10716,6 +11925,15 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
+ range-parser@1.2.1: {}
+
+ raw-body@3.0.0:
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.0
+ iconv-lite: 0.6.3
+ unpipe: 1.0.0
+
react-dom@19.1.0(react@19.1.0):
dependencies:
react: 19.1.0
@@ -10834,6 +12052,23 @@ snapshots:
parse-json: 5.2.0
type-fest: 0.6.0
+ readable-stream@1.0.34:
+ dependencies:
+ core-util-is: 1.0.3
+ inherits: 2.0.4
+ isarray: 0.0.1
+ string_decoder: 0.10.31
+
+ readable-stream@2.3.8:
+ dependencies:
+ core-util-is: 1.0.3
+ inherits: 2.0.4
+ isarray: 1.0.0
+ process-nextick-args: 2.0.1
+ safe-buffer: 5.1.2
+ string_decoder: 1.1.1
+ util-deprecate: 1.0.2
+
readable-stream@4.7.0:
dependencies:
abort-controller: 3.0.0
@@ -10870,6 +12105,16 @@ snapshots:
indent-string: 4.0.0
strip-indent: 3.0.0
+ redis-errors@1.2.0: {}
+
+ redis-info@3.1.0:
+ dependencies:
+ lodash: 4.17.21
+
+ redis-parser@3.0.0:
+ dependencies:
+ redis-errors: 1.2.0
+
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@@ -10907,6 +12152,8 @@ snapshots:
unified: 11.0.5
vfile: 6.0.3
+ require-directory@2.1.1: {}
+
require-from-string@2.0.2: {}
require-in-the-middle@7.5.2:
@@ -11006,6 +12253,16 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.41.1
fsevents: 2.3.3
+ router@2.2.0:
+ dependencies:
+ debug: 4.4.1
+ depd: 2.0.0
+ is-promise: 4.0.0
+ parseurl: 1.3.3
+ path-to-regexp: 8.2.0
+ transitivePeerDependencies:
+ - supports-color
+
rrweb-cssom@0.8.0: {}
rtl-css-js@1.16.1:
@@ -11016,6 +12273,10 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
+ rxjs@7.8.2:
+ dependencies:
+ tslib: 2.8.1
+
safe-array-concat@1.1.3:
dependencies:
call-bind: 1.0.8
@@ -11024,6 +12285,8 @@ snapshots:
has-symbols: 1.1.0
isarray: 2.0.5
+ safe-buffer@5.1.2: {}
+
safe-buffer@5.2.1: {}
safe-push-apply@1.0.0:
@@ -11064,6 +12327,22 @@ snapshots:
semver@7.7.2: {}
+ send@1.2.0:
+ dependencies:
+ debug: 4.4.1
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 2.0.0
+ http-errors: 2.0.0
+ mime-types: 3.0.1
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
serialize-error@8.1.0:
dependencies:
type-fest: 0.20.2
@@ -11072,6 +12351,15 @@ snapshots:
dependencies:
randombytes: 2.1.0
+ serve-static@2.2.0:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 1.2.0
+ transitivePeerDependencies:
+ - supports-color
+
server-only@0.0.1: {}
set-function-length@1.2.2:
@@ -11098,6 +12386,8 @@ snapshots:
es-errors: 1.3.0
es-object-atoms: 1.1.1
+ setprototypeof@1.2.0: {}
+
sharp@0.34.2:
dependencies:
color: 4.2.3
@@ -11133,6 +12423,8 @@ snapshots:
shebang-regex@3.0.0: {}
+ shell-quote@1.8.3: {}
+
shimmer@1.2.1: {}
side-channel-list@1.0.0:
@@ -11264,6 +12556,12 @@ snapshots:
dependencies:
type-fest: 0.7.1
+ standard-as-callback@2.1.0: {}
+
+ statuses@2.0.1: {}
+
+ statuses@2.0.2: {}
+
std-env@3.9.0: {}
stop-iteration-iterator@1.1.0:
@@ -11337,6 +12635,12 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
+ string_decoder@0.10.31: {}
+
+ string_decoder@1.1.1:
+ dependencies:
+ safe-buffer: 5.1.2
+
string_decoder@1.3.0:
dependencies:
safe-buffer: 5.2.1
@@ -11356,18 +12660,28 @@ snapshots:
strip-final-newline@2.0.0: {}
+ strip-final-newline@4.0.0: {}
+
strip-indent@3.0.0:
dependencies:
min-indent: 1.0.1
strip-json-comments@3.1.1: {}
+ strip-literal@3.0.0:
+ dependencies:
+ js-tokens: 9.0.1
+
stripe@18.2.0(@types/node@22.15.27):
dependencies:
qs: 6.14.0
optionalDependencies:
'@types/node': 22.15.27
+ strong-type@0.1.6: {}
+
+ strong-type@1.1.0: {}
+
style-to-js@1.1.16:
dependencies:
style-to-object: 1.0.8
@@ -11440,18 +12754,17 @@ snapshots:
commander: 2.20.3
source-map-support: 0.5.21
- test-exclude@7.0.1:
- dependencies:
- '@istanbuljs/schema': 0.1.3
- glob: 10.4.5
- minimatch: 9.0.5
-
thread-stream@3.1.0:
dependencies:
real-require: 0.2.0
throttle-debounce@3.0.1: {}
+ through2@2.0.5:
+ dependencies:
+ readable-stream: 2.3.8
+ xtend: 4.0.2
+
tiny-invariant@1.3.3: {}
tinybench@2.9.0: {}
@@ -11463,11 +12776,11 @@ snapshots:
fdir: 6.4.5(picomatch@4.0.2)
picomatch: 4.0.2
- tinypool@1.0.2: {}
+ tinypool@1.1.1: {}
tinyrainbow@2.0.0: {}
- tinyspy@3.0.2: {}
+ tinyspy@4.0.3: {}
tldts-core@6.1.86: {}
@@ -11481,6 +12794,8 @@ snapshots:
toggle-selection@1.0.6: {}
+ toidentifier@1.0.1: {}
+
totalist@3.0.1: {}
tough-cookie@5.1.2:
@@ -11493,6 +12808,8 @@ snapshots:
dependencies:
punycode: 2.3.1
+ tree-kill@1.2.2: {}
+
trim-lines@3.0.1: {}
trim-newlines@3.0.1: {}
@@ -11561,6 +12878,12 @@ snapshots:
type-fest@4.41.0: {}
+ type-is@2.0.1:
+ dependencies:
+ content-type: 1.0.5
+ media-typer: 1.1.0
+ mime-types: 3.0.1
+
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.4
@@ -11615,6 +12938,8 @@ snapshots:
undici-types@6.21.0: {}
+ unicorn-magic@0.3.0: {}
+
unified@11.0.5:
dependencies:
'@types/unist': 3.0.3
@@ -11648,6 +12973,8 @@ snapshots:
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
+ unpipe@1.0.0: {}
+
unplugin@1.0.1:
dependencies:
acorn: 8.15.0
@@ -11655,6 +12982,8 @@ snapshots:
webpack-sources: 3.3.0
webpack-virtual-modules: 0.5.0
+ untildify@4.0.0: {}
+
update-browserslist-db@1.1.3(browserslist@4.25.0):
dependencies:
browserslist: 4.25.0
@@ -11691,6 +13020,8 @@ snapshots:
dependencies:
react: 19.1.0
+ util-deprecate@1.0.2: {}
+
uuid@11.1.0: {}
uuid@9.0.1: {}
@@ -11700,9 +13031,11 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
- vaul@1.1.2(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ vary@1.1.2: {}
+
+ vaul@1.1.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
- '@radix-ui/react-dialog': 1.1.14(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@radix-ui/react-dialog': 1.1.14(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
transitivePeerDependencies:
@@ -11736,7 +13069,28 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
- vite-node@3.1.4(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ vite-node@3.2.4(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.1
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite-node@3.2.4(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
dependencies:
cac: 6.7.14
debug: 4.4.1
@@ -11757,6 +13111,27 @@ snapshots:
- tsx
- yaml
+ vite-node@3.2.4(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.1
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
dependencies:
debug: 4.4.1
@@ -11768,6 +13143,23 @@ snapshots:
- supports-color
- typescript
+ vite@6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ esbuild: 0.25.5
+ fdir: 6.4.5(picomatch@4.0.2)
+ picomatch: 4.0.2
+ postcss: 8.5.4
+ rollup: 4.41.1
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 20.19.1
+ fsevents: 2.3.3
+ jiti: 2.4.2
+ lightningcss: 1.30.1
+ terser: 5.43.1
+ tsx: 4.20.3
+ yaml: 2.8.0
+
vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
dependencies:
esbuild: 0.25.5
@@ -11785,28 +13177,90 @@ snapshots:
tsx: 4.20.3
yaml: 2.8.0
- vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
dependencies:
- '@vitest/expect': 3.1.4
- '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
- '@vitest/pretty-format': 3.1.4
- '@vitest/runner': 3.1.4
- '@vitest/snapshot': 3.1.4
- '@vitest/spy': 3.1.4
- '@vitest/utils': 3.1.4
+ esbuild: 0.25.5
+ fdir: 6.4.5(picomatch@4.0.2)
+ picomatch: 4.0.2
+ postcss: 8.5.4
+ rollup: 4.41.1
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 22.15.32
+ fsevents: 2.3.3
+ jiti: 2.4.2
+ lightningcss: 1.30.1
+ terser: 5.43.1
+ tsx: 4.20.3
+ yaml: 2.8.0
+
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.1)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
chai: 5.2.0
debug: 4.4.1
expect-type: 1.2.1
magic-string: 0.30.17
pathe: 2.0.3
+ picomatch: 4.0.2
std-env: 3.9.0
tinybench: 2.9.0
tinyexec: 0.3.2
tinyglobby: 0.2.14
- tinypool: 1.0.2
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 6.3.5(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ vite-node: 3.2.4(@types/node@20.19.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/debug': 4.1.12
+ '@types/node': 20.19.1
+ jsdom: 26.1.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.15.27)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.2.0
+ debug: 4.4.1
+ expect-type: 1.2.1
+ magic-string: 0.30.17
+ pathe: 2.0.3
+ picomatch: 4.0.2
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.14
+ tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 6.3.5(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
- vite-node: 3.1.4(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ vite-node: 3.2.4(@types/node@22.15.27)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
@@ -11826,6 +13280,49 @@ snapshots:
- tsx
- yaml
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.15.32)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.2.0
+ debug: 4.4.1
+ expect-type: 1.2.1
+ magic-string: 0.30.17
+ pathe: 2.0.3
+ picomatch: 4.0.2
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.14
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ vite-node: 3.2.4(@types/node@22.15.32)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/debug': 4.1.12
+ '@types/node': 22.15.32
+ jsdom: 26.1.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
@@ -11997,6 +13494,8 @@ snapshots:
xtend@4.0.2: {}
+ y18n@5.0.8: {}
+
yallist@3.1.1: {}
yallist@4.0.0: {}
@@ -12007,8 +13506,32 @@ snapshots:
yargs-parser@20.2.9: {}
+ yargs-parser@21.1.1: {}
+
+ yargs@16.2.0:
+ dependencies:
+ cliui: 7.0.4
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 20.2.9
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
yocto-queue@0.1.0: {}
+ yoctocolors@2.1.1: {}
+
zod@3.25.41: {}
zwitch@2.0.4: {}