diff --git a/.env b/.env index b7cbba89fec0b14c5003379ad2fdc1a58591cf94..bea0e89a20ec6666e263645063ab7a83769cf70f 100644 --- a/.env +++ b/.env @@ -1,79 +1,68 @@ # Use .env.local to change these variables # DO NOT EDIT THIS FILE WITH SENSITIVE DATA -### Config ### -ENABLE_CONFIG_MANAGER=true +### Models ### +# Models are sourced exclusively from an OpenAI-compatible base URL. +# Example: https://router.huggingface.co/v1 +OPENAI_BASE_URL= + +# Canonical auth token for any OpenAI-compatible provider +OPENAI_API_KEY=#your provider API key (works for HF router, OpenAI, LM Studio, etc.) +# Legacy alias (still supported): if set and OPENAI_API_KEY is empty, it will be used +# HF_TOKEN= ### MongoDB ### MONGODB_URL=#your mongodb URL here, use chat-ui-db image if you don't want to set this MONGODB_DB_NAME=chat-ui MONGODB_DIRECT_CONNECTION=false + +## Public app configuration ## +PUBLIC_APP_GUEST_MESSAGE=# a message to the guest user. If not set, no message will be shown. Only used if you have authentication enabled. +PUBLIC_APP_NAME=ChatUI # name used as title throughout the app +PUBLIC_APP_ASSETS=chatui # used to find logos & favicons in static/$PUBLIC_APP_ASSETS +PUBLIC_APP_DESCRIPTION=# description used throughout the app +PUBLIC_APP_DATA_SHARING=# Set to 1 to enable an option in the user settings to share conversations with model authors + ### Local Storage ### -MODELS_STORAGE_PATH= # where are .gguf for model inference stored MONGO_STORAGE_PATH= # where is the db folder stored -### Endpoints config ### -HF_API_ROOT=https://api-inference.huggingface.co/models -# HF_TOKEN is used for a lot of things, not only for inference but also fetching tokenizers, etc. -# We recommend using an HF_TOKEN even if you use a local endpoint. -HF_TOKEN= #get it from https://huggingface.co/settings/token -# API Keys for providers, you will need to specify models in the MODELS section but these keys can be kept secret -OPENAI_API_KEY=#your openai api key here -ANTHROPIC_API_KEY=#your anthropic api key here -CLOUDFLARE_ACCOUNT_ID=#your cloudflare account id here -CLOUDFLARE_API_TOKEN=#your cloudflare api token here -COHERE_API_TOKEN=#your cohere api token here -GOOGLE_GENAI_API_KEY=#your google genai api token here - +REASONING_SUMMARY=false # Change this to false to disable reasoning summary -### Models ### -## Models can support many different endpoints, check the documentation for more details -MODELS=`[ - { - "name": "NousResearch/Hermes-3-Llama-3.1-8B", - "description": "Nous Research's latest Hermes 3 release in 8B size.", - "promptExamples": [ - { - "title": "Write an email", - "prompt": "As a restaurant owner, write a professional email to the supplier to get these products every week: \n\n- Wine (x10)\n- Eggs (x24)\n- Bread (x12)" - }, { - "title": "Code a game", - "prompt": "Code a basic snake game in python, give explanations for each step." - }, { - "title": "Recipe help", - "prompt": "How do I make a delicious lemon cheesecake?" - } - ] - } -]` - -LOAD_GGUF_MODELS=true -## Text Embedding Models used for websearch -# Default is a model that runs locally on CPU. -TEXT_EMBEDDING_MODELS = `[ - { - "name": "Xenova/gte-small", - "displayName": "Xenova/gte-small", - "description": "Local embedding model running on the server.", - "chunkCharLength": 512, - "endpoints": [ - { "type": "transformersjs" } - ] - } -]` - - -REASONING_SUMMARY=true # Change this to false to disable reasoning summary -## Removed models, useful for migrating conversations -# { name: string, displayName?: string, id?: string, transferTo?: string }` -OLD_MODELS=`[]` +## Models overrides +MODELS= ## Task model -# name of the model used for tasks such as summarizing title, creating query, etc. -# if not set, the first model in MODELS will be used +# Optional: set to the model id/name from the `${OPENAI_BASE_URL}/models` list +# to use for internal tasks (title summarization, etc). If not set, the current model will be used TASK_MODEL= +# Arch router (OpenAI-compatible) endpoint base URL used for route selection +# Example: https://api.openai.com/v1 or your hosted Arch endpoint +LLM_ROUTER_ARCH_BASE_URL= + +## LLM Router Configuration +# Path to routes policy (JSON array). Defaults to llm-router/routes.chat.json +LLM_ROUTER_ROUTES_PATH= + +# Model used at the Arch router endpoint for selection +LLM_ROUTER_ARCH_MODEL= + +# Fallback behavior +# Route to map "other" to (must exist in routes file) +LLM_ROUTER_OTHER_ROUTE=casual_conversation +# Model to call if the Arch selection fails entirely +LLM_ROUTER_FALLBACK_MODEL= +# Arch selection timeout in milliseconds (default 10000) +LLM_ROUTER_ARCH_TIMEOUT_MS=10000 + +# Router UI overrides (client-visible) +# Public display name for the router entry in the model list. Defaults to "Omni". +PUBLIC_LLM_ROUTER_DISPLAY_NAME=Omni +# Optional: public logo URL for the router entry. If unset, the UI shows a Carbon icon. +PUBLIC_LLM_ROUTER_LOGO_URL= +# Public alias id used for the virtual router model (Omni). Defaults to "omni". +PUBLIC_LLM_ROUTER_ALIAS_ID=omni ### Authentication ### # Parameters to enable open id login @@ -97,41 +86,6 @@ TRUSTED_EMAIL_HEADER=# header to use to get the user email, only use if you know ADMIN_CLI_LOGIN=true # set to false to disable the CLI login ADMIN_TOKEN=#We recommend leaving this empty, you can get the token from the terminal. - -### Websearch ### -## API Keys used to activate search with web functionality. websearch is disabled if none are defined. choose one of the following: -YDC_API_KEY=#your docs.you.com api key here -SERPER_API_KEY=#your serper.dev api key here -SERPAPI_KEY=#your serpapi key here -SERPSTACK_API_KEY=#your serpstack api key here -SEARCHAPI_KEY=#your searchapi api key here -USE_LOCAL_WEBSEARCH=#set to true to parse google results yourself, overrides other API keys -SEARXNG_QUERY_URL=# where '' will be replaced with query keywords see https://docs.searxng.org/dev/search_api.html eg https://searxng.yourdomain.com/search?q=&engines=duckduckgo,google&format=json -BING_SUBSCRIPTION_KEY=#your key -## Websearch configuration -PLAYWRIGHT_ADBLOCKER=true -WEBSEARCH_ALLOWLIST=`[]` # if it's defined, allow websites from only this list. -WEBSEARCH_BLOCKLIST=`[]` # if it's defined, block websites from this list. -WEBSEARCH_JAVASCRIPT=true # CPU usage reduces by 60% on average by disabling javascript. Enable to improve website compatibility -WEBSEARCH_TIMEOUT = 3500 # in milliseconds, determines how long to wait to load a page before timing out -ENABLE_LOCAL_FETCH=false #set to true to allow fetches on the local network. /!\ Only enable this if you have the proper firewall rules to prevent SSRF attacks and understand the implications. - - -## Public app configuration ## -PUBLIC_APP_GUEST_MESSAGE=# a message to the guest user. If not set, no message will be shown. Only used if you have authentication enabled. -PUBLIC_APP_NAME=ChatUI # name used as title throughout the app -PUBLIC_APP_ASSETS=chatui # used to find logos & favicons in static/$PUBLIC_APP_ASSETS -PUBLIC_APP_DESCRIPTION=# description used throughout the app -PUBLIC_APP_DATA_SHARING=# Set to 1 to enable an option in the user settings to share conversations with model authors -PUBLIC_APP_DISCLAIMER=# Set to 1 to show a disclaimer on login page -PUBLIC_APP_DISCLAIMER_MESSAGE=# Message to show on the login page -PUBLIC_ANNOUNCEMENT_BANNERS=`[ - { - "title": "chat-ui is now open source!", - "linkTitle": "check it out", - "linkHref": "https://github.com/huggingface/chat-ui" - } -]` PUBLIC_SMOOTH_UPDATES=false # set to true to enable smoothing of messages client-side, can be CPU intensive PUBLIC_ORIGIN=#https://huggingface.co PUBLIC_SHARE_PREFIX=#https://hf.co/chat @@ -144,17 +98,10 @@ PUBLIC_APPLE_APP_ID=#1234567890 / Leave empty to disable ### Feature Flags ### LLM_SUMMARIZATION=true # generate conversation titles with LLMs -ENABLE_ASSISTANTS=false #set to true to enable assistants feature -ENABLE_ASSISTANTS_RAG=false # /!\ This will let users specify arbitrary URLs that the server will then request. Make sure you have the proper firewall rules in place. -REQUIRE_FEATURED_ASSISTANTS=false # require featured assistants to show in the list -COMMUNITY_TOOLS=false # set to true to enable community tools + ALLOW_IFRAME=true # Allow the app to be embedded in an iframe ENABLE_DATA_EXPORT=true -### Tools ### -# Check out public config in `chart/env/prod.yaml` for more details -TOOLS=`[]` - ### Rate limits ### # See `src/lib/server/usageLimits.ts` # { @@ -167,21 +114,15 @@ TOOLS=`[]` # } USAGE_LIMITS=`{}` - ### HuggingFace specific ### -# Let user authenticate with their HF token in the /api routes. This is only useful if you have OAuth configured with huggingface. -USE_HF_TOKEN_IN_API=false ## Feature flag & admin settings # Used for setting early access & admin flags to users HF_ORG_ADMIN= HF_ORG_EARLY_ACCESS= WEBHOOK_URL_REPORT_ASSISTANT=#provide slack webhook url to get notified for reports/feature requests -IP_TOKEN_SECRET= ### Metrics ### -METRICS_ENABLED=false -METRICS_PORT=5565 LOG_LEVEL=info @@ -191,19 +132,19 @@ PARQUET_EXPORT_DATASET= PARQUET_EXPORT_HF_TOKEN= ADMIN_API_SECRET=# secret to admin API calls, like computing usage stats or exporting parquet data +### Config ### +ENABLE_CONFIG_MANAGER=true ### Docker build variables ### # These values cannot be updated at runtime # They need to be passed when building the docker image # See https://github.com/huggingface/chat-ui/main/.github/workflows/deploy-prod.yml#L44-L47 APP_BASE="" # base path of the app, e.g. /chat, left blank as default -PUBLIC_APP_COLOR=blue # can be any of tailwind colors: https://tailwindcss.com/docs/customizing-colors#default-color-palette ### Body size limit for SvelteKit https://svelte.dev/docs/kit/adapter-node#Environment-variables-BODY_SIZE_LIMIT BODY_SIZE_LIMIT=15728640 PUBLIC_COMMIT_SHA= ### LEGACY parameters -HF_ACCESS_TOKEN=#LEGACY! Use HF_TOKEN instead ALLOW_INSECURE_COOKIES=false # LEGACY! Use COOKIE_SECURE and COOKIE_SAMESITE instead PARQUET_EXPORT_SECRET=#DEPRECATED, use ADMIN_API_SECRET instead RATE_LIMIT= # /!\ DEPRECATED definition of messages per minute. Use USAGE_LIMITS.messagesPerMinute instead diff --git a/Dockerfile b/Dockerfile index 4904dad8720794f40e2a86b43af4838c4e53af47..45112b7e86aa9bd7c53427ab3ba7cbac242e2fae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,6 @@ ARG INCLUDE_DB=false FROM node:20-slim AS base -ENV PLAYWRIGHT_SKIP_BROWSER_GC=1 # install dotenv-cli RUN npm install -g dotenv-cli @@ -21,7 +20,6 @@ WORKDIR /app RUN touch /app/.env.local -RUN npm i --no-package-lock --no-save playwright@1.52.0 USER root @@ -31,9 +29,9 @@ RUN chown -R 1000:1000 /data/models RUN apt-get update RUN apt-get install gnupg curl git cmake clang libgomp1 -y -RUN npx playwright install --with-deps chromium -RUN chown -R 1000:1000 /home/user/.npm +# ensure npm cache dir exists before adjusting ownership +RUN mkdir -p /home/user/.npm && chown -R 1000:1000 /home/user/.npm USER user diff --git a/PRIVACY.md b/PRIVACY.md index 587676d77e169bb9eeaa66688143e98d74acd889..1147feb6c8b906e626b1cfc60fe9027ec5b4a5c8 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,22 +1,38 @@ ## Privacy -> Last updated: Feb 14, 2025 +> Last updated: Sep 15, 2025 -Users of HuggingChat are authenticated through their HF user account. +Basics: -We endorse Privacy by Design. As such, your conversations are private to you and will not be shared with anyone, including model authors, for any purpose, including for research or model training purposes. - -You conversation data will only be stored to let you access past conversations. You can click on the Delete icon to delete any past conversation at any moment. +- Sign-in: You authenticate with your Hugging Face account. +- Conversation history: Stored so you can access past chats; you can delete any conversation at any time from the UI. 🗓 Please also consult huggingface.co's main privacy policy at . To exercise any of your legal privacy rights, please send an email to . +## Data handling and processing + +HuggingChat uses Hugging Face’s Inference Providers to access models from multiple partners via a single API. Depending on the model and availability, inference runs with the corresponding provider. + +- Inference Providers documentation: +- Security & Compliance: + +Security and routing facts + +- Hugging Face does not store any user data for training purposes. +- Hugging Face does not store the request body or the response when routing requests through Hugging Face. +- Logs are kept for debugging purposes for up to 30 days, but no user data or tokens are stored in those logs. +- Inference Provider routing uses TLS/SSL to encrypt data in transit. +- The Hugging Face Hub (which Inference Providers is a feature of) is SOC 2 Type 2 certified. See . + +External providers are responsible for their own security and data handling. Please consult each provider’s respective security and privacy policies via the Inference Providers documentation linked above. + ## About available LLMs The goal of this app is to showcase that it is now possible to build an open source alternative to ChatGPT. 💪 -We aim to always provide a diverse set of state of the art open LLMs, hence we rotate the available models over time. Discuss available models and request new ones on the [models discussion page](https://huggingface.co/spaces/huggingchat/chat-ui/discussions/372). +We aim to always provide a diverse set of state‑of‑the‑art open LLMs, and we may update the available models over time. Discuss models or request new ones on the [models discussion page](https://huggingface.co/spaces/huggingchat/chat-ui/discussions/372). -Check the [models](https://huggingface.co/chat/models/) page for an up-to-date list of the best available LLMs. +Check the [models](https://huggingface.co/chat/models/) page for an up‑to‑date list of the best available LLMs. ## Technical details @@ -26,10 +42,10 @@ The app is completely open source, and further development takes place on the [h You can find the production configuration for HuggingChat [here](https://github.com/huggingface/chat-ui/blob/main/chart/env/prod.yaml). -The inference backend is running the optimized [text-generation-inference](https://github.com/huggingface/text-generation-inference) on HuggingFace's Inference API infrastructure. +HuggingChat connects to the OpenAI‑compatible Inference Providers router at `https://router.huggingface.co/v1` to access models across multiple providers. Provider selection may be automatic or fixed depending on the model configuration. -It is possible to deploy a copy of this app to a Space and customize it (swap model, add some UI elements, or store user messages according to your own Terms and conditions). You can also 1-click deploy your own instance using the [Chat UI Spaces Docker template](https://huggingface.co/new-space?template=huggingchat/chat-ui-template). +It is possible to deploy a copy of this app to a Space and customize it (swap models, add UI elements, or store user messages according to your own Terms and Conditions). You can also 1‑click deploy your own instance using the [Chat UI Spaces Docker template](https://huggingface.co/new-space?template=huggingchat/chat-ui-template). -We welcome any feedback on this app: please participate to the public discussion at +We welcome any feedback on this app: please participate in the public discussion at diff --git a/README.md b/README.md index 89a8b9574690be8390b3e23f5896133ab0414e96..6e5f1104dc0f48539c352a9a92c7c4da7eb2a43b 100644 --- a/README.md +++ b/README.md @@ -1,236 +1,107 @@ # Chat UI -**Find the docs at [hf.co/docs/chat-ui](https://huggingface.co/docs/chat-ui/index).** - -![Chat UI repository thumbnail](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/chatui-websearch.png) +![Chat UI repository thumbnail](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/chat-ui/Frame%2013.png) A chat interface using open source models, eg OpenAssistant or Llama. It is a SvelteKit app and it powers the [HuggingChat app on hf.co/chat](https://huggingface.co/chat). 0. [Quickstart](#quickstart) -1. [No Setup Deploy](#no-setup-deploy) -2. [Setup](#setup) -3. [Launch](#launch) -4. [Web Search](#web-search) -5. [Text Embedding Models](#text-embedding-models) -6. [Extra parameters](#extra-parameters) -7. [Common issues](#common-issues) -8. [Deploying to a HF Space](#deploying-to-a-hf-space) -9. [Building](#building) - -## Quickstart - -### Docker image - -You can deploy a chat-ui instance in a single command using the docker image. Get your huggingface token from [here](https://huggingface.co/settings/tokens). - -```bash -docker run -p 3000 -e HF_TOKEN=hf_*** -v db:/data ghcr.io/huggingface/chat-ui-db:latest -``` - -Take a look at the [`.env` file](https://github.com/huggingface/chat-ui/blob/main/.env) and the readme to see all the environment variables that you can set. We have endpoint support for all OpenAI API compatible local services as well as many other providers like Anthropic, Cloudflare, Google Vertex AI, etc. +1. [Database Options](#database-options) +2. [Launch](#launch) +3. [Optional Docker Image](#optional-docker-image) +4. [Extra parameters](#extra-parameters) +5. [Building](#building) -### Local setup +> Note on models: Chat UI only supports OpenAI-compatible APIs via `OPENAI_BASE_URL` and the `/models` endpoint. Provider-specific integrations (legacy `MODELS` env var, GGUF discovery, embeddings, web-search helpers, etc.) are removed, but any service that speaks the OpenAI protocol—Hugging Face router, llama.cpp server, Ollama’s OpenAI bridge, OpenRouter, Anthropic-on-OpenRouter, etc.—will work. -You can quickly start a locally running chat-ui & LLM text-generation server thanks to chat-ui's [llama.cpp server support](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). - -**Step 1 (Start llama.cpp server):** - -Install llama.cpp w/ brew (for Mac): - -```bash -# install llama.cpp -brew install llama.cpp -``` - -or [build directly from the source](https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md) for your target device: +## Quickstart -``` -git clone https://github.com/ggerganov/llama.cpp && cd llama.cpp && make -``` +Chat UI speaks to OpenAI-compatible APIs only. The fastest way to get running is with the Hugging Face Inference Providers router plus your personal Hugging Face access token. -Next, start the server with the [LLM of your choice](https://huggingface.co/models?library=gguf): +**Step 1 – Create `.env.local`:** -```bash -# start llama.cpp server (using hf.co/microsoft/Phi-3-mini-4k-instruct-gguf as an example) -llama-server --hf-repo microsoft/Phi-3-mini-4k-instruct-gguf --hf-file Phi-3-mini-4k-instruct-q4.gguf -c 4096 +```env +OPENAI_BASE_URL=https://router.huggingface.co/v1 +OPENAI_API_KEY=hf_************************ +# Fill in once you pick a database option below +MONGODB_URL= ``` -A local LLaMA.cpp HTTP Server will start on `http://localhost:8080`. Read more [here](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). +`OPENAI_API_KEY` can come from any OpenAI-compatible endpoint you plan to call. Pick the combo that matches your setup and drop the values into `.env.local`: -**Step 3 (make sure you have MongoDb running locally):** +| Provider | Example `OPENAI_BASE_URL` | Example key env | +| --------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------- | +| Hugging Face Inference Providers router | `https://router.huggingface.co/v1` | `OPENAI_API_KEY=hf_xxx` (or `HF_TOKEN` legacy alias) | +| llama.cpp server (`llama.cpp --server --api`) | `http://127.0.0.1:8080/v1` | `OPENAI_API_KEY=sk-local-demo` (any string works; llama.cpp ignores it) | +| Ollama (with OpenAI-compatible bridge) | `http://127.0.0.1:11434/v1` | `OPENAI_API_KEY=ollama` | +| OpenRouter | `https://openrouter.ai/api/v1` | `OPENAI_API_KEY=sk-or-v1-...` | -```bash -docker run -d -p 27017:27017 --name mongo-chatui mongo:latest -``` +Check the root [`.env` template](./.env) for the full list of optional variables you can override. -Read more [here](#database). +**Step 2 – Choose where MongoDB lives:** Either provision a managed cluster (for example MongoDB Atlas) or run a local container. Both approaches are described in [Database Options](#database-options). After you have the URI, drop it into `MONGODB_URL` (and, if desired, set `MONGODB_DB_NAME`). -**Step 4 (clone chat-ui):** +**Step 3 – Install and launch the dev server:** ```bash git clone https://github.com/huggingface/chat-ui cd chat-ui -``` - -**Step 5 (tell chat-ui to use local llama.cpp server):** - -Add the following to your `.env.local`: - -```ini -MODELS=`[ - { - "name": "microsoft/Phi-3-mini-4k-instruct", - "endpoints": [{ - "type" : "llamacpp", - "baseURL": "http://localhost:8080" - }], - }, -]` -``` - -Read more [here](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). - -**Step 6 (start chat-ui):** - -```bash npm install npm run dev -- --open ``` -Read more [here](#launch). +You now have Chat UI running against the Hugging Face router without needing to host MongoDB yourself. - +## Database Options -## No Setup Deploy +Chat history, users, settings, files, and stats all live in MongoDB. You can point Chat UI at any MongoDB 6/7 deployment. -If you don't want to configure, setup, and launch your own Chat UI yourself, you can use this option as a fast deploy alternative. +### MongoDB Atlas (managed) -You can deploy your own customized Chat UI instance with any supported [LLM](https://huggingface.co/models?pipeline_tag=text-generation&sort=trending) of your choice on [Hugging Face Spaces](https://huggingface.co/spaces). To do so, use the chat-ui template [available here](https://huggingface.co/new-space?template=huggingchat/chat-ui-template). +1. Create a free cluster at [mongodb.com](https://www.mongodb.com/pricing). +2. Add your IP (or `0.0.0.0/0` for development) to the network access list. +3. Create a database user and copy the connection string. +4. Paste that string into `MONGODB_URL` in `.env.local`. Keep the default `MONGODB_DB_NAME=chat-ui` or change it per environment. -Set `HF_TOKEN` in [Space secrets](https://huggingface.co/docs/hub/spaces-overview#managing-secrets) to deploy a model with gated access or a model in a private repository. It's also compatible with [Inference for PROs](https://huggingface.co/blog/inference-pro) curated list of powerful models with higher rate limits. Make sure to create your personal token first in your [User Access Tokens settings](https://huggingface.co/settings/tokens). +Atlas keeps MongoDB off your laptop, which is ideal for teams or cloud deployments. -Read the full tutorial [here](https://huggingface.co/docs/hub/spaces-sdks-docker-chatui#chatui-on-spaces). +### Local MongoDB (container) -## Setup - -The default config for Chat UI is stored in the `.env` file. You will need to override some values to get Chat UI to run locally. This is done in `.env.local`. - -Start by creating a `.env.local` file in the root of the repository. The bare minimum config you need to get Chat UI to run locally is the following: - -```env -MONGODB_URL= -HF_TOKEN= -``` - -### Database - -The chat history is stored in a MongoDB instance, and having a DB instance available is needed for Chat UI to work. - -You can use a local MongoDB instance. The easiest way is to spin one up using docker: +If you prefer to run MongoDB locally: ```bash docker run -d -p 27017:27017 --name mongo-chatui mongo:latest ``` -In which case the url of your DB will be `MONGODB_URL=mongodb://localhost:27017`. - -Alternatively, you can use a [free MongoDB Atlas](https://www.mongodb.com/pricing) instance for this, Chat UI should fit comfortably within their free tier. After which you can set the `MONGODB_URL` variable in `.env.local` to match your instance. - -### Hugging Face Access Token - -If you use a remote inference endpoint, you will need a Hugging Face access token to run Chat UI locally. You can get one from [your Hugging Face profile](https://huggingface.co/settings/tokens). +Then set `MONGODB_URL=mongodb://localhost:27017` in `.env.local`. You can also supply `MONGO_STORAGE_PATH` if you want Chat UI’s fallback in-memory server to persist under a specific folder. ## Launch -After you're done with the `.env.local` file you can run Chat UI locally with: +After configuring your environment variables, start Chat UI with: ```bash npm install npm run dev ``` -## Web Search - -Chat UI features a powerful Web Search feature. It works by: - -1. Generating an appropriate search query from the user prompt. -2. Performing web search and extracting content from webpages. -3. Creating embeddings from texts using a text embedding model. -4. From these embeddings, find the ones that are closest to the user query using a vector similarity search. Specifically, we use `inner product` distance. -5. Get the corresponding texts to those closest embeddings and perform [Retrieval-Augmented Generation](https://huggingface.co/papers/2005.11401) (i.e. expand user prompt by adding those texts so that an LLM can use this information). +The dev server listens on `http://localhost:5173` by default. Use `npm run build` / `npm run preview` for production builds. -## Text Embedding Models +## Optional Docker Image -By default (for backward compatibility), when `TEXT_EMBEDDING_MODELS` environment variable is not defined, [transformers.js](https://huggingface.co/docs/transformers.js) embedding models will be used for embedding tasks, specifically, [Xenova/gte-small](https://huggingface.co/Xenova/gte-small) model. +Prefer containerized setup? You can run everything in one container as long as you supply a MongoDB URI (local or hosted): -You can customize the embedding model by setting `TEXT_EMBEDDING_MODELS` in your `.env.local` file. For example: - -```env -TEXT_EMBEDDING_MODELS = `[ - { - "name": "Xenova/gte-small", - "displayName": "Xenova/gte-small", - "description": "locally running embedding", - "chunkCharLength": 512, - "endpoints": [ - {"type": "transformersjs"} - ] - }, - { - "name": "intfloat/e5-base-v2", - "displayName": "intfloat/e5-base-v2", - "description": "hosted embedding model", - "chunkCharLength": 768, - "preQuery": "query: ", # See https://huggingface.co/intfloat/e5-base-v2#faq - "prePassage": "passage: ", # See https://huggingface.co/intfloat/e5-base-v2#faq - "endpoints": [ - { - "type": "tei", - "url": "http://127.0.0.1:8080/", - "authorization": "TOKEN_TYPE TOKEN" // optional authorization field. Example: "Basic VVNFUjpQQVNT" - } - ] - } -]` +```bash +docker run \ + -p 3000 \ + -e MONGODB_URL=mongodb://host.docker.internal:27017 \ + -e OPENAI_BASE_URL=https://router.huggingface.co/v1 \ + -e OPENAI_API_KEY=hf_*** \ + -v db:/data \ + ghcr.io/huggingface/chat-ui-db:latest ``` -The required fields are `name`, `chunkCharLength` and `endpoints`. -Supported text embedding backends are: [`transformers.js`](https://huggingface.co/docs/transformers.js), [`TEI`](https://github.com/huggingface/text-embeddings-inference) and [`OpenAI`](https://platform.openai.com/docs/guides/embeddings). `transformers.js` models run locally as part of `chat-ui`, whereas `TEI` models run in a different environment & accessed through an API endpoint. `openai` models are accessed through the [OpenAI API](https://platform.openai.com/docs/guides/embeddings). - -When more than one embedding models are supplied in `.env.local` file, the first will be used by default, and the others will only be used on LLM's which configured `embeddingModel` to the name of the model. +`host.docker.internal` lets the container reach a MongoDB instance on your host machine; swap it for your Atlas URI if you use the hosted option. All environment variables accepted in `.env.local` can be provided as `-e` flags. ## Extra parameters -### OpenID connect - -The login feature is disabled by default and users are attributed a unique ID based on their browser. But if you want to use OpenID to authenticate your users, you can add the following to your `.env.local` file: - -```env -OPENID_CONFIG=`{ - PROVIDER_URL: "", - CLIENT_ID: "", - CLIENT_SECRET: "", - SCOPES: "openid profile", - TOLERANCE: // optional - RESOURCE: // optional -}` -``` - -These variables will enable the openID sign-in modal for users. - -### Trusted header authentication - -You can set the env variable `TRUSTED_EMAIL_HEADER` to point to the header that contains the user's email address. This will allow you to authenticate users from the header. This setup is usually combined with a proxy that will be in front of chat-ui and will handle the auth and set the header. - -> [!WARNING] -> Make sure to only allow requests to chat-ui through your proxy which handles authentication, otherwise users could authenticate as anyone by setting the header manually! Only set this up if you understand the implications and know how to do it correctly. - -Here is a list of header names for common auth providers: - -- Tailscale Serve: `Tailscale-User-Login` -- Cloudflare Access: `Cf-Access-Authenticated-User-Email` -- oauth2-proxy: `X-Forwarded-Email` - ### Theming You can use a few environment variables to customize the look and feel of chat-ui. These are by default: @@ -241,785 +112,32 @@ PUBLIC_APP_ASSETS=chatui PUBLIC_APP_COLOR=blue PUBLIC_APP_DESCRIPTION="Making the community's best AI chat models available to everyone." PUBLIC_APP_DATA_SHARING= -PUBLIC_APP_DISCLAIMER= ``` - `PUBLIC_APP_NAME` The name used as a title throughout the app. - `PUBLIC_APP_ASSETS` Is used to find logos & favicons in `static/$PUBLIC_APP_ASSETS`, current options are `chatui` and `huggingchat`. - `PUBLIC_APP_COLOR` Can be any of the [tailwind colors](https://tailwindcss.com/docs/customizing-colors#default-color-palette). - `PUBLIC_APP_DATA_SHARING` Can be set to 1 to add a toggle in the user settings that lets your users opt-in to data sharing with models creator. -- `PUBLIC_APP_DISCLAIMER` If set to 1, we show a disclaimer about generated outputs on login. - -### Web Search config - -You can enable the web search through an API by adding `YDC_API_KEY` ([docs.you.com](https://docs.you.com)) or `SERPER_API_KEY` ([serper.dev](https://serper.dev/)) or `SERPAPI_KEY` ([serpapi.com](https://serpapi.com/)) or `SERPSTACK_API_KEY` ([serpstack.com](https://serpstack.com/)) or `SEARCHAPI_KEY` ([searchapi.io](https://www.searchapi.io/)) to your `.env.local`. - -You can also simply enable the local google websearch by setting `USE_LOCAL_WEBSEARCH=true` in your `.env.local` or specify a SearXNG instance by adding the query URL to `SEARXNG_QUERY_URL`. - -You can enable javascript when parsing webpages to improve compatibility with `WEBSEARCH_JAVASCRIPT=true` at the cost of increased CPU usage. You'll want at least 4 cores when enabling. - -### Custom models - -You can customize the parameters passed to the model or even use a new model by updating the `MODELS` variable in your `.env.local`. The default one can be found in `.env` and looks like this : - -```env -MODELS=`[ - { - "name": "mistralai/Mistral-7B-Instruct-v0.2", - "displayName": "mistralai/Mistral-7B-Instruct-v0.2", - "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.", - "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/", - "preprompt": "", - "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.3, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 3072, - "max_new_tokens": 1024, - "stop": [""] - }, - "promptExamples": [ - { - "title": "Write an email", - "prompt": "As a restaurant owner, write a professional email to the supplier to get these products every week: \n\n- Wine (x10)\n- Eggs (x24)\n- Bread (x12)" - }, { - "title": "Code a game", - "prompt": "Code a basic snake game in python, give explanations for each step." - }, { - "title": "Recipe help", - "prompt": "How do I make a delicious lemon cheesecake?" - } - ] - } -]` - -``` - -You can change things like the parameters, or customize the preprompt to better suit your needs. You can also add more models by adding more objects to the array, with different preprompts for example. - -#### chatPromptTemplate - -In 2025 most chat-completion endpoints (local or remotely hosted) support the OpenAI-compatible API and take arrays of messages. - -If not, when querying the model for a chat response, the `chatPromptTemplate` template is used. `messages` is an array of chat messages, it has the format `[{ content: string }, ...]`. To identify if a message is a user message or an assistant message the `ifUser` and `ifAssistant` block helpers can be used. - -The following is the default `chatPromptTemplate`, although newlines and indentiation have been added for readability. You can find the prompts used in production for HuggingChat [here](https://github.com/huggingface/chat-ui/blob/main/PROMPTS.md). - -```prompt -{{preprompt}} -{{#each messages}} - {{#ifUser}}{{@root.userMessageToken}}{{content}}{{@root.userMessageEndToken}}{{/ifUser}} - {{#ifAssistant}}{{@root.assistantMessageToken}}{{content}}{{@root.assistantMessageEndToken}}{{/ifAssistant}} -{{/each}} -{{assistantMessageToken}} -``` - -> [!INFO] -> We also support Jinja2 templates for the `chatPromptTemplate` in addition to Handlebars templates. On startup we first try to compile with Jinja and if that fails we fall back to interpreting `chatPromptTemplate` as handlebars. - -#### Multi modal model - -We currently support [IDEFICS](https://huggingface.co/blog/idefics) (hosted on TGI), OpenAI and Claude 3 as multimodal models. You can enable it by setting `multimodal: true` in your `MODELS` configuration. For IDEFICS, you must have a [PRO HF Api token](https://huggingface.co/settings/tokens). For OpenAI, see the [OpenAI section](#openai-api-compatible-models). For Anthropic, see the [Anthropic section](#anthropic). - -```env - { - "name": "HuggingFaceM4/idefics-80b-instruct", - "multimodal" : true, - "description": "IDEFICS is the new multimodal model by Hugging Face.", - "preprompt": "", - "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}User: {{content}}{{/ifUser}}\nAssistant: {{#ifAssistant}}{{content}}\n{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.1, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 12, - "truncate": 1000, - "max_new_tokens": 1024, - "stop": ["", "User:", "\nUser:"] - } - } -``` - -#### Running your own models using a custom endpoint - -If you want to, instead of hitting models on the Hugging Face Inference API, you can run your own models locally. - -A good option is to hit a [text-generation-inference](https://github.com/huggingface/text-generation-inference), or a llama.cpp endpoint. You will find an example for TGI in the official [Chat UI Spaces Docker template](https://huggingface.co/new-space?template=huggingchat/chat-ui-template) for instance: both this app and a text-generation-inference server run inside the same container. - -To do this, you can add your own endpoints to the `MODELS` variable in `.env.local`, by adding an `"endpoints"` key for each model in `MODELS`. - -```env -{ -// rest of the model config here -"endpoints": [{ - "type" : "tgi", - "url": "https://HOST:PORT", - }] -} -``` - -If `endpoints` are left unspecified, ChatUI will look for the model on the hosted Hugging Face inference API using the model name. - -##### OpenAI API compatible models - -Chat UI can be used with any API server that supports OpenAI API compatibility, for example [text-generation-webui](https://github.com/oobabooga/text-generation-webui/tree/main/extensions/openai), [LocalAI](https://github.com/go-skynet/LocalAI), [FastChat](https://github.com/lm-sys/FastChat/blob/main/docs/openai_api.md), [llama-cpp-python](https://github.com/abetlen/llama-cpp-python), and [ialacol](https://github.com/chenhunghan/ialacol) and [vllm](https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html). - -The following example config makes Chat UI works with [text-generation-webui](https://github.com/oobabooga/text-generation-webui/tree/main/extensions/openai), the `endpoint.baseUrl` is the url of the OpenAI API compatible server, this overrides the baseUrl to be used by OpenAI instance. The `endpoint.completion` determine which endpoint to be used, default is `chat_completions` which uses `v1/chat/completions`, change to `endpoint.completion` to `completions` to use the `v1/completions` endpoint. - -Parameters not supported by OpenAI (e.g., top_k, repetition_penalty, etc.) must be set in the extraBody of endpoints. Be aware that setting them in parameters will cause them to be omitted. - -``` -MODELS=`[ - { - "name": "text-generation-webui", - "id": "text-generation-webui", - "parameters": { - "temperature": 0.9, - "top_p": 0.95, - "max_new_tokens": 1024, - "stop": [] - }, - "endpoints": [{ - "type" : "openai", - "baseURL": "http://localhost:8000/v1", - "extraBody": { - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 1000 - } - }] - } -]` - -``` - -The `openai` type includes official OpenAI models. You can add, for example, GPT4/GPT3.5 as a "openai" model: - -``` -OPENAI_API_KEY=#your openai api key here -MODELS=`[{ - "name": "gpt-4", - "displayName": "GPT 4", - "endpoints" : [{ - "type": "openai" - }] -}, - { - "name": "gpt-3.5-turbo", - "displayName": "GPT 3.5 Turbo", - "endpoints" : [{ - "type": "openai" - }] -}]` -``` - -You may also consume any model provider that provides compatible OpenAI API endpoint. For example, you may self-host [Portkey](https://github.com/Portkey-AI/gateway) gateway and experiment with Claude or GPTs offered by Azure OpenAI. Example for Claude from Anthropic: - -``` -MODELS=`[{ - "name": "claude-2.1", - "displayName": "Claude 2.1", - "description": "Anthropic has been founded by former OpenAI researchers...", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://gateway.example.com/v1", - "defaultHeaders": { - "x-portkey-config": '{"provider":"anthropic","api_key":"sk-ant-abc...xyz"}' - } - } - ] -}]` -``` - -Example for GPT 4 deployed on Azure OpenAI: - -``` -MODELS=`[{ - "id": "gpt-4-1106-preview", - "name": "gpt-4-1106-preview", - "displayName": "gpt-4-1106-preview", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://{resource-name}.openai.azure.com/openai/deployments/{deployment-id}", - "defaultHeaders": { - "api-key": "{api-key}" - }, - "defaultQuery": { - "api-version": "2023-05-15" - } - } - ] -}]` -``` - -Or try Mistral from [Deepinfra](https://deepinfra.com/mistralai/Mistral-7B-Instruct-v0.1/api?example=openai-http): - -> Note, apiKey can either be set custom per endpoint, or globally using `OPENAI_API_KEY` variable. - -``` -MODELS=`[{ - "name": "mistral-7b", - "displayName": "Mistral 7B", - "description": "A 7B dense Transformer, fast-deployed and easily customisable. Small, yet powerful for a variety of use cases. Supports English and code, and a 8k context window.", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://api.deepinfra.com/v1/openai", - "apiKey": "abc...xyz" - } - ] -}]` -``` - -_Non-streaming endpoints_ - -For endpoints that don´t support streaming like o1 on Azure, you can pass `streamingSupported: false` in your endpoint config: - -``` -MODELS=`[{ - "id": "o1-preview", - "name": "o1-preview", - "displayName": "o1-preview", - "systemRoleSupported": false, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://my-deployment.openai.azure.com/openai/deployments/o1-preview", - "defaultHeaders": { - "api-key": "$SECRET" - }, - "streamingSupported": false, - } - ] -}]` -``` - -##### Llama.cpp API server - -chat-ui also supports the llama.cpp API server directly without the need for an adapter. You can do this using the `llamacpp` endpoint type. - -If you want to run Chat UI with llama.cpp, you can do the following, using [microsoft/Phi-3-mini-4k-instruct-gguf](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf) as an example model: - -```bash -# install llama.cpp -brew install llama.cpp -# start llama.cpp server -llama-server --hf-repo microsoft/Phi-3-mini-4k-instruct-gguf --hf-file Phi-3-mini-4k-instruct-q4.gguf -c 4096 -``` - -```env -MODELS=`[ - { - "name": "Local Zephyr", - "chatPromptTemplate": "<|system|>\n{{preprompt}}\n{{#each messages}}{{#ifUser}}<|user|>\n{{content}}\n<|assistant|>\n{{/ifUser}}{{#ifAssistant}}{{content}}\n{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.1, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 1000, - "max_new_tokens": 2048, - "stop": [""] - }, - "endpoints": [ - { - "url": "http://127.0.0.1:8080", - "type": "llamacpp" - } - ] - } -]` -``` - -Start chat-ui with `npm run dev` and you should be able to chat with Zephyr locally. - -#### Ollama - -We also support the Ollama inference server. Spin up a model with - -```cli -ollama run mistral -``` - -Then specify the endpoints like so: - -```env -MODELS=`[ - { - "name": "Ollama Mistral", - "chatPromptTemplate": "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}} {{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}} {{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.1, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 3072, - "max_new_tokens": 1024, - "stop": [""] - }, - "endpoints": [ - { - "type": "ollama", - "url" : "http://127.0.0.1:11434", - "ollamaName" : "mistral" - } - ] - } -]` -``` - -#### Anthropic - -We also support Anthropic models (including multimodal ones via `multmodal: true`) through the official SDK. You may provide your API key via the `ANTHROPIC_API_KEY` env variable, or alternatively, through the `endpoints.apiKey` as per the following example. -``` -MODELS=`[ - { - "name": "claude-3-haiku-20240307", - "displayName": "Claude 3 Haiku", - "description": "Fastest and most compact model for near-instant responsiveness", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-sonnet-20240229", - "displayName": "Claude 3 Sonnet", - "description": "Ideal balance of intelligence and speed", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-opus-20240229", - "displayName": "Claude 3 Opus", - "description": "Most powerful model for highly complex tasks", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096 - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - } -]` -``` - -We also support using Anthropic models running on Vertex AI. Authentication is done using Google Application Default Credentials. Project ID can be provided through the `endpoints.projectId` as per the following example: - -``` -MODELS=`[ - { - "name": "claude-3-sonnet@20240229", - "displayName": "Claude 3 Sonnet", - "description": "Ideal balance of intelligence and speed", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic-vertex", - "region": "us-central1", - "projectId": "gcp-project-id", - // optionals - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-haiku@20240307", - "displayName": "Claude 3 Haiku", - "description": "Fastest, most compact model for near-instant responsiveness", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096 - }, - "endpoints": [ - { - "type": "anthropic-vertex", - "region": "us-central1", - "projectId": "gcp-project-id", - // optionals - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - } -]` -``` - -#### Amazon - -You can also specify your Amazon SageMaker instance as an endpoint for chat-ui. The config goes like this: - -```env -"endpoints": [ - { - "type" : "aws", - "service" : "sagemaker" - "url": "", - "accessKey": "", - "secretKey" : "", - "sessionToken": "", - "region": "", - - "weight": 1 - } -] -``` - -You can also set `"service" : "lambda"` to use a lambda instance. - -You can get the `accessKey` and `secretKey` from your AWS user, under programmatic access. - -#### Cloudflare Workers AI - -You can also use Cloudflare Workers AI to run your own models with serverless inference. - -You will need to have a Cloudflare account, then get your [account ID](https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/) as well as your [API token](https://developers.cloudflare.com/workers-ai/get-started/rest-api/#1-get-api-token-and-account-id) for Workers AI. - -You can either specify them directly in your `.env.local` using the `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` variables, or you can set them directly in the endpoint config. +### Models -You can find the list of models available on Cloudflare [here](https://developers.cloudflare.com/workers-ai/models/#text-generation). +This build does not use the `MODELS` env var or GGUF discovery. Configure models via `OPENAI_BASE_URL` only; Chat UI will fetch `${OPENAI_BASE_URL}/models` and populate the list automatically. Authorization uses `OPENAI_API_KEY` (preferred). `HF_TOKEN` remains a legacy alias. -```env - { - "name" : "nousresearch/hermes-2-pro-mistral-7b", - "tokenizer": "nousresearch/hermes-2-pro-mistral-7b", - "parameters": { - "stop": ["<|im_end|>"] - }, - "endpoints" : [ - { - "type" : "cloudflare" - - } - ] -} -``` - -#### Cohere - -You can also use Cohere to run their models directly from chat-ui. You will need to have a Cohere account, then get your [API token](https://dashboard.cohere.com/api-keys). You can either specify it directly in your `.env.local` using the `COHERE_API_TOKEN` variable, or you can set it in the endpoint config. - -Here is an example of a Cohere model config. You can set which model you want to use by setting the `id` field to the model name. - -```env - { - "name" : "CohereForAI/c4ai-command-r-v01", - "id": "command-r", - "description": "C4AI Command-R is a research release of a 35 billion parameter highly performant generative model", - "endpoints": [ - { - "type": "cohere", - - } - ] - } -``` - -##### Google Vertex models +### LLM Router (Optional) -Chat UI can connect to the google Vertex API endpoints ([List of supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)). +Chat UI can perform client-side routing using an Arch Router model without running a separate router service. The UI exposes a virtual model alias called "Omni" (configurable) that, when selected, chooses the best route/model for each message. -To enable: +- Provide a routes policy JSON via `LLM_ROUTER_ROUTES_PATH`. No sample file ships with this branch, so you must point the variable to a JSON array you create yourself (for example, commit one in your project like `config/routes.chat.json`). Each route entry needs `name`, `description`, `primary_model`, and optional `fallback_models`. +- Configure the Arch router selection endpoint with `LLM_ROUTER_ARCH_BASE_URL` (OpenAI-compatible `/chat/completions`) and `LLM_ROUTER_ARCH_MODEL` (e.g. `router/omni`). The Arch call reuses `OPENAI_API_KEY` for auth. +- Map `other` to a concrete route via `LLM_ROUTER_OTHER_ROUTE` (default: `casual_conversation`). If Arch selection fails, calls fall back to `LLM_ROUTER_FALLBACK_MODEL`. +- Selection timeout can be tuned via `LLM_ROUTER_ARCH_TIMEOUT_MS` (default 10000). +- Omni alias configuration: `PUBLIC_LLM_ROUTER_ALIAS_ID` (default `omni`), `PUBLIC_LLM_ROUTER_DISPLAY_NAME` (default `Omni`), and optional `PUBLIC_LLM_ROUTER_LOGO_URL`. -1. [Select](https://console.cloud.google.com/project) or [create](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project) a Google Cloud project. -1. [Enable billing for your project](https://cloud.google.com/billing/docs/how-to/modify-project). -1. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com). -1. [Set up authentication with a service account](https://cloud.google.com/docs/authentication/getting-started) - so you can access the API from your local workstation. +When you select Omni in the UI, Chat UI will: -The service account credentials file can be imported as an environmental variable: - -```env - GOOGLE_APPLICATION_CREDENTIALS = clientid.json -``` - -Make sure your docker container has access to the file and the variable is correctly set. -Afterwards Google Vertex endpoints can be configured as following: - -``` -MODELS=`[ -//... - { - "name": "gemini-1.5-pro", - "displayName": "Vertex Gemini Pro 1.5", - "multimodal": true, - "endpoints" : [{ - "type": "vertex", - "project": "abc-xyz", - "location": "europe-west3", - "extraBody": { - "model_version": "gemini-1.5-pro-preview-0409", - }, - - // Optional - "safetyThreshold": "BLOCK_MEDIUM_AND_ABOVE", - "apiEndpoint": "", // alternative api endpoint url, - "tools": [{ - "googleSearchRetrieval": { - "disableAttribution": true - } - }], - "multimodal": { - "image": { - "supportedMimeTypes": ["image/png", "image/jpeg", "image/webp"], - "preferredMimeType": "image/png", - "maxSizeInMB": 5, - "maxWidth": 2000, - "maxHeight": 1000, - } - } - }] - }, -]` - -``` - -##### LangServe - -LangChain applications that are deployed using LangServe can be called with the following config: - -``` -MODELS=`[ -//... - { - "name": "summarization-chain", //model-name - "endpoints" : [{ - "type": "langserve", - "url" : "http://127.0.0.1:8100", - }] - }, -]` - -``` - -### Model Context Protocol (MCP) Support (Upcoming) - -The project is planning to introduce support for the Model Context Protocol (MCP). MCP is a specification designed to standardize how language models receive and understand context from various sources. This will enable more flexible and powerful integrations, allowing models to seamlessly access and utilize a broader range of information, such as user history, external documents, or real-time data, in a structured way. - -This is an upcoming feature, and we believe it will significantly enhance the capabilities and extensibility of Chat UI. - -We are actively seeking contributions from the community to help design, implement, and integrate MCP support into Chat UI. If you are interested in shaping the future of how Chat UI handles model context and want to contribute to this exciting development, please look for issues tagged with 'MCP' or 'Model Context Protocol' on our issue tracker. Your expertise and input would be invaluable! - -### Custom endpoint authorization - -#### Basic and Bearer - -Custom endpoints may require authorization, depending on how you configure them. Authentication will usually be set either with `Basic` or `Bearer`. - -For `Basic` we will need to generate a base64 encoding of the username and password. - -`echo -n "USER:PASS" | base64` - -> VVNFUjpQQVNT - -For `Bearer` you can use a token, which can be grabbed from [here](https://huggingface.co/settings/tokens). - -You can then add the generated information and the `authorization` parameter to your `.env.local`. - -```env -"endpoints": [ - { - "url": "https://HOST:PORT", - "authorization": "Basic VVNFUjpQQVNT", - } -] -``` - -Please note that if `HF_TOKEN` is also set or not empty, it will take precedence. - -#### Models hosted on multiple custom endpoints - -If the model being hosted will be available on multiple servers/instances add the `weight` parameter to your `.env.local`. The `weight` will be used to determine the probability of requesting a particular endpoint. - -```env -"endpoints": [ - { - "url": "https://HOST:PORT", - "weight": 1 - }, - { - "url": "https://HOST:PORT", - "weight": 2 - } - ... -] -``` - -#### Client Certificate Authentication (mTLS) - -Custom endpoints may require client certificate authentication, depending on how you configure them. To enable mTLS between Chat UI and your custom endpoint, you will need to set the `USE_CLIENT_CERTIFICATE` to `true`, and add the `CERT_PATH` and `KEY_PATH` parameters to your `.env.local`. These parameters should point to the location of the certificate and key files on your local machine. The certificate and key files should be in PEM format. The key file can be encrypted with a passphrase, in which case you will also need to add the `CLIENT_KEY_PASSWORD` parameter to your `.env.local`. - -If you're using a certificate signed by a private CA, you will also need to add the `CA_PATH` parameter to your `.env.local`. This parameter should point to the location of the CA certificate file on your local machine. - -If you're using a self-signed certificate, e.g. for testing or development purposes, you can set the `REJECT_UNAUTHORIZED` parameter to `false` in your `.env.local`. This will disable certificate validation, and allow Chat UI to connect to your custom endpoint. - -#### Specific Embedding Model - -A model can use any of the embedding models defined in `.env.local`, (currently used when web searching), -by default it will use the first embedding model, but it can be changed with the field `embeddingModel`: - -```env -TEXT_EMBEDDING_MODELS = `[ - { - "name": "Xenova/gte-small", - "chunkCharLength": 512, - "endpoints": [ - {"type": "transformersjs"} - ] - }, - { - "name": "intfloat/e5-base-v2", - "chunkCharLength": 768, - "endpoints": [ - {"type": "tei", "url": "http://127.0.0.1:8080/", "authorization": "Basic VVNFUjpQQVNT"}, - {"type": "tei", "url": "http://127.0.0.1:8081/"} - ] - } -]` - -MODELS=`[ - { - "name": "Ollama Mistral", - "chatPromptTemplate": "...", - "embeddingModel": "intfloat/e5-base-v2" - "parameters": { - ... - }, - "endpoints": [ - ... - ] - } -]` - -``` - -### Reasoning Models - -ChatUI supports specialized reasoning/Chain-of-Thought (CoT) models through the `reasoning` configuration field. When properly configured, this displays a UI widget that allows users to view or collapse the model’s reasoning steps. We support three types of reasoning parsing: - -#### Token-Based Delimitations - -For models like DeepSeek R1, token-based delimitations can be used to identify reasoning steps. This is done by specifying the `beginToken` and `endToken` fields in the `reasoning` configuration. - -Example configuration for DeepSeek R1 (token-based): - -```json -{ - "name": "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B", - // ... - "reasoning": { - "type": "tokens", - "beginToken": "", - "endToken": "" - } -} -``` - -#### Summarizing the Chain of Thought - -For models like QwQ, which return a chain of thought but do not explicitly provide a final answer, the `summarize` type can be used. This automatically summarizes the reasoning steps using the `TASK_MODEL` (or the first model in the configuration if `TASK_MODEL` is not specified) and displays the summary as the final answer. - -Example configuration for QwQ (summarize-based): - -```json -{ - "name": "Qwen/QwQ-32B-Preview", - // ... - "reasoning": { - "type": "summarize" - } -} -``` - -#### Regex-Based Delimitations - -In some cases, the final answer can be extracted from the model output using a regular expression. This is achieved by specifying the `regex` field in the `reasoning` configuration. For example, if your model wraps the final answer in a `\boxed{}` tag, you can use the following configuration: - -```json -{ - "name": "model/yourmodel", - // ... - "reasoning": { - "type": "regex", - "regex": "\\\\boxed\\{(.+?)\\}" - } -} -``` - -#### Enabling/Disabling Reasoning Summary - -You can toggle the summaries that are displayed alongside the CoT by changing the `REASONING_SUMMARY` env variable. - -```env -REASONING_SUMMARY=false -``` - -## Common issues - -### 403:You don't have access to this conversation - -Most likely you are running chat-ui over HTTP. The recommended option is to setup something like NGINX to handle HTTPS and proxy the requests to chat-ui. If you really need to run over HTTP you can add `COOKIE_SECURE=false` and `COOKIE_SAMESITE=lax` to your `.env.local`. - -Make sure to set your `PUBLIC_ORIGIN` in your `.env.local` to the correct URL as well. - -## Deploying to a HF Space - -Create a `DOTENV_LOCAL` secret to your HF space with the content of your .env.local, and they will be picked up automatically when you run. +- Call the Arch endpoint once (non-streaming) to pick the best route for the last turns. +- Emit RouterMetadata immediately (route and actual model used) so the UI can display it. +- Stream from the selected model via your configured `OPENAI_BASE_URL`. On errors, it tries route fallbacks. ## Building @@ -1032,89 +150,3 @@ npm run build You can preview the production build with `npm run preview`. > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. - -## Config changes for HuggingChat - -The config file for HuggingChat is stored in the `chart/env/prod.yaml` file. It is the source of truth for the environment variables used for our CI/CD pipeline. For HuggingChat, as we need to customize the app color, as well as the base path, we build a custom docker image. You can find the workflow here. - -> [!TIP] -> If you want to make changes to the model config used in production for HuggingChat, you should do so against `chart/env/prod.yaml`. - -### Running a copy of HuggingChat locally - -If you want to run an exact copy of HuggingChat locally, you will need to do the following first: - -1. Create an [OAuth App on the hub](https://huggingface.co/settings/applications/new) with `openid profile email` permissions. Make sure to set the callback URL to something like `http://localhost:5173/chat/login/callback` which matches the right path for your local instance. -2. Create a [HF Token](https://huggingface.co/settings/tokens) with your Hugging Face account. You will need a Pro account to be able to access some of the larger models available through HuggingChat. -3. Create a free account with [serper.dev](https://serper.dev/) (you will get 2500 free search queries) -4. Run an instance of mongoDB, however you want. (Local or remote) - -You can then create a new `.env.SECRET_CONFIG` file with the following content - -```env -MONGODB_URL= -HF_TOKEN= -OPENID_CONFIG=`{ - PROVIDER_URL: "https://huggingface.co", - CLIENT_ID: "", - CLIENT_SECRET: "", -}` -SERPER_API_KEY= -MESSAGES_BEFORE_LOGIN= -``` - -You can then run `npm run updateLocalEnv` in the root of chat-ui. This will create a `.env.local` file which combines the `chart/env/prod.yaml` and the `.env.SECRET_CONFIG` file. You can then run `npm run dev` to start your local instance of HuggingChat. - -### Populate database - -> [!WARNING] -> The `MONGODB_URL` used for this script will be fetched from `.env.local`. Make sure it's correct! The command runs directly on the database. - -You can populate the database using faker data using the `populate` script: - -```bash -npm run populate -``` - -At least one flag must be specified, the following flags are available: - -- `reset` - resets the database -- `all` - populates all tables -- `users` - populates the users table -- `settings` - populates the settings table for existing users -- `assistants` - populates the assistants table for existing users -- `conversations` - populates the conversations table for existing users - -For example, you could use it like so: - -```bash -npm run populate reset -``` - -to clear out the database. Then login in the app to create your user and run the following command: - -```bash -npm run populate users settings assistants conversations -``` - -to populate the database with fake data, including fake conversations and assistants for your user. - -## Building the docker images locally - -You can build the docker images locally using the following commands: - -```bash -docker build -t chat-ui-db:latest --build-arg INCLUDE_DB=true . -docker build -t chat-ui:latest --build-arg INCLUDE_DB=false . -docker build -t huggingchat:latest --build-arg INCLUDE_DB=false --build-arg APP_BASE=/chat --build-arg PUBLIC_APP_COLOR=yellow --build-arg SKIP_LLAMA_CPP_BUILD=true . -``` - -If you want to run the images with your local .env.local you have two options - -```bash -DOTENV_LOCAL=$(<.env.local) docker run --network=host -e DOTENV_LOCAL chat-ui-db -``` - -```bash -docker run --network=host --mount type=bind,source="$(pwd)/.env.local",target=/app/.env.local chat-ui-db -``` diff --git a/chart/env/prod.yaml b/chart/env/prod.yaml index 2260cc95ebbaf52da404f74da503ddbddd288bff..cc2ccec72c3df52db3c2a06d6d99452338ae54b3 100644 --- a/chart/env/prod.yaml +++ b/chart/env/prod.yaml @@ -51,11 +51,8 @@ envVars: COOKIE_SAMESITE: "lax" COOKIE_SECURE: "true" ENABLE_ASSISTANTS: "true" - ENABLE_ASSISTANTS_RAG: "true" ENABLE_CONFIG_MANAGER: "false" - METRICS_PORT: 5565 LOG_LEVEL: "debug" - METRICS_ENABLED: "true" MODELS: > [ { @@ -542,10 +539,8 @@ envVars: PUBLIC_APP_ASSETS: "huggingchat" PUBLIC_APP_COLOR: "yellow" PUBLIC_APP_DESCRIPTION: "Making the community's best AI chat models available to everyone." - PUBLIC_APP_DISCLAIMER_MESSAGE: "Disclaimer: AI is an area of active research with known problems such as biased generation and misinformation. Do not use this application for high-stakes decisions or advice." PUBLIC_APP_GUEST_MESSAGE: "Sign in with a free Hugging Face account to continue using HuggingChat." PUBLIC_APP_DATA_SHARING: 0 - PUBLIC_APP_DISCLAIMER: 1 PUBLIC_PLAUSIBLE_SCRIPT_URL: "/js/script.js" REQUIRE_FEATURED_ASSISTANTS: "true" TASK_MODEL: > diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index a9f8d562265ee2bf549e1102adfd2f301665056a..ea86653d9e030cb9ab214a03b1a85aa821587144 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -53,11 +53,6 @@ spec: - containerPort: {{ $.Values.envVars.APP_PORT | default 3000 | int }} name: http protocol: TCP - {{- if $.Values.monitoring.enabled }} - - containerPort: {{ $.Values.envVars.METRICS_PORT | default 5565 | int }} - name: metrics - protocol: TCP - {{- end }} resources: {{ toYaml .Values.resources | nindent 12 }} {{- with $.Values.extraEnv }} env: diff --git a/chart/templates/service-monitor.yaml b/chart/templates/service-monitor.yaml deleted file mode 100644 index 2d7fdae07d839b37ee0032ebb2b895b85af80a9b..0000000000000000000000000000000000000000 --- a/chart/templates/service-monitor.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if $.Values.monitoring.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: {{ include "labels.standard" . | nindent 4 }} - name: {{ include "name" . }} - namespace: {{ .Release.Namespace }} -spec: - selector: - matchLabels: {{ include "labels.standard" . | nindent 6 }} - endpoints: - - port: metrics - path: /metrics - interval: 15s -{{- end }} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml index 682f8571fa5b1e9b2532660c5e61a30ccc715e2c..0df90327704c18b7ea70ffd287193c9c7100d097 100644 --- a/chart/templates/service.yaml +++ b/chart/templates/service.yaml @@ -11,11 +11,5 @@ spec: port: 80 protocol: TCP targetPort: http - {{- if $.Values.monitoring.enabled }} - - name: metrics - port: 5565 - protocol: TCP - targetPort: metrics - {{- end }} selector: {{ include "labels.standard" . | nindent 4 }} type: {{.Values.service.type}} diff --git a/chart/values.yaml b/chart/values.yaml index 67ba9cfd0c60486580dfcc58506f9b7bb34ae8a9..29446ac9f489ccfc8b0f940d729438b55b90995b 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -70,5 +70,4 @@ autoscaling: targetMemoryUtilizationPercentage: "" targetCPUUtilizationPercentage: "" -monitoring: - enabled: false +## Metrics removed; monitoring configuration no longer used diff --git a/docs/source/_toctree.yml b/docs/source/_toctree.yml deleted file mode 100644 index 6287065386e44a96b8bfec3b75c7572eef98b06d..0000000000000000000000000000000000000000 --- a/docs/source/_toctree.yml +++ /dev/null @@ -1,64 +0,0 @@ -- local: index - title: 🤗 Chat UI -- title: Installation - sections: - - local: installation/local - title: Local - - local: installation/spaces - title: Spaces - - local: installation/docker - title: Docker - - local: installation/helm - title: Helm -- title: Configuration - sections: - - local: configuration/overview - title: Overview - - local: configuration/theming - title: Theming - - local: configuration/open-id - title: OpenID - - local: configuration/web-search - title: Web Search - - local: configuration/metrics - title: Metrics - - local: configuration/embeddings - title: Text Embedding Models - - title: Models - sections: - - local: configuration/models/overview - title: Overview - - local: configuration/models/multimodal - title: Multimodal - - local: configuration/models/tools - title: Tools - - title: Providers - sections: - - local: configuration/models/providers/anthropic - title: Anthropic - - local: configuration/models/providers/aws - title: AWS - - local: configuration/models/providers/cloudflare - title: Cloudflare - - local: configuration/models/providers/cohere - title: Cohere - - local: configuration/models/providers/google - title: Google - - local: configuration/models/providers/langserve - title: Langserve - - local: configuration/models/providers/llamacpp - title: Llama.cpp - - local: configuration/models/providers/ollama - title: Ollama - - local: configuration/models/providers/openai - title: OpenAI - - local: configuration/models/providers/tgi - title: TGI - - local: configuration/common-issues - title: Common Issues -- title: Developing - sections: - - local: developing/architecture - title: Architecture - - local: developing/copy-huggingchat - title: Copy HuggingChat diff --git a/docs/source/configuration/common-issues.md b/docs/source/configuration/common-issues.md deleted file mode 100644 index 8ebb98fff0e7e8311fe81946d87f4b8b36a77ca1..0000000000000000000000000000000000000000 --- a/docs/source/configuration/common-issues.md +++ /dev/null @@ -1,7 +0,0 @@ -# Common Issues - -## 403:You don't have access to this conversation - -Most likely you are running chat-ui over HTTP. The recommended option is to setup something like NGINX to handle HTTPS and proxy the requests to chat-ui. If you really need to run over HTTP you can add `ALLOW_INSECURE_COOKIES=true` to your `.env.local`. - -Make sure to set your `PUBLIC_ORIGIN` in your `.env.local` to the correct URL as well. diff --git a/docs/source/configuration/embeddings.md b/docs/source/configuration/embeddings.md deleted file mode 100644 index ad853725ca1809dfea778592029969e7f156cbb4..0000000000000000000000000000000000000000 --- a/docs/source/configuration/embeddings.md +++ /dev/null @@ -1,105 +0,0 @@ -# Text Embedding Models - -By default (for backward compatibility), when `TEXT_EMBEDDING_MODELS` environment variable is not defined, [transformers.js](https://huggingface.co/docs/transformers.js) embedding models will be used for embedding tasks, specifically, the [Xenova/gte-small](https://huggingface.co/Xenova/gte-small) model. - -You can customize the embedding model by setting `TEXT_EMBEDDING_MODELS` in your `.env.local` file where the required fields are `name`, `chunkCharLength` and `endpoints`. - -Supported text embedding backends are: [`transformers.js`](https://huggingface.co/docs/transformers.js), [`TEI`](https://github.com/huggingface/text-embeddings-inference) and [`OpenAI`](https://platform.openai.com/docs/guides/embeddings). `transformers.js` models run locally as part of `chat-ui`, whereas `TEI` models run in a different environment & accessed through an API endpoint. `openai` models are accessed through the [OpenAI API](https://platform.openai.com/docs/guides/embeddings). - -When more than one embedding models are supplied in `.env.local` file, the first will be used by default, and the others will only be used on LLM's which configured `embeddingModel` to the name of the model. - -## Transformers.js - -The Transformers.js backend uses local CPU for the embedding which can be quite slow. If possible, consider using TEI or OpenAI embeddings instead if you use web search frequently, as performance will improve significantly. - -```ini -TEXT_EMBEDDING_MODELS = `[ - { - "name": "Xenova/gte-small", - "displayName": "Xenova/gte-small", - "description": "locally running embedding", - "chunkCharLength": 512, - "endpoints": [ - { "type": "transformersjs" } - ] - } -]` -``` - -## Text Embeddings Inference (TEI) - -> Text Embeddings Inference (TEI) is a comprehensive toolkit designed for efficient deployment and serving of open source text embeddings models. It enables high-performance extraction for the most popular models, including FlagEmbedding, Ember, GTE, and E5. - -Some recommended models at the time of writing (May 2024) are `Snowflake/snowflake-arctic-embed-m` and `BAAI/bge-large-en-v1.5`. You may run TEI locally with GPU support via Docker: - -`docker run --gpus all -p 8080:80 -v tei-data:/data --name tei ghcr.io/huggingface/text-embeddings-inference:1.2 --model-id YOUR/HF_MODEL` - -You can then hook this up to your Chat UI instance with the following configuration. - -```ini -TEXT_EMBEDDING_MODELS=`[ - { - "name": "YOUR/HF_MODEL", - "displayName": "YOUR/HF_MODEL", - "preQuery": "Check the model documentation for the preQuery. Not all models have one", - "prePassage": "Check the model documentation for the prePassage. Not all models have one", - "chunkCharLength": 512, - "endpoints": [{ - "type": "tei", - "url": "http://127.0.0.1:8080/" - }] - } -]` -``` - -Examples for `Snowflake/snowflake-arctic-embed-m` and `BAAI/bge-large-en-v1.5`: - -```ini -TEXT_EMBEDDING_MODELS=`[ - { - "name": "Snowflake/snowflake-arctic-embed-m", - "displayName": "Snowflake/snowflake-arctic-embed-m", - "preQuery": "Represent this sentence for searching relevant passages: ", - "chunkCharLength": 512, - "endpoints": [{ - "type": "tei", - "url": "http://127.0.0.1:8080/" - }] - },{ - "name": "BAAI/bge-large-en-v1.5", - "displayName": "BAAI/bge-large-en-v1.5", - "chunkCharLength": 512, - "endpoints": [{ - "type": "tei", - "url": "http://127.0.0.1:8080/" - }] - } -]` -``` - -## OpenAI - -It's also possible to host your own OpenAI API compatible embedding models. [`Infinity`](https://github.com/michaelfeil/infinity) is one example. You may run it locally with Docker: - -`docker run -it --gpus all -v infinity-data:/app/.cache -p 7997:7997 michaelf34/infinity:latest v2 --model-id nomic-ai/nomic-embed-text-v1 --port 7997` - -You can then hook this up to your Chat UI instance with the following configuration. - -```ini -TEXT_EMBEDDING_MODELS=`[ - { - "name": "nomic-ai/nomic-embed-text-v1", - "displayName": "nomic-ai/nomic-embed-text-v1", - "chunkCharLength": 512, - "model": { - "name": "nomic-ai/nomic-embed-text-v1" - }, - "endpoints": [ - { - "type": "openai", - "url": "https://127.0.0.1:7997/embeddings" - } - ] - } -]` -``` diff --git a/docs/source/configuration/metrics.md b/docs/source/configuration/metrics.md deleted file mode 100644 index 45ad3e368baafd4a7bc8411eef2cf135335e2c6c..0000000000000000000000000000000000000000 --- a/docs/source/configuration/metrics.md +++ /dev/null @@ -1,9 +0,0 @@ -# Metrics - -The server can expose prometheus metrics on port `5565` but is off by default. You may enable the metrics server with `METRICS_ENABLED=true` and change the port with `METRICS_PORT=1234`. - - - -In development with `npm run dev`, the metrics server does not shutdown gracefully due to Sveltekit not providing hooks for restart. It's recommended to disable the metrics server in this case. - - diff --git a/docs/source/configuration/models/multimodal.md b/docs/source/configuration/models/multimodal.md deleted file mode 100644 index a8f1b367269f559a01ca82927eeb48b8bd9a1410..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/multimodal.md +++ /dev/null @@ -1,24 +0,0 @@ -# Multimodal - -We currently support [IDEFICS](https://huggingface.co/blog/idefics) (hosted on [TGI](./providers/tgi)), OpenAI and Anthropic Claude 3 as multimodal models. You can enable it by setting `multimodal: true` in your `MODELS` configuration. For IDEFICS, you must have a [PRO HF Api token](https://huggingface.co/settings/tokens). For OpenAI, see the [OpenAI section](./providers/openai). For Anthropic, see the [Anthropic section](./providers/anthropic). - -```ini -MODELS=`[ - { - "name": "HuggingFaceM4/idefics-80b-instruct", - "multimodal" : true, - "description": "IDEFICS is the new multimodal model by Hugging Face.", - "preprompt": "", - "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}User: {{content}}{{/ifUser}}\nAssistant: {{#ifAssistant}}{{content}}\n{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.1, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 12, - "truncate": 1000, - "max_new_tokens": 1024, - "stop": ["", "User:", "\nUser:"] - } - } -]` -``` diff --git a/docs/source/configuration/models/overview.md b/docs/source/configuration/models/overview.md deleted file mode 100644 index c7b40823916bd6011cc55e047618accf4db83c46..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/overview.md +++ /dev/null @@ -1,147 +0,0 @@ -# Models Overview - -You can customize the parameters passed to the model or even use a new model by updating the `MODELS` variable in your `.env.local`. The default one can be found in `.env` and looks like this : - -```ini -MODELS=`[ - { - "name": "mistralai/Mistral-7B-Instruct-v0.2", - "displayName": "mistralai/Mistral-7B-Instruct-v0.2", - "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.", - "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/", - "preprompt": "", - "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.3, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 3072, - "max_new_tokens": 1024, - "stop": [""] - }, - "promptExamples": [ - { - "title": "Write an email", - "prompt": "As a restaurant owner, write a professional email to the supplier to get these products every week: \n\n- Wine (x10)\n- Eggs (x24)\n- Bread (x12)" - }, { - "title": "Code a game", - "prompt": "Code a basic snake game in python, give explanations for each step." - }, { - "title": "Recipe help", - "prompt": "How do I make a delicious lemon cheesecake?" - } - ] - } -]` - -``` - -You can change things like the parameters, or customize the preprompt to better suit your needs. You can also add more models by adding more objects to the array, with different preprompts for example. - -## Chat Prompt Template - -When querying the model for a chat response, the `chatPromptTemplate` template is used. `messages` is an array of chat messages, it has the format `[{ content: string }, ...]`. To identify if a message is a user message or an assistant message the `ifUser` and `ifAssistant` block helpers can be used. - -The following is the default `chatPromptTemplate`, although newlines and indentation have been added for readability. You can find the prompts used in production for HuggingChat [here](https://github.com/huggingface/chat-ui/blob/main/PROMPTS.md). The templating language used is [Handlebars](https://www.npmjs.com/package/handlebars). - -```handlebars -{{preprompt}} -{{#each messages}} - {{#ifUser}}{{@root.userMessageToken}}{{content}}{{@root.userMessageEndToken}}{{/ifUser}} - {{#ifAssistant - }}{{@root.assistantMessageToken}}{{content}}{{@root.assistantMessageEndToken}}{{/ifAssistant}} -{{/each}} -{{assistantMessageToken}} -``` - -## Custom endpoint authorization - -### Basic and Bearer - -Custom endpoints may require authorization, depending on how you configure them. Authentication will usually be set either with `Basic` or `Bearer`. - -For `Basic` we will need to generate a base64 encoding of the username and password. - -`echo -n "USER:PASS" | base64` - -> VVNFUjpQQVNT - -For `Bearer` you can use a token, which can be grabbed from [here](https://huggingface.co/settings/tokens). - -You can then add the generated information and the `authorization` parameter to your `.env.local`. - -```ini -"endpoints": [ - { - "url": "https://HOST:PORT", - "authorization": "Basic VVNFUjpQQVNT", - } -] -``` - -Please note that if `HF_TOKEN` is also set or not empty, it will take precedence. - -## Models hosted on multiple custom endpoints - -If the model being hosted will be available on multiple servers/instances add the `weight` parameter to your `.env.local`. The `weight` will be used to determine the probability of requesting a particular endpoint. - -```ini -"endpoints": [ - { - "url": "https://HOST:PORT", - "weight": 1 - }, - { - "url": "https://HOST:PORT", - "weight": 2 - } - ... -] -``` - -## Client Certificate Authentication (mTLS) - -Custom endpoints may require client certificate authentication, depending on how you configure them. To enable mTLS between Chat UI and your custom endpoint, you will need to set the `USE_CLIENT_CERTIFICATE` to `true`, and add the `CERT_PATH` and `KEY_PATH` parameters to your `.env.local`. These parameters should point to the location of the certificate and key files on your local machine. The certificate and key files should be in PEM format. The key file can be encrypted with a passphrase, in which case you will also need to add the `CLIENT_KEY_PASSWORD` parameter to your `.env.local`. - -If you're using a certificate signed by a private CA, you will also need to add the `CA_PATH` parameter to your `.env.local`. This parameter should point to the location of the CA certificate file on your local machine. - -If you're using a self-signed certificate, e.g. for testing or development purposes, you can set the `REJECT_UNAUTHORIZED` parameter to `false` in your `.env.local`. This will disable certificate validation, and allow Chat UI to connect to your custom endpoint. - -## Specific Embedding Model - -A model can use any of the embedding models defined under `TEXT_EMBEDDING_MODELS`, (currently used when web searching). By default it will use the first embedding model, but it can be changed with the field `embeddingModel`: - -```ini -TEXT_EMBEDDING_MODELS = `[ - { - "name": "Xenova/gte-small", - "chunkCharLength": 512, - "endpoints": [ - {"type": "transformersjs"} - ] - }, - { - "name": "intfloat/e5-base-v2", - "chunkCharLength": 768, - "endpoints": [ - {"type": "tei", "url": "http://127.0.0.1:8080/", "authorization": "Basic VVNFUjpQQVNT"}, - {"type": "tei", "url": "http://127.0.0.1:8081/"} - ] - } -]` - -MODELS=`[ - { - "name": "Ollama Mistral", - "chatPromptTemplate": "...", - "embeddingModel": "intfloat/e5-base-v2" - "parameters": { - ... - }, - "endpoints": [ - ... - ] - } -]` -``` diff --git a/docs/source/configuration/models/providers/anthropic.md b/docs/source/configuration/models/providers/anthropic.md deleted file mode 100644 index db18bc12ab55d420d8f3050cd8de0937523a43b0..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/anthropic.md +++ /dev/null @@ -1,117 +0,0 @@ -# Anthropic - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | Yes | - -We also support Anthropic models (including multimodal ones via `multmodal: true`) through the official SDK. You may provide your API key via the `ANTHROPIC_API_KEY` env variable, or alternatively, through the `endpoints.apiKey` as per the following example. - -```ini -MODELS=`[ - { - "name": "claude-3-haiku-20240307", - "displayName": "Claude 3 Haiku", - "description": "Fastest and most compact model for near-instant responsiveness", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-sonnet-20240229", - "displayName": "Claude 3 Sonnet", - "description": "Ideal balance of intelligence and speed", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-opus-20240229", - "displayName": "Claude 3 Opus", - "description": "Most powerful model for highly complex tasks", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096 - }, - "endpoints": [ - { - "type": "anthropic", - // optionals - "apiKey": "sk-ant-...", - "baseURL": "https://api.anthropic.com", - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - } -]` -``` - -## VertexAI - -We also support using Anthropic models running on Vertex AI. Authentication is done using Google Application Default Credentials. Project ID can be provided through the `endpoints.projectId` as per the following example: - -```ini -MODELS=`[ - { - "name": "claude-3-haiku@20240307", - "displayName": "Claude 3 Haiku", - "description": "Fastest, most compact model for near-instant responsiveness", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096 - }, - "endpoints": [ - { - "type": "anthropic-vertex", - "region": "us-central1", - "projectId": "gcp-project-id", - // optionals - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, - { - "name": "claude-3-sonnet@20240229", - "displayName": "Claude 3 Sonnet", - "description": "Ideal balance of intelligence and speed", - "multimodal": true, - "parameters": { - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "anthropic-vertex", - "region": "us-central1", - "projectId": "gcp-project-id", - // optionals - "defaultHeaders": {}, - "defaultQuery": {} - } - ] - }, -]` -``` diff --git a/docs/source/configuration/models/providers/aws.md b/docs/source/configuration/models/providers/aws.md deleted file mode 100644 index 07374de45f30566a0425365b621d236ffd648f46..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/aws.md +++ /dev/null @@ -1,35 +0,0 @@ -# Amazon Web Services (AWS) - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | No | - -You may specify your Amazon SageMaker instance as an endpoint for Chat UI: - -```ini -MODELS=`[{ - "name": "your-model", - "displayName": "Your Model", - "description": "Your description", - "parameters": { - "max_new_tokens": 4096 - }, - "endpoints": [ - { - "type" : "aws", - "service" : "sagemaker" - "url": "", - "accessKey": "", - "secretKey" : "", - "sessionToken": "", - "region": "", - "weight": 1 - } - ] -}]` -``` - -You can also set `"service": "lambda"` to use a lambda instance. - -You can get the `accessKey` and `secretKey` from your AWS user, under programmatic access. diff --git a/docs/source/configuration/models/providers/cloudflare.md b/docs/source/configuration/models/providers/cloudflare.md deleted file mode 100644 index 35534763e61bf8e92eb181e97082181387956aa9..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/cloudflare.md +++ /dev/null @@ -1,35 +0,0 @@ -# Cloudflare - -| Feature | Available | -| ------------------------------ | --------- | -| [Tools](../tools.md) | No | -| [Multimodal](../multimodal.md) | No | - -You may use Cloudflare Workers AI to run your own models with serverless inference. - -You will need to have a Cloudflare account, then get your [account ID](https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/) as well as your [API token](https://developers.cloudflare.com/workers-ai/get-started/rest-api/#1-get-an-api-token) for Workers AI. - -You can either specify them directly in your `.env.local` using the `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` variables, or you can set them directly in the endpoint config. - -You can find the list of models available on Cloudflare [here](https://developers.cloudflare.com/workers-ai/models/#text-generation). - -```ini -MODELS=`[ - { - "name" : "nousresearch/hermes-2-pro-mistral-7b", - "tokenizer": "nousresearch/hermes-2-pro-mistral-7b", - "parameters": { - "stop": ["<|im_end|>"] - }, - "endpoints" : [ - { - "type" : "cloudflare" - - } - ] - } -]` -``` diff --git a/docs/source/configuration/models/providers/cohere.md b/docs/source/configuration/models/providers/cohere.md deleted file mode 100644 index 6def938d41f8235aa59e2352927e438ac592df38..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/cohere.md +++ /dev/null @@ -1,26 +0,0 @@ -# Cohere - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | Yes | -| [Multimodal](../multimodal) | No | - -You may use Cohere to run their models directly from Chat UI. You will need to have a Cohere account, then get your [API token](https://dashboard.cohere.com/api-keys). You can either specify it directly in your `.env.local` using the `COHERE_API_TOKEN` variable, or you can set it in the endpoint config. - -Here is an example of a Cohere model config. You can set which model you want to use by setting the `id` field to the model name. - -```ini -MODELS=`[ - { - "name": "command-r-plus", - "displayName": "Command R+", - "tools": true, - "endpoints": [{ - "type": "cohere", - - }] - } -]` -``` diff --git a/docs/source/configuration/models/providers/google.md b/docs/source/configuration/models/providers/google.md deleted file mode 100644 index 1d8dcd33f3b46d9f8bb3e739575a28ba52ef667f..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/google.md +++ /dev/null @@ -1,92 +0,0 @@ -# Google - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | No | - -Chat UI can connect to the google Vertex API endpoints ([List of supported models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)). - -To enable: - -1. [Select](https://console.cloud.google.com/project) or [create](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project) a Google Cloud project. -1. [Enable billing for your project](https://cloud.google.com/billing/docs/how-to/modify-project). -1. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com). -1. [Set up authentication with a service account](https://cloud.google.com/docs/authentication/getting-started) - so you can access the API from your local workstation. - -The service account credentials file can be imported as an environmental variable: - -```ini -GOOGLE_APPLICATION_CREDENTIALS = clientid.json -``` - -Make sure your docker container has access to the file and the variable is correctly set. -Afterwards Google Vertex endpoints can be configured as following: - -```ini -MODELS=`[ - { - "name": "gemini-1.5-pro", - "displayName": "Vertex Gemini Pro 1.5", - "endpoints" : [{ - "type": "vertex", - "project": "abc-xyz", - "location": "europe-west3", - "extraBody": { - "model_version": "gemini-1.5-pro-002", - }, - // Optional - "safetyThreshold": "BLOCK_MEDIUM_AND_ABOVE", - "apiEndpoint": "", // alternative api endpoint url, - "tools": [{ - "googleSearchRetrieval": { - "disableAttribution": true - } - }] - }] - } -]` -``` - -## GenAI - -Or use the Gemini API API provider [from](https://github.com/google-gemini/generative-ai-js#readme): - -Make sure that you have an API key from Google Cloud Platform. To get an API key, follow the instructions [here](https://ai.google.dev/gemini-api/docs/api-key). - -You can either specify them directly in your `.env.local` using the `GOOGLE_GENAI_API_KEY` variables, or you can set them directly in the endpoint config. - -You can find the list of models available [here](https://ai.google.dev/gemini-api/docs/models/gemini), and experimental models available [here](https://ai.google.dev/gemini-api/docs/models/experimental-models). - -```ini -MODELS=`[ - { - "name": "gemini-1.5-flash", - "displayName": "Gemini Flash 1.5", - "multimodal": true, - "endpoints": [ - { - "type": "genai", - - // Optional - "apiKey": "abc...xyz" - "safetyThreshold": "BLOCK_MEDIUM_AND_ABOVE", - } - ] - }, - { - "name": "gemini-1.5-pro", - "displayName": "Gemini Pro 1.5", - "multimodal": false, - "endpoints": [ - { - "type": "genai", - - // Optional - "apiKey": "abc...xyz" - } - ] - } -]` -``` diff --git a/docs/source/configuration/models/providers/langserve.md b/docs/source/configuration/models/providers/langserve.md deleted file mode 100644 index 931358c716ecbdfb9d3cbce05e7ebdeb30318e3b..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/langserve.md +++ /dev/null @@ -1,22 +0,0 @@ -# LangServe - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | No | - -LangChain applications that are deployed using LangServe can be called with the following config: - -```ini -MODELS=`[ - { - "name": "summarization-chain", - "displayName": "Summarization Chain" - "endpoints" : [{ - "type": "langserve", - "url" : "http://127.0.0.1:8100", - }] - } -]` - -``` diff --git a/docs/source/configuration/models/providers/llamacpp.md b/docs/source/configuration/models/providers/llamacpp.md deleted file mode 100644 index 8a21e947f904777b7a5095b9d6a78cb3c01e5a1f..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/llamacpp.md +++ /dev/null @@ -1,49 +0,0 @@ -# Llama.cpp - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | No | - -Chat UI supports the llama.cpp API server directly without the need for an adapter. You can do this using the `llamacpp` endpoint type. - -If you want to run Chat UI with llama.cpp, you can do the following, using [microsoft/Phi-3-mini-4k-instruct-gguf](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf) as an example model: - -```bash -# install llama.cpp -brew install llama.cpp -# start llama.cpp server -llama-server --hf-repo microsoft/Phi-3-mini-4k-instruct-gguf --hf-file Phi-3-mini-4k-instruct-q4.gguf -c 4096 -``` - -_note: you can swap the `hf-repo` and `hf-file` with your fav GGUF on the [Hub](https://huggingface.co/models?library=gguf). For example: `--hf-repo TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF` for [this repo](https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF) & `--hf-file tinyllama-1.1b-chat-v1.0.Q4_0.gguf` for [this file](https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/blob/main/tinyllama-1.1b-chat-v1.0.Q4_0.gguf)._ - -A local LLaMA.cpp HTTP Server will start on `http://localhost:8080` (to change the port or any other default options, please find [LLaMA.cpp HTTP Server readme](https://github.com/ggml-org/llama.cpp/tree/master/tools/server#readme)). - -Add the following to your `.env.local`: - -```ini -MODELS=`[ - { - "name": "Local microsoft/Phi-3-mini-4k-instruct-gguf", - "tokenizer": "microsoft/Phi-3-mini-4k-instruct-gguf", - "preprompt": "", - "chatPromptTemplate": "{{preprompt}}{{#each messages}}{{#ifUser}}<|user|>\n{{content}}<|end|>\n<|assistant|>\n{{/ifUser}}{{#ifAssistant}}{{content}}<|end|>\n{{/ifAssistant}}{{/each}}", - "parameters": { - "stop": ["<|end|>", "<|endoftext|>", "<|assistant|>"], - "temperature": 0.7, - "max_new_tokens": 1024, - "truncate": 3071 - }, - "endpoints": [{ - "type" : "llamacpp", - "baseURL": "http://localhost:8080" - }], - }, -]` -``` - -
- - -
diff --git a/docs/source/configuration/models/providers/ollama.md b/docs/source/configuration/models/providers/ollama.md deleted file mode 100644 index ae0f4f189dc26f601c24aebcaef68c0d2facc0ae..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/ollama.md +++ /dev/null @@ -1,39 +0,0 @@ -# Ollama - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | No | - -We also support the Ollama inference server. Spin up a model with - -```bash -ollama run mistral -``` - -Then specify the endpoints like so: - -```ini -MODELS=`[ - { - "name": "Ollama Mistral", - "chatPromptTemplate": "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}} {{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}} {{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.1, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 3072, - "max_new_tokens": 1024, - "stop": ["
"] - }, - "endpoints": [ - { - "type": "ollama", - "url" : "http://127.0.0.1:11434", - "ollamaName" : "mistral" - } - ] - } -]` -``` diff --git a/docs/source/configuration/models/providers/openai.md b/docs/source/configuration/models/providers/openai.md deleted file mode 100644 index c324f3419dce3a6fe8d028e11de04ec507fceff5..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/openai.md +++ /dev/null @@ -1,181 +0,0 @@ -# OpenAI - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | No | -| [Multimodal](../multimodal) | Yes | - -Chat UI can be used with any API server that supports OpenAI API compatibility, for example [text-generation-webui](https://github.com/oobabooga/text-generation-webui/tree/main/extensions/openai), [LocalAI](https://github.com/go-skynet/LocalAI), [FastChat](https://github.com/lm-sys/FastChat/blob/main/docs/openai_api.md), [llama-cpp-python](https://github.com/abetlen/llama-cpp-python), and [ialacol](https://github.com/chenhunghan/ialacol) and [vllm](https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html). - -The following example config makes Chat UI works with [text-generation-webui](https://github.com/oobabooga/text-generation-webui/tree/main/extensions/openai), the `endpoint.baseUrl` is the url of the OpenAI API compatible server, this overrides the baseUrl to be used by OpenAI instance. The `endpoint.completion` determine which endpoint to be used, default is `chat_completions` which uses `/chat/completions`, change to `endpoint.completion` to `completions` to use the `/completions` endpoint. - -```ini -MODELS=`[ - { - "name": "text-generation-webui", - "id": "text-generation-webui", - "parameters": { - "temperature": 0.9, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 1000, - "max_new_tokens": 1024, - "stop": [] - }, - "endpoints": [{ - "type" : "openai", - "baseURL": "http://localhost:8000/v1" - }] - } -]` - -``` - -The `openai` type includes official OpenAI models. You can add, for example, GPT4/GPT3.5 as a "openai" model: - -```ini -OPENAI_API_KEY=#your openai api key here -MODELS=`[{ - "name": "gpt-4", - "displayName": "GPT 4", - "endpoints" : [{ - "type": "openai", - "apiKey": "or your openai api key here" - }] -},{ - "name": "gpt-3.5-turbo", - "displayName": "GPT 3.5 Turbo", - "endpoints" : [{ - "type": "openai", - "apiKey": "or your openai api key here" - }] -}]` -``` - -We also support models in the `o1` family. You need to add a few more options ot the config: Here is an example for `o1-mini`: - -```ini -MODELS=`[ - { - "name": "o1-mini", - "description": "ChatGPT o1-mini", - "systemRoleSupported": false, - "parameters": { - "max_new_tokens": 2048, - }, - "endpoints" : [{ - "type": "openai", - "useCompletionTokens": true, - }] - } -] -``` - -You may also consume any model provider that provides compatible OpenAI API endpoint. For example, you may self-host [Portkey](https://github.com/Portkey-AI/gateway) gateway and experiment with Claude or GPTs offered by Azure OpenAI. Example for Claude from Anthropic: - -```ini -MODELS=`[{ - "name": "claude-2.1", - "displayName": "Claude 2.1", - "description": "Anthropic has been founded by former OpenAI researchers...", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://gateway.example.com/v1", - "defaultHeaders": { - "x-portkey-config": '{"provider":"anthropic","api_key":"sk-ant-abc...xyz"}' - } - } - ] -}]` -``` - -Example for GPT 4 deployed on Azure OpenAI: - -```ini -MODELS=`[{ - "id": "gpt-4-1106-preview", - "name": "gpt-4-1106-preview", - "displayName": "gpt-4-1106-preview", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://{resource-name}.openai.azure.com/openai/deployments/{deployment-id}", - "defaultHeaders": { - "api-key": "{api-key}" - }, - "defaultQuery": { - "api-version": "2023-05-15" - } - } - ] -}]` -``` - -## DeepInfra - -Or try Mistral from [Deepinfra](https://deepinfra.com/mistralai/Mistral-7B-Instruct-v0.1/api?example=openai-http): - -> Note, apiKey can either be set custom per endpoint, or globally using `OPENAI_API_KEY` variable. - -```ini -MODELS=`[{ - "name": "mistral-7b", - "displayName": "Mistral 7B", - "description": "A 7B dense Transformer, fast-deployed and easily customisable. Small, yet powerful for a variety of use cases. Supports English and code, and a 8k context window.", - "parameters": { - "temperature": 0.5, - "max_new_tokens": 4096, - }, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://api.deepinfra.com/v1/openai", - "apiKey": "abc...xyz" - } - ] -}]` -``` - -_Non-streaming endpoints_ - -For endpoints that don´t support streaming like o1 on Azure, you can pass `streamingSupported: false` in your endpoint config: - -``` -MODELS=`[{ - "id": "o1-preview", - "name": "o1-preview", - "displayName": "o1-preview", - "systemRoleSupported": false, - "endpoints": [ - { - "type": "openai", - "baseURL": "https://my-deployment.openai.azure.com/openai/deployments/o1-preview", - "defaultHeaders": { - "api-key": "$SECRET" - }, - "streamingSupported": false, - } - ] -}]` -``` - -## Other - -Some other providers and their `baseURL` for reference. - -[Groq](https://groq.com/): https://api.groq.com/openai/v1 -[Fireworks](https://fireworks.ai/): https://api.fireworks.ai/inference/v1 - -``` - -``` diff --git a/docs/source/configuration/models/providers/tgi.md b/docs/source/configuration/models/providers/tgi.md deleted file mode 100644 index 87f8aa1034e6ccb2c9fbcc8cacff99a8608f433e..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/providers/tgi.md +++ /dev/null @@ -1,66 +0,0 @@ -# Text Generation Inference (TGI) - -| Feature | Available | -| --------------------------- | --------- | -| [Tools](../tools) | Yes\* | -| [Multimodal](../multimodal) | Yes\* | - -\* Tools are only supported with the Cohere Command R+ model with the Xenova tokenizers. Please see the [Tools](../tools) section. - -\* Multimodal is only supported with the IDEFICS model. Please see the [Multimodal](../multimodal) section. - -By default, if `endpoints` are left unspecified, Chat UI will look for the model on the hosted Hugging Face inference API using the model name, and use your `HF_TOKEN`. Refer to the [overview](../overview) for more information about model configuration. - -```ini -MODELS=`[ - { - "name": "mistralai/Mistral-7B-Instruct-v0.2", - "displayName": "mistralai/Mistral-7B-Instruct-v0.2", - "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.", - "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/", - "preprompt": "", - "chatPromptTemplate" : "{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}{{/ifAssistant}}{{/each}}", - "parameters": { - "temperature": 0.3, - "top_p": 0.95, - "repetition_penalty": 1.2, - "top_k": 50, - "truncate": 3072, - "max_new_tokens": 1024, - "stop": [""] - }, - "promptExamples": [ - { - "title": "Write an email", - "prompt": "As a restaurant owner, write a professional email to the supplier to get these products every week: \n\n- Wine (x10)\n- Eggs (x24)\n- Bread (x12)" - }, { - "title": "Code a game", - "prompt": "Code a basic snake game in python, give explanations for each step." - }, { - "title": "Recipe help", - "prompt": "How do I make a delicious lemon cheesecake?" - } - ] - } -]` -``` - -## Running your own models using a custom endpoint - -If you want to, instead of hitting models on the Hugging Face Inference API, you can run your own models locally. - -A good option is to hit a [text-generation-inference](https://github.com/huggingface/text-generation-inference) endpoint. This is what is done in the official [Chat UI Spaces Docker template](https://huggingface.co/new-space?template=huggingchat/chat-ui-template) for instance: both this app and a text-generation-inference server run inside the same container. - -To do this, you can add your own endpoints to the `MODELS` variable in `.env.local`, by adding an `"endpoints"` key for each model in `MODELS`. - -```ini -MODELS=`[{ - "name": "your-model-name", - "displayName": "Your Model Name", - ... other model config - "endpoints": [{ - "type" : "tgi", - "url": "https://HOST:PORT", - }] -}]` -``` diff --git a/docs/source/configuration/models/tools.md b/docs/source/configuration/models/tools.md deleted file mode 100644 index b38793640b7b1cd650a5e9e28d89d5fb883332ca..0000000000000000000000000000000000000000 --- a/docs/source/configuration/models/tools.md +++ /dev/null @@ -1,62 +0,0 @@ -# Tools - -Tool calling instructs the model to generate an output matching a user-defined schema, which may be parsed for invoking external tools. The model simply chooses the tools and their parameters. Currently, only `TGI` and `Cohere` with `Command R+` are supported. - -
- - -
- -## TGI Configuration - -A custom tokenizer is required for prompting the model for generating tool calls, as well as prompting with the results. The expected format for these tools and the resulting tool calls are hard coded for TGI, so it's likely that only the following configuration will work: - -```ini -MODELS=`[ - { - "name" : "CohereForAI/c4ai-command-r-plus", - "displayName": "Command R+", - "description": "Command R+ is Cohere's latest LLM and is the first open weight model to beat GPT4 in the Chatbot Arena!", - "tools": true, - "tokenizer": "Xenova/c4ai-command-r-v01-tokenizer", - "modelUrl": "https://huggingface.co/CohereForAI/c4ai-command-r-plus", - "websiteUrl": "https://docs.cohere.com/docs/command-r-plus", - "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/cohere-logo.png", - "parameters": { - "stop": ["<|END_OF_TURN_TOKEN|>"], - "truncate" : 28672, - "max_new_tokens" : 4096, - "temperature" : 0.3 - } - } -]` -``` - -## Cohere Configuration - -The Cohere provider supports the endpoint native method of tool calling. Refer to the `endpoints/cohere` for implementation details. - -```ini -MODELS=`[ - { - "name": "command-r-plus", - "displayName": "Command R+", - "description": "Command R+ is Cohere's latest LLM and is the first open weight model to beat GPT4 in the Chatbot Arena!", - "tools": true, - "websiteUrl": "https://docs.cohere.com/docs/command-r-plus", - "logoUrl": "https://huggingface.co/datasets/huggingchat/models-logo/resolve/main/cohere-logo.png", - "endpoints": [{ - "type": "cohere", - "apiKey": "YOUR_API_KEY" - }] - } -]` -``` - -## Adding Tools - -Tool implementations are placed in `src/lib/server/tools`, with helpers available for easy integration with HuggingFace Zero GPU spaces. In the future, there may be an OpenAPI interface for adding tools. - -## Adding Support for Additional Models - -The TGI implementation uses a custom tokenizer and hard coded schema for supporting tools. The Cohere implementation, on the other hand, uses the native support in the SDK to emit tool calls. This is the recommended way to add support for more models. Please see the `endpoints/cohere` section of the code for implementation details. diff --git a/docs/source/configuration/open-id.md b/docs/source/configuration/open-id.md deleted file mode 100644 index 90ba2e97a8049150364620d7a80582d14261166e..0000000000000000000000000000000000000000 --- a/docs/source/configuration/open-id.md +++ /dev/null @@ -1,16 +0,0 @@ -# OpenID - -The login feature is disabled by default and users are attributed a unique ID based on their browser. But if you want to use OpenID to authenticate your users, you can add the following to your `.env.local` file: - -```ini -OPENID_CONFIG=`{ - PROVIDER_URL: "", - CLIENT_ID: "", - CLIENT_SECRET: "", - SCOPES: "openid profile", - TOLERANCE: // optional - RESOURCE: // optional -}` -``` - -Redirect URI: `/login/callback` diff --git a/docs/source/configuration/overview.md b/docs/source/configuration/overview.md deleted file mode 100644 index e20defc99eb4625061be860b897465ec496f0dd1..0000000000000000000000000000000000000000 --- a/docs/source/configuration/overview.md +++ /dev/null @@ -1,10 +0,0 @@ -# Configuration Overview - -Chat UI handles configuration with environment variables. The default config for Chat UI is stored in the `.env` file, which you may use as a reference. You will need to override some values to get Chat UI to run locally. This can be done in `.env.local` or via your environment. The bare minimum configuration to get Chat UI running is: - -```ini -MONGODB_URL=mongodb://localhost:27017 -HF_TOKEN=your_token -``` - -The following sections detail various sections of the app you may want to configure. diff --git a/docs/source/configuration/theming.md b/docs/source/configuration/theming.md deleted file mode 100644 index fbd52fed451cf0934045a07c703f24799216f621..0000000000000000000000000000000000000000 --- a/docs/source/configuration/theming.md +++ /dev/null @@ -1,18 +0,0 @@ -# Theming - -You can use a few environment variables to customize the look and feel of Chat UI. These are by default: - -```ini -PUBLIC_APP_NAME=ChatUI -PUBLIC_APP_ASSETS=chatui -PUBLIC_APP_COLOR=blue -PUBLIC_APP_DESCRIPTION="Making the community's best AI chat models available to everyone." -PUBLIC_APP_DATA_SHARING= -PUBLIC_APP_DISCLAIMER= -``` - -- `PUBLIC_APP_NAME` The name used as a title throughout the app. -- `PUBLIC_APP_ASSETS` Is used to find logos & favicons in `static/$PUBLIC_APP_ASSETS`, current options are `chatui` and `huggingchat`. -- `PUBLIC_APP_COLOR` Can be any of the [tailwind colors](https://tailwindcss.com/docs/customizing-colors#default-color-palette). -- `PUBLIC_APP_DATA_SHARING` Can be set to 1 to add a toggle in the user settings that lets your users opt-in to data sharing with models creator. -- `PUBLIC_APP_DISCLAIMER` If set to 1, we show a disclaimer about generated outputs on login. diff --git a/docs/source/configuration/web-search.md b/docs/source/configuration/web-search.md deleted file mode 100644 index 6451b7c19f5b714d68a826b417d9e429af67eef4..0000000000000000000000000000000000000000 --- a/docs/source/configuration/web-search.md +++ /dev/null @@ -1,58 +0,0 @@ -# Web Search - -Chat UI features a powerful Web Search feature. A high level overview of how it works: - -1. Generate an appropriate search query from the user prompt using the `TASK_MODEL` -2. Perform web search via an external provider (i.e. Serper) or via locally scrape Google results -3. Load each search result into playwright and scrape -4. Convert scraped HTML to Markdown tree with headings as parents -5. Create embeddings for each Markdown element -6. Find the embeddings closest to the user query using a vector similarity search (inner product) -7. Get the corresponding Markdown elements and their parent, up to 8000 characters -8. Supply the information as context to the model - -
- - -
- -## Providers - -Many providers are supported for the web search, or you can use locally scraped Google results. - -### Local - -For locally scraped Google results, put `USE_LOCAL_WEBSEARCH=true` in your `.env.local`. Please note that you may hit rate limits as we make no attempt to make the traffic look legitimate. To avoid this, you may choose a provider, such as Serper, used on the official instance. - -### SearXNG - -> SearXNG is a free internet metasearch engine which aggregates results from various search services and databases. Users are neither tracked nor profiled. - -You may enable support via the `SEARXNG_QUERY_URL` where `` will be replaced with the query keywords. Please see [the official documentation](https://docs.searxng.org/dev/search_api.html) for more information - -Example: `https://searxng.yourdomain.com/search?q=&engines=duckduckgo,google&format=json` - -### Third Party - -Many third party providers are supported as well. The official instance uses Serper. - -```ini -YDC_API_KEY=docs.you.com api key here -SERPER_API_KEY=serper.dev api key here -SERPAPI_KEY=serpapi key here -SERPSTACK_API_KEY=serpstack api key here -SEARCHAPI_KEY=searchapi api key here -``` - -## Block/Allow List - -You may block or allow specific websites from the web search results. When using an allow list, only the links in the allowlist will be used. For supported search engines, the links will be blocked from the results directly. Any URL in the results that **partially or fully matches** the entry will be filtered out. - -```ini -WEBSEARCH_BLOCKLIST=`["youtube.com", "https://example.com/foo/bar"]` -WEBSEARCH_ALLOWLIST=`["stackoverflow.com"]` -``` - -## Disabling Javascript - -By default, Playwright will execute all Javascript on the page. This can be intensive, requiring up to 6 cores for full performance, on some webpages. You may block scripts from running by settings `WEBSEARCH_JAVASCRIPT=false`. However, this will not block Javascript inlined in the HTML. diff --git a/docs/source/developing/architecture.md b/docs/source/developing/architecture.md deleted file mode 100644 index 6a41fa16471434ed38dcfa64de2509008524f30b..0000000000000000000000000000000000000000 --- a/docs/source/developing/architecture.md +++ /dev/null @@ -1,35 +0,0 @@ -# Architecture - -This document discusses the high level overview of the Chat UI codebase. If you're looking to contribute or just want to understand how the codebase works, this is the place for you! - -## Overview - -Chat UI provides a simple interface connecting LLMs to external information and tools. The project uses [MongoDB](https://www.mongodb.com/) and [SvelteKit](https://kit.svelte.dev/) with [Tailwind](https://tailwindcss.com/). - -## Code Map - -This section discusses various modules of the codebase briefly. The headings are not paths since the codebase structure may change. - -### `routes` - -Provides all of the routes rendered with SSR via SvelteKit. The majority of backend and frontend logic can be found here, with some modules being pulled out into `lib` for the client and `lib/server` for the server. - -### `textGeneration` - -Provides a standard interface for most chat features such as model output, web search, assistants and tools. Outputs `MessageUpdate`s which provide fine-grained updates on the request status such as new tokens and web search results. - -### `endpoints`/`embeddingEndpoints` - -Provides a common streaming interface for many third party LLM and embedding providers. - -### `websearch` - -Implements web search querying and RAG. See the [Web Search](../configuration/web-search) section for more information. - -### `tools` - -Provides a common interface for external tools called by LLMs. See the [Tools](../configuration/models/tools.md) section for more information - -### `migrations` - -Includes all MongoDB migrations for maintaining backwards compatibility across schema changes. Any changes to the schema must include a migration diff --git a/docs/source/developing/copy-huggingchat.md b/docs/source/developing/copy-huggingchat.md deleted file mode 100644 index 1e64c6f234134f72099bb809a49c34f637a4df56..0000000000000000000000000000000000000000 --- a/docs/source/developing/copy-huggingchat.md +++ /dev/null @@ -1,71 +0,0 @@ -# Copy HuggingChat - -The config file for HuggingChat is stored in the `chart/env/prod.yaml` file. It is the source of truth for the environment variables used for our CI/CD pipeline. For HuggingChat, as we need to customize the app color, as well as the base path, we build a custom docker image. You can find the workflow here. - - - -If you want to make changes to the model config used in production for HuggingChat, you should do so against `chart/env/prod.yaml`. - - - -### Running a copy of HuggingChat locally - -If you want to run an exact copy of HuggingChat locally, you will need to do the following first: - -1. Create an [OAuth App on the hub](https://huggingface.co/settings/applications/new) with `openid profile email` permissions. Make sure to set the callback URL to something like `http://localhost:5173/chat/login/callback` which matches the right path for your local instance. -2. Create a [HF Token](https://huggingface.co/settings/tokens) with your Hugging Face account. You will need a Pro account to be able to access some of the larger models available through HuggingChat. -3. Create a free account with [serper.dev](https://serper.dev/) (you will get 2500 free search queries) -4. Run an instance of MongoDB, however you want. (Local or remote) - -You can then create a new `.env.SECRET_CONFIG` file with the following content - -```ini -MONGODB_URL= -HF_TOKEN= -OPENID_CONFIG=`{ - PROVIDER_URL: "https://huggingface.co", - CLIENT_ID: "", - CLIENT_SECRET: "", -}` -SERPER_API_KEY= -MESSAGES_BEFORE_LOGIN= -``` - -You can then run `npm run updateLocalEnv` in the root of chat-ui. This will create a `.env.local` file which combines the `chart/env/prod.yaml` and the `.env.SECRET_CONFIG` file. You can then run `npm run dev` to start your local instance of HuggingChat. - -### Populate database - - - -The `MONGODB_URL` used for this script will be fetched from `.env.local`. Make sure it's correct! The command runs directly on the database. - - - -You can populate the database using faker data using the `populate` script: - -```bash -npm run populate -``` - -At least one flag must be specified, the following flags are available: - -- `reset` - resets the database -- `all` - populates all tables -- `users` - populates the users table -- `settings` - populates the settings table for existing users -- `assistants` - populates the assistants table for existing users -- `conversations` - populates the conversations table for existing users - -For example, you could use it like so: - -```bash -npm run populate reset -``` - -to clear out the database. Then login in the app to create your user and run the following command: - -```bash -npm run populate users settings assistants conversations -``` - -to populate the database with fake data, including fake conversations and assistants for your user. diff --git a/docs/source/index.md b/docs/source/index.md deleted file mode 100644 index d0ba841aa8d70c42ac605c25ef1f25e5c892b58a..0000000000000000000000000000000000000000 --- a/docs/source/index.md +++ /dev/null @@ -1,97 +0,0 @@ -# 🤗 Chat UI - -Open source chat interface with support for tools, web search, multimodal and many API providers. The app uses MongoDB and SvelteKit behind the scenes. Try the live version of the app called [HuggingChat on hf.co/chat](https://huggingface.co/chat) or [setup your own instance](./installation/spaces). - -🔧 **[Tools](./configuration/models/tools)**: Function calling with custom tools and support for [Zero GPU spaces](https://huggingface.co/spaces/enzostvs/zero-gpu-spaces) - -🔍 **[Web Search](./configuration/web-search)**: Automated web search, scraping and RAG for all models - -🐙 **[Multimodal](./configuration/models/multimodal)**: Accepts image file uploads on supported providers - -👤 **[OpenID](./configuration/open-id)**: Optionally setup OpenID for user authentication - -
- -
-Tools -
- - -
-
- -
-Web Search -
- - -
-
- -
- -## Quickstart - -You can quickly have a locally running chat-ui & LLM text-generation server thanks to chat-ui's [llama.cpp server support](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). - -**Step 1 (Start llama.cpp server):** - -```bash -# install llama.cpp -brew install llama.cpp -# start llama.cpp server (using hf.co/microsoft/Phi-3-mini-4k-instruct-gguf as an example) -llama-server --hf-repo microsoft/Phi-3-mini-4k-instruct-gguf --hf-file Phi-3-mini-4k-instruct-q4.gguf -c 4096 -``` - -A local LLaMA.cpp HTTP Server will start on `http://localhost:8080`. Read more [here](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). - -**Step 2 (tell chat-ui to use local llama.cpp server):** - -Add the following to your `.env.local`: - -```ini -MODELS=`[ - { - "name": "Local microsoft/Phi-3-mini-4k-instruct-gguf", - "tokenizer": "microsoft/Phi-3-mini-4k-instruct-gguf", - "preprompt": "", - "chatPromptTemplate": "{{preprompt}}{{#each messages}}{{#ifUser}}<|user|>\n{{content}}<|end|>\n<|assistant|>\n{{/ifUser}}{{#ifAssistant}}{{content}}<|end|>\n{{/ifAssistant}}{{/each}}", - "parameters": { - "stop": ["<|end|>", "<|endoftext|>", "<|assistant|>"], - "temperature": 0.7, - "max_new_tokens": 1024, - "truncate": 3071 - }, - "endpoints": [{ - "type" : "llamacpp", - "baseURL": "http://localhost:8080" - }], - }, -]` -``` - -Read more [here](https://huggingface.co/docs/chat-ui/configuration/models/providers/llamacpp). - -**Step 3 (make sure you have MongoDb running locally):** - -```bash -docker run -d -p 27017:27017 --name mongo-chatui mongo:latest -``` - -Read more [here](https://github.com/huggingface/chat-ui?tab=Readme-ov-file#database). - -**Step 4 (start chat-ui):** - -```bash -git clone https://github.com/huggingface/chat-ui -cd chat-ui -npm install -npm run dev -- --open -``` - -Read more [here](https://github.com/huggingface/chat-ui?tab=readme-ov-file#launch). - -
- - -
diff --git a/docs/source/installation/docker.md b/docs/source/installation/docker.md deleted file mode 100644 index 5b7e3b70884a2b5a6496cf0f8ba582dc7dbbf27b..0000000000000000000000000000000000000000 --- a/docs/source/installation/docker.md +++ /dev/null @@ -1,11 +0,0 @@ -# Running on Docker - -Pre-built docker images are provided with and without MongoDB built in. Refer to the [configuration section](../configuration/overview) for env variables that must be provided. We recommend using the `--env-file` option to avoid leaking secrets into your shell history. - -```bash -# Without built-in DB -docker run -p 3000:3000 --env-file .env.local --name chat-ui ghcr.io/huggingface/chat-ui - -# With built-in DB -docker run -p 3000:3000 --env-file .env.local -v chat-ui:/data --name chat-ui ghcr.io/huggingface/chat-ui-db -``` diff --git a/docs/source/installation/helm.md b/docs/source/installation/helm.md deleted file mode 100644 index 789e3695f515d98182ca18e2a58f5996acd70b38..0000000000000000000000000000000000000000 --- a/docs/source/installation/helm.md +++ /dev/null @@ -1,35 +0,0 @@ -# Helm - - - -**We highly discourage using the chart**. The Helm chart is a work in progress and should be considered unstable. Breaking changes to the chart may be pushed without migration guides or notice. Contributions welcome! - - - -For installation on Kubernetes, you may use the helm chart in `/chart`. Please note that no chart repository has been setup, so you'll need to clone the repository and install the chart by path. The production values may be found at `chart/env/prod.yaml`. - -**Example values.yaml** - -```yaml -replicas: 1 - -domain: example.com - -service: - type: ClusterIP - -resources: - requests: - cpu: 100m - memory: 2Gi - limits: - # Recommended to use large limits when web search is enabled - cpu: "4" - memory: 6Gi - -envVars: - MONGODB_URL: mongodb://chat-ui-mongo:27017 - # Ensure that your values.yaml will not leak anywhere - # PRs welcome for a chart rework with envFrom support! - HF_TOKEN: secret_token -``` diff --git a/docs/source/installation/local.md b/docs/source/installation/local.md deleted file mode 100644 index f176d349bbb75522dbc1e14b354239882e31d859..0000000000000000000000000000000000000000 --- a/docs/source/installation/local.md +++ /dev/null @@ -1,34 +0,0 @@ -# Running Locally - -You may start an instance locally for non-production use cases. For production use cases, please see the other installation options. - -## Configuration - -The default config for Chat UI is stored in the `.env` file. You will need to override some values to get Chat UI to run locally. Start by creating a `.env.local` file in the root of the repository as per the [configuration section](../configuration/overview). The bare minimum config you need to get Chat UI to run locally is the following: - -```ini -MONGODB_URL= -HF_TOKEN= # find your token at hf.co/settings/token -``` - -## Database - -The chat history is stored in a MongoDB instance, and having a DB instance available is needed for Chat UI to work. - -You can use a local MongoDB instance. The easiest way is to spin one up using docker with persistence: - -```bash -docker run -d -p 27017:27017 -v mongo-chat-ui:/data --name mongo-chat-ui mongo:latest -``` - -In which case the url of your DB will be `MONGODB_URL=mongodb://localhost:27017`. - -Alternatively, you can use a [free MongoDB Atlas](https://www.mongodb.com/pricing) instance for this, Chat UI should fit comfortably within their free tier. After which you can set the `MONGODB_URL` variable in `.env.local` to match your instance. - -## Starting the server - -```bash -npm ci # install dependencies -npm run build # build the project -npm run preview -- --open # start the server with & open your instance at http://localhost:4173 -``` diff --git a/docs/source/installation/spaces.md b/docs/source/installation/spaces.md deleted file mode 100644 index 54341744b7b5b7305a37536dbb09e29871782bc7..0000000000000000000000000000000000000000 --- a/docs/source/installation/spaces.md +++ /dev/null @@ -1,9 +0,0 @@ -# Running on Huggingface Spaces - -If you don't want to configure, setup, and launch your own Chat UI yourself, you can use this option as a fast deploy alternative. - -You can deploy your own customized Chat UI instance with any supported [LLM](https://huggingface.co/models?pipeline_tag=text-generation) of your choice on [Hugging Face Spaces](https://huggingface.co/spaces). To do so, use the chat-ui template [available here](https://huggingface.co/new-space?template=huggingchat/chat-ui-template). - -Set `HF_TOKEN` in [Space secrets](https://huggingface.co/docs/hub/spaces-overview#managing-secrets-and-environment-variables) to deploy a model with gated access or a model in a private repository. It's also compatible with [Inference for PROs](https://huggingface.co/blog/inference-pro) curated list of powerful models with higher rate limits. Make sure to create your personal token first in your [User Access Tokens settings](https://huggingface.co/settings/tokens). - -Read the full tutorial [here](https://huggingface.co/docs/hub/spaces-sdks-docker-chatui#chatui-on-spaces). diff --git a/package-lock.json b/package-lock.json index 4815435daccba061111251c1c2dadcfc9e464a06..ba7406c0a0ee37a40ad780dda8640e0a14a73b7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,59 +1,41 @@ { "name": "chat-ui", - "version": "0.10.0", + "version": "0.20.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "chat-ui", - "version": "0.10.0", + "version": "0.20.0", "dependencies": { - "@aws-sdk/credential-providers": "^3.592.0", - "@cliqz/adblocker-playwright": "^1.34.0", "@elysiajs/swagger": "^1.3.0", "@gradio/client": "^1.8.0", "@huggingface/hub": "^2.2.0", "@huggingface/inference": "^3.12.1", - "@huggingface/mcp-client": "^0.1.1", - "@huggingface/tasks": "^0.19.1", - "@huggingface/transformers": "^3.1.1", "@iconify-json/bi": "^1.1.21", - "@playwright/browser-chromium": "^1.52.0", "@resvg/resvg-js": "^2.6.2", "autoprefixer": "^10.4.14", - "aws-sigv4-fetch": "^4.0.1", - "aws4": "^1.13.0", "date-fns": "^2.29.3", "dotenv": "^16.5.0", - "express": "^4.21.2", "file-type": "^21.0.0", - "google-auth-library": "^9.13.0", "handlebars": "^4.7.8", "highlight.js": "^11.7.0", "husky": "^9.0.11", - "image-size": "^1.2.1", "ip-address": "^9.0.5", - "jose": "^5.3.0", - "jsdom": "^22.0.0", "json5": "^2.2.3", - "jsonpath": "^1.1.1", "katex": "^0.16.21", "lint-staged": "^15.2.7", "marked": "^12.0.1", "mongodb": "^5.8.0", "nanoid": "^5.0.9", - "natural": "^8.1.0", + "openai": "^4.44.0", "openid-client": "^5.4.2", "parquetjs": "^0.11.2", "pino": "^9.0.0", "pino-pretty": "^11.0.0", - "playwright": "^1.52.0", "postcss": "^8.4.31", - "saslprep": "^1.0.3", "satori": "^0.10.11", "satori-html": "^0.3.2", - "sbd": "^1.0.19", - "serpapi": "^1.1.1", "sharp": "^0.33.4", "tailwind-scrollbar": "^3.0.0", "tailwindcss": "^3.4.0", @@ -62,9 +44,7 @@ "zod": "^3.22.3" }, "devDependencies": { - "@elysiajs/cors": "^1.3.3", "@elysiajs/eden": "^1.3.2", - "@elysiajs/node": "^1.2.6", "@faker-js/faker": "^8.4.1", "@iconify-json/carbon": "^1.1.16", "@iconify-json/eos-icons": "^1.1.6", @@ -73,17 +53,12 @@ "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/typography": "^0.5.9", "@types/dompurify": "^3.0.5", - "@types/express": "^4.17.21", - "@types/fs-extra": "^11.0.4", "@types/js-yaml": "^4.0.9", - "@types/jsdom": "^21.1.1", - "@types/jsonpath": "^0.2.4", "@types/katex": "^0.16.7", "@types/mime-types": "^2.1.4", "@types/minimist": "^1.2.5", "@types/node": "^22.1.0", "@types/parquetjs": "^0.10.3", - "@types/sbd": "^1.0.5", "@types/uuid": "^9.0.8", "@types/yazl": "^3.3.0", "@typescript-eslint/eslint-plugin": "^6.x", @@ -94,23 +69,19 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.45.1", - "fs-extra": "^11.3.0", + "fs-extra": "^11.3.1", "isomorphic-dompurify": "^2.13.0", "js-yaml": "^4.1.0", - "jsonrepair": "^3.12.0", "minimist": "^1.2.8", "mongodb-memory-server": "^10.1.2", - "node-llama-cpp": "^3.6.0", "prettier": "^3.5.3", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.6.11", - "prom-client": "^15.1.2", "sade": "^1.8.1", "superjson": "^2.2.2", "svelte": "^5.33.3", "svelte-check": "^4.0.0", "svelte-gestures": "^5.1.3", - "ts-node": "^10.9.1", "tslib": "^2.4.1", "typescript": "^5.5.0", "unplugin-icons": "^0.16.1", @@ -118,16 +89,6 @@ "vite-node": "^3.0.9", "vitest": "^3.1.4", "yazl": "^3.3.1" - }, - "optionalDependencies": { - "@anthropic-ai/sdk": "^0.32.1", - "@anthropic-ai/vertex-sdk": "^0.4.1", - "@aws-sdk/client-bedrock-runtime": "^3.631.0", - "@google-cloud/vertexai": "^1.1.0", - "@google/generative-ai": "^0.24.0", - "aws4fetch": "^1.0.17", - "cohere-ai": "^7.9.0", - "openai": "^4.44.0" } }, "node_modules/@alloc/quick-lru": { @@ -282,50 +243,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@anthropic-ai/sdk": { - "version": "0.32.1", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.32.1.tgz", - "integrity": "sha512-U9JwTrDvdQ9iWuABVsMLj8nJVwAyQz6QXvgLsVhryhCEPkLsbcP/MXxm+jYcAwLoV8ESbaTTjnD4kuAFa+Hyjg==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7" - } - }, - "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { - "version": "18.19.111", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.111.tgz", - "integrity": "sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==", - "license": "MIT", - "optional": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@anthropic-ai/sdk/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT", - "optional": true - }, - "node_modules/@anthropic-ai/vertex-sdk": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@anthropic-ai/vertex-sdk/-/vertex-sdk-0.4.3.tgz", - "integrity": "sha512-2Uef0C5P2Hx+T88RnUSRA3u4aZqmqnrRSOb2N64ozgKPiSUPTM5JlggAq2b32yWMj5d3MLYa6spJXKMmHXOcoA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@anthropic-ai/sdk": ">=0.14 <1", - "google-auth-library": "^9.4.2" - } - }, "node_modules/@asamuzakjp/css-color": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", @@ -347,9912 +264,4411 @@ "dev": true, "license": "ISC" }, - "node_modules/@aws-crypto/crc32": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", - "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "peer": true, "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-crypto/supports-web-crypto": "^5.2.0", - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" + "node": ">=6.9.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "peer": true, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "license": "ISC", "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" + "cookie": "^0.7.2" } }, - "node_modules/@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">= 0.6" } }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", - "license": "Apache-2.0", + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "license": "ISC", "dependencies": { - "tslib": "^2.6.2" + "statuses": "^2.0.1" } }, - "node_modules/@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", - "license": "Apache-2.0", + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "license": "ISC", "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" + "node": ">=18" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.825.0.tgz", - "integrity": "sha512-tIo+fc6CeLmjeMvkS1zNMk2DUkmcxVeY7xgd9lMhhgwy2iRUKeIIp527ZLukI/wQT59QBoeWkUOgM38Ww8k7rg==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", + "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/credential-provider-node": "3.825.0", - "@aws-sdk/eventstream-handler-node": "3.821.0", - "@aws-sdk/middleware-eventstream": "3.821.0", - "@aws-sdk/middleware-host-header": "3.821.0", - "@aws-sdk/middleware-logger": "3.821.0", - "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.825.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/eventstream-serde-browser": "^4.0.4", - "@smithy/eventstream-serde-config-resolver": "^4.1.2", - "@smithy/eventstream-serde-node": "^4.0.4", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.10", - "@smithy/middleware-retry": "^4.1.11", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.18", - "@smithy/util-defaults-mode-node": "^4.0.18", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "@smithy/util-stream": "^4.2.2", - "@smithy/util-utf8": "^4.0.0", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" }, "engines": { - "node": ">=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.825.0.tgz", - "integrity": "sha512-FYXwkFmOYMiUYbLuzEl9by4Ks+bidXiHQwRXaDijuzkjM3B/Dd8noIxlvQCdxd6Ji7ofXcXTfNpVqN0U0JF9ag==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/credential-provider-node": "3.825.0", - "@aws-sdk/middleware-host-header": "3.821.0", - "@aws-sdk/middleware-logger": "3.821.0", - "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.825.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.10", - "@smithy/middleware-retry": "^4.1.11", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.18", - "@smithy/util-defaults-mode-node": "^4.0.18", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sagemaker": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sagemaker/-/client-sagemaker-3.825.0.tgz", - "integrity": "sha512-w8niH0WRxnuzHvDu///HBxLJ41CoDXipHDVE4pMDlV506Dl2aGN824ON/H6gbFIqTMsSm6vVu2expabC19YPug==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/credential-provider-node": "3.825.0", - "@aws-sdk/middleware-host-header": "3.821.0", - "@aws-sdk/middleware-logger": "3.821.0", - "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.825.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.10", - "@smithy/middleware-retry": "^4.1.11", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.18", - "@smithy/util-defaults-mode-node": "^4.0.18", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.5", - "@types/uuid": "^9.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" + "node": ">=18" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@aws-sdk/client-sagemaker/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.825.0.tgz", - "integrity": "sha512-U0J2RQUsxiin+uEYR8atMByojuvhtWvvEVSD2MhSUUnCa7BSu/H+4SbREBvnGDJ2nezrYh59bkSQBlp9c3Z9gg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/middleware-host-header": "3.821.0", - "@aws-sdk/middleware-logger": "3.821.0", - "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.825.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.10", - "@smithy/middleware-retry": "^4.1.11", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.18", - "@smithy/util-defaults-mode-node": "^4.0.18", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/core": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.825.0.tgz", - "integrity": "sha512-UsdK6l62skh6mqY/La4xvehNj5sUl/eZ2N+8mNTHZKW4U+tiRESdrw1t/Z3r/NUAu7Tbmp+DHbUu+5K1BBY6YQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.5.2", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "node_modules/@elysiajs/eden": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@elysiajs/eden/-/eden-1.3.2.tgz", + "integrity": "sha512-0bCU5DO7J7hQfS2y3O3399GtoxMWRDMgQNMTHOnf70/F2nF8SwGHvzwh3+wO62Ko5FMF7EYqTN9Csw/g/Q7qwg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "elysia": ">= 1.3.0" } }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.825.0.tgz", - "integrity": "sha512-TDqaakIsUeYbShBCt5F8wgjLOkq5d16JwhCgHCuM/kbwxeLmQkJWDNlui1Z32MLCIWRBilsFCr+aNG6tlj9siQ==", - "license": "Apache-2.0", + "node_modules/@elysiajs/swagger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@elysiajs/swagger/-/swagger-1.3.0.tgz", + "integrity": "sha512-0fo3FWkDRPNYpowJvLz3jBHe9bFe6gruZUyf+feKvUEEMG9ZHptO1jolSoPE0ffFw1BgN1/wMsP19p4GRXKdfg==", + "license": "MIT", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@scalar/themes": "^0.9.52", + "@scalar/types": "^0.0.12", + "openapi-types": "^12.1.3", + "pathe": "^1.1.2" }, - "engines": { - "node": ">=18.0.0" + "peerDependencies": { + "elysia": ">= 1.3.0" } }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.825.0.tgz", - "integrity": "sha512-Ptkbhj4K1un+GIz5fmTLVCFtWv9rcbaCLgdZszudo/ZqLP0QzAoACADGYFFkPGYr2o51COKkgKPhHWl7FNEq6A==", - "license": "Apache-2.0", + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "license": "MIT", + "optional": true, "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "tslib": "^2.4.0" } }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.825.0.tgz", - "integrity": "sha512-r0V0rlNCjnFLfYfUqP6TlwAo+YgWxIkrgUb/K6mV2XCBElbFZlc9oPzMOJCmHF/+D6S60FLlMC9AnFopnEZ3/A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.825.0.tgz", - "integrity": "sha512-HDYopAiIGTLLhybI8jEuKGWdVUnKkkotwXHwvu8ttL5qgs13A6a/iWiREe71fmYH2fGT2URJE9+xeHa2oxohyQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/credential-provider-env": "3.825.0", - "@aws-sdk/credential-provider-http": "3.825.0", - "@aws-sdk/credential-provider-process": "3.825.0", - "@aws-sdk/credential-provider-sso": "3.825.0", - "@aws-sdk/credential-provider-web-identity": "3.825.0", - "@aws-sdk/nested-clients": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.825.0.tgz", - "integrity": "sha512-qWMrrUgWFQN7nkMdQYzWF/Z/fhUctCjwTQQD/qNSs42qt3sxmC00SZcqwPn9N8S9R/hLmu5z6fefVF4o20nGng==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.825.0", - "@aws-sdk/credential-provider-http": "3.825.0", - "@aws-sdk/credential-provider-ini": "3.825.0", - "@aws-sdk/credential-provider-process": "3.825.0", - "@aws-sdk/credential-provider-sso": "3.825.0", - "@aws-sdk/credential-provider-web-identity": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.825.0.tgz", - "integrity": "sha512-QQoOBQAXuBfD6BCg61Hl5EkdrLyFSQCNRHVLjAO5WYQGyiPb9iTZPqo9sPwyOnCMpZE1k2EOwQ+FsnZh0xSa3Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.825.0.tgz", - "integrity": "sha512-ppwsN8tuwwJKvNnllkrhIx7AQv4r5uiNf5FTIkyeJ+3p67wgJeJye+0SP64IEkdmG7YxCaU2YkdSvyHud+D5og==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-sso": "3.825.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/token-providers": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.825.0.tgz", - "integrity": "sha512-cyL5xHqtvBUpflkmdQSkvjD/t+Dl/ZSXvPnc9KF79xDpuraZ5tFP1l0B6rIEu7dUzUh8XG+7m2CZ6TEs6QU33Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/nested-clients": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/credential-providers": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.825.0.tgz", - "integrity": "sha512-V4AaXB3oH+1lQS9lMp6+Iu3TPETdqVCktiqop3CknrjlYmtISt/vwcQ6GLWQskm1lsfewlfIsERwu5FDbHokEQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.825.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/credential-provider-cognito-identity": "3.825.0", - "@aws-sdk/credential-provider-env": "3.825.0", - "@aws-sdk/credential-provider-http": "3.825.0", - "@aws-sdk/credential-provider-ini": "3.825.0", - "@aws-sdk/credential-provider-node": "3.825.0", - "@aws-sdk/credential-provider-process": "3.825.0", - "@aws-sdk/credential-provider-sso": "3.825.0", - "@aws-sdk/credential-provider-web-identity": "3.825.0", - "@aws-sdk/nested-clients": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.821.0.tgz", - "integrity": "sha512-JqmzOCAnd9pUnmbrqXIbyBUxjw/UAfXAu8KAsE/4SveUIvyYRbYSTfCoPq6nnNJQpBtdEFLkjvBnHKBcInDwkg==", - "license": "Apache-2.0", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/eventstream-codec": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "os": [ + "freebsd" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/middleware-eventstream": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.821.0.tgz", - "integrity": "sha512-L+qud1uX1hX7MpRy564dFj4/5sDRKVLToiydvgRy6Rc3pwsVhRpm6/2djMVgDsFI3sYd+JoeTFjEypkoV3LE5Q==", - "license": "Apache-2.0", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.821.0.tgz", - "integrity": "sha512-xSMR+sopSeWGx5/4pAGhhfMvGBHioVBbqGvDs6pG64xfNwM5vq5s5v6D04e2i+uSTj4qGa71dLUs5I0UzAK3sw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.821.0.tgz", - "integrity": "sha512-0cvI0ipf2tGx7fXYEEN5fBeZDz2RnHyb9xftSgUsEq7NBxjV0yTZfLJw6Za5rjE6snC80dRN8+bTNR1tuG89zA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.821.0.tgz", - "integrity": "sha512-efmaifbhBoqKG3bAoEfDdcM8hn1psF+4qa7ykWuYmfmah59JBeqHLfz5W9m9JoTwoKPkFcVLWZxnyZzAnVBOIg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.825.0.tgz", - "integrity": "sha512-3ZZOPU3GE5cqKl6VFDwiL8KIvlrrQJ4rgYkeiF+m5kA0eXV2xFOwoLgm3AmPB+6kfo9HQ0N74KKJV0teS5nO6Q==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@smithy/core": "^3.5.2", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.825.0.tgz", - "integrity": "sha512-OuV2pypFAv52Lty8eXWVWyyOywVmMAsgH6Gq3SA06pHEtcE+ghVIW9ByegecyfMRUpedAiovARKNy0pfGX05Pg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.825.0", - "@aws-sdk/middleware-host-header": "3.821.0", - "@aws-sdk/middleware-logger": "3.821.0", - "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.825.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.2", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.10", - "@smithy/middleware-retry": "^4.1.11", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.2", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.18", - "@smithy/util-defaults-mode-node": "^4.0.18", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/protocol-http": { - "version": "3.374.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.374.0.tgz", - "integrity": "sha512-9WpRUbINdGroV3HiZZIBoJvL2ndoWk39OfwxWs2otxByppJZNN14bg/lvCx5e8ggHUti7IBk5rb0nqQZ4m05pg==", - "deprecated": "This package has moved to @smithy/protocol-http", - "license": "Apache-2.0", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@smithy/protocol-http": "^1.1.0", - "tslib": "^2.5.0" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/protocol-http/node_modules/@smithy/protocol-http": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.2.0.tgz", - "integrity": "sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q==", - "license": "Apache-2.0", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@smithy/types": "^1.2.0", - "tslib": "^2.5.0" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/protocol-http/node_modules/@smithy/types": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", - "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", - "license": "Apache-2.0", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "tslib": "^2.5.0" - }, + "os": [ + "linux" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.821.0.tgz", - "integrity": "sha512-t8og+lRCIIy5nlId0bScNpCkif8sc0LhmtaKsbm0ZPm3sCa/WhCbSZibjbZ28FNjVCV+p0D9RYZx0VDDbtWyjw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4": { - "version": "3.374.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.374.0.tgz", - "integrity": "sha512-2xLJvSdzcZZAg0lsDLUAuSQuihzK0dcxIK7WmfuJeF7DGKJFmp9czQmz5f3qiDz6IDQzvgK1M9vtJSVCslJbyQ==", - "deprecated": "This package has moved to @smithy/signature-v4", - "license": "Apache-2.0", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@smithy/signature-v4": "^1.0.1", - "tslib": "^2.5.0" - }, + "os": [ + "netbsd" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", - "license": "Apache-2.0", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@aws-crypto/crc32/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD", - "optional": true - }, - "node_modules/@aws-sdk/signature-v4/node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "license": "Apache-2.0", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@aws-crypto/util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD", - "optional": true - }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/eventstream-codec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.1.0.tgz", - "integrity": "sha512-3tEbUb8t8an226jKB6V/Q2XU/J53lCwCzULuBPEaF4JjSh+FlCMp7TmogE/Aij5J9DwlsZ4VAD/IRDuQ/0ZtMw==", - "license": "Apache-2.0", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^1.2.0", - "@smithy/util-hex-encoding": "^1.1.0", - "tslib": "^2.5.0" + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/is-array-buffer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.1.0.tgz", - "integrity": "sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ==", - "license": "Apache-2.0", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "tslib": "^2.5.0" - }, + "os": [ + "win32" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/signature-v4": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.1.0.tgz", - "integrity": "sha512-fDo3m7YqXBs7neciOePPd/X9LPm5QLlDMdIC4m1H6dgNLnXfLMFNIxEfPyohGA8VW9Wn4X8lygnPSGxDZSmp0Q==", - "license": "Apache-2.0", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", "optional": true, - "dependencies": { - "@smithy/eventstream-codec": "^1.1.0", - "@smithy/is-array-buffer": "^1.1.0", - "@smithy/types": "^1.2.0", - "@smithy/util-hex-encoding": "^1.1.0", - "@smithy/util-middleware": "^1.1.0", - "@smithy/util-uri-escape": "^1.1.0", - "@smithy/util-utf8": "^1.1.0", - "tslib": "^2.5.0" - }, + "os": [ + "win32" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/types": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", - "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", - "license": "Apache-2.0", + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "tslib": "^2.5.0" - }, + "os": [ + "win32" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/util-buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.1.0.tgz", - "integrity": "sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", "dependencies": { - "@smithy/is-array-buffer": "^1.1.0", - "tslib": "^2.5.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=14.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/util-hex-encoding": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.1.0.tgz", - "integrity": "sha512-7UtIE9eH0u41zpB60Jzr0oNCQ3hMJUabMcKRUVjmyHTXiWDE4vjSqN6qlih7rCNeKGbioS7f/y2Jgym4QZcKFg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.5.0" - }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/util-middleware": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.1.0.tgz", - "integrity": "sha512-6hhckcBqVgjWAqLy2vqlPZ3rfxLDhFWEmM7oLh2POGvsi7j0tHkbN7w4DFhuBExVJAbJ/qqxqZdRY6Fu7/OezQ==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.5.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=14.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/util-uri-escape": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz", - "integrity": "sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/util-utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.1.0.tgz", - "integrity": "sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "@smithy/util-buffer-from": "^1.1.0", - "tslib": "^2.5.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=14.0.0" + "node": "*" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.825.0.tgz", - "integrity": "sha512-a3HbF6h1Gq2vA+mGlxFe3op65wNK6dBRmp3GFwsPVQ+OFTbZJi86FCljMfBrv+BGYUkp503/IPC49wuRHOdcZA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.825.0", - "@aws-sdk/nested-clients": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@aws-sdk/types": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.821.0.tgz", - "integrity": "sha512-Znroqdai1a90TlxGaJ+FK1lwC0fHpo97Xjsp5UKGR5JODYm7f9+/fF17ebO1KdoBr/Rm0UIFiF5VmI8ts9F1eA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, + "node_modules/@faker-js/faker": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.821.0.tgz", - "integrity": "sha512-Uknt/zUZnLE76zaAAPEayOeF5/4IZ2puTFXvcSCWHsi9m3tqbb9UozlnlVqvCZLCRWfQryZQoG2W4XSS3qgk5A==", - "license": "Apache-2.0", + "node_modules/@gradio/client": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.15.1.tgz", + "integrity": "sha512-9WcemR708HYsyJgeP0l07jzGw8wPLVOUofaa9/ZeHSkeVnOXAIOfURxWHlP3rgpX3/1YDVZP5hs6NxyXhkV/gQ==", + "license": "ISC", "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/types": "^4.3.1", - "@smithy/util-endpoints": "^3.0.6", - "tslib": "^2.6.2" + "@types/eventsource": "^1.1.15", + "bufferutil": "^4.0.7", + "eventsource": "^2.0.2", + "fetch-event-stream": "^0.1.5", + "msw": "^2.2.1", + "semiver": "^1.1.0", + "textlinestream": "^1.1.1", + "typescript": "^5.0.0", + "ws": "^8.13.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz", - "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==", - "license": "Apache-2.0", + "node_modules/@huggingface/hub": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@huggingface/hub/-/hub-2.2.0.tgz", + "integrity": "sha512-G+VS1eMp80KovIHBlsiEigS6I6qmI4j+VQ1UZ8CaXT+pw2A7tj6e/crfxFdKNE2uOK5oQkRFiCBJykMwrWQ8OA==", + "license": "MIT", "dependencies": { - "tslib": "^2.6.2" + "@huggingface/tasks": "^0.19.11" + }, + "bin": { + "hfjs": "dist/cli.js" }, "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.821.0.tgz", - "integrity": "sha512-irWZHyM0Jr1xhC+38OuZ7JB6OXMLPZlj48thElpsO1ZSLRkLZx5+I7VV6k3sp2yZ7BYbKz/G2ojSv4wdm7XTLw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.821.0", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" + "node": ">=18" } }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.825.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.825.0.tgz", - "integrity": "sha512-RfB0w9YJSsFGsbrzOQ1VE2O4NwR6gxelUvmz8PzuerPCg4iD4JW7hSCmnoAEi51Xnq0bNeCsnhzXJzIlPe04jA==", - "license": "Apache-2.0", + "node_modules/@huggingface/inference": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-3.15.0.tgz", + "integrity": "sha512-C+Adt4fu4ztlq0Al9EOgEdK5Hl8ebV1eoDEWegJPdAJ97U8A1aqBbl1Sp4S4+wIy3nLApTrtcLuoizGZmLtDMA==", + "license": "MIT", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.825.0", - "@aws-sdk/types": "3.821.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@huggingface/jinja": "^0.5.0", + "@huggingface/tasks": "^0.19.9" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.3.1" + "node_modules/@huggingface/jinja": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.0.tgz", + "integrity": "sha512-Ptc03/jGRiYRoi0bUYKZ14MkDslsBRT24oxmsvUlfYrvQMldrxCevhPnT+hfX8awKTT8/f/0ZBBWldoeAcMHdQ==", + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", - "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", + "node_modules/@huggingface/tasks": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.19.11.tgz", + "integrity": "sha512-oBhSgVlg7Pp643MsH8BiI3OAXIMJNxdSiMtv4mApRZV8dmAz8oasKhg6CVKIplO7vAO7F6dkmMn4bYM64I2A9w==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=18.0.0" + "node": ">=10.10.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "license": "MIT", - "peer": true, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=6.9.0" + "node": "*" } }, - "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", - "license": "MIT", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.9.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@bundled-es-modules/cookie": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", - "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", - "license": "ISC", - "dependencies": { - "cookie": "^0.7.2" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/@iconify-json/bi": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@iconify-json/bi/-/bi-1.2.4.tgz", + "integrity": "sha512-ipD8nm86ovjgXGEJj/B5oSJGaEIsGgzrKqNT1ei66nRExzK6Mgh4an/efG30Xtvp2eQjz9eWN5kHmadbnjUmzw==", "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@bundled-es-modules/statuses": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", - "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", - "license": "ISC", "dependencies": { - "statuses": "^2.0.1" + "@iconify/types": "*" } }, - "node_modules/@bundled-es-modules/tough-cookie": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", - "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", - "license": "ISC", + "node_modules/@iconify-json/carbon": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@iconify-json/carbon/-/carbon-1.2.9.tgz", + "integrity": "sha512-RyeSAuFTzhs1GX4yrzVEKEbNQGt95p9zMR4S2F63vbThtNoUr5OKwaWbhO/GbHQCSgdbKuZv2ApAOsY2fLxLbQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@types/tough-cookie": "^4.0.5", - "tough-cookie": "^4.1.4" + "@iconify/types": "*" } }, - "node_modules/@cliqz/adblocker": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/@cliqz/adblocker/-/adblocker-1.34.0.tgz", - "integrity": "sha512-d7TeUl5t+TOMJe7/CRYtf+x6hbd8N25DtH7guQTIjjr3AFVortxiAIgNejGvVqy0by4eNByw+oVil15oqxz2Eg==", - "deprecated": "This project has been renamed to @ghostery/adblocker. Install using @ghostery/adblocker instead", - "license": "MPL-2.0", - "dependencies": { - "@cliqz/adblocker-content": "^1.34.0", - "@cliqz/adblocker-extended-selectors": "^1.34.0", - "@remusao/guess-url-type": "^1.3.0", - "@remusao/small": "^1.2.1", - "@remusao/smaz": "^1.9.1", - "@types/chrome": "^0.0.278", - "@types/firefox-webext-browser": "^120.0.0", - "tldts-experimental": "^6.0.14" - } - }, - "node_modules/@cliqz/adblocker-content": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/@cliqz/adblocker-content/-/adblocker-content-1.34.0.tgz", - "integrity": "sha512-5LcV8UZv49RWwtpom9ve4TxJIFKd+bjT59tS/2Z2c22Qxx5CW1ncO/T+ybzk31z422XplQfd0ZE6gMGGKs3EMg==", - "deprecated": "This project has been renamed to @ghostery/adblocker-content. Install using @ghostery/adblocker-content instead", - "license": "MPL-2.0", + "node_modules/@iconify-json/eos-icons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@iconify-json/eos-icons/-/eos-icons-1.2.2.tgz", + "integrity": "sha512-kYfV1WfgiHDbWdG9JEbV1K77MvksRmo9KIM4VjtYFMnF8pKqTv4MoLIOdCD2lbRlhBZspxr1GKde5Z/LYqz3Qw==", + "dev": true, + "license": "MIT", "dependencies": { - "@cliqz/adblocker-extended-selectors": "^1.34.0" + "@iconify/types": "*" } }, - "node_modules/@cliqz/adblocker-extended-selectors": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.34.0.tgz", - "integrity": "sha512-lNrgdUPpsBWHjrwXy2+Z5nX/Gy5YAvNwFMLqkeMdjzrybwPIalJJN2e+YtkS1I6mVmOMNppF5cv692OAVoI74g==", - "deprecated": "This project has been renamed to @ghostery/adblocker-extended-selectors. Install using @ghostery/adblocker-extended-selectors instead", - "license": "MPL-2.0" - }, - "node_modules/@cliqz/adblocker-playwright": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/@cliqz/adblocker-playwright/-/adblocker-playwright-1.34.0.tgz", - "integrity": "sha512-YMedgiz9LR5VW6ocKoC1P3cSsj1T9Ibinp14beXxvpydMmneX+fQB0Hq4bqWvuuL3CNl7fENMgiCDDMTgMLqww==", - "deprecated": "This project has been renamed to @ghostery/adblocker-playwright. Install using @ghostery/adblocker-playwright instead", - "license": "MPL-2.0", - "dependencies": { - "@cliqz/adblocker": "^1.34.0", - "@cliqz/adblocker-content": "^1.34.0", - "tldts-experimental": "^6.0.14" - }, - "peerDependencies": { - "playwright": "^1.x" - } + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "node_modules/@iconify/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" + "@antfu/install-pkg": "^1.0.0", + "@antfu/utils": "^8.1.0", + "@iconify/types": "^2.0.0", + "debug": "^4.4.0", + "globals": "^15.14.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.0.0", + "mlly": "^1.7.4" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "node_modules/@iconify/utils/node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "node_modules/@iconify/utils/node_modules/@antfu/utils": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", + "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "node_modules/@iconify/utils/node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/color-helpers": "^5.0.2", - "@csstools/css-calc": "^2.1.4" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } + "license": "MIT" }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "node_modules/@iconify/utils/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", "engines": { "node": ">=18" }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "node_modules/@iconify/utils/node_modules/local-pkg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", + "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.0.1", + "quansync": "^0.2.8" + }, "engines": { - "node": ">=18" - } - }, - "node_modules/@elysiajs/cors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@elysiajs/cors/-/cors-1.3.3.tgz", - "integrity": "sha512-mYIU6PyMM6xIJuj7d27Vt0/wuzVKIEnFPjcvlkyd7t/m9xspAG37cwNjFxVOnyvY43oOd2I/oW2DB85utXpA2Q==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "elysia": ">= 1.3.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@elysiajs/eden": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@elysiajs/eden/-/eden-1.3.2.tgz", - "integrity": "sha512-0bCU5DO7J7hQfS2y3O3399GtoxMWRDMgQNMTHOnf70/F2nF8SwGHvzwh3+wO62Ko5FMF7EYqTN9Csw/g/Q7qwg==", + "node_modules/@iconify/utils/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "license": "MIT", - "peerDependencies": { - "elysia": ">= 1.3.0" - } + "license": "MIT" }, - "node_modules/@elysiajs/node": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@elysiajs/node/-/node-1.3.0.tgz", - "integrity": "sha512-AA9rnL/FOBklxtJjFpUDBVZLuiKddDaV1KgnKawHzj5VgN99SzE+V0h1MOhp+8jlo2KQQJO/3aD3upyGgrfohQ==", + "node_modules/@iconify/utils/node_modules/pkg-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", + "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", "dev": true, "license": "MIT", "dependencies": { - "@hono/node-server": "^1.14.3" - }, - "peerDependencies": { - "elysia": ">= 1.3.3" - } - }, - "node_modules/@elysiajs/swagger": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@elysiajs/swagger/-/swagger-1.3.0.tgz", - "integrity": "sha512-0fo3FWkDRPNYpowJvLz3jBHe9bFe6gruZUyf+feKvUEEMG9ZHptO1jolSoPE0ffFw1BgN1/wMsP19p4GRXKdfg==", - "license": "MIT", - "dependencies": { - "@scalar/themes": "^0.9.52", - "@scalar/types": "^0.0.12", - "openapi-types": "^12.1.3", - "pathe": "^1.1.2" - }, - "peerDependencies": { - "elysia": ">= 1.3.0" + "confbox": "^0.2.1", + "exsolve": "^1.0.1", + "pathe": "^2.0.3" } }, - "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } + "node_modules/@iconify/utils/node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "dev": true, + "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ - "ppc64" + "arm64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "aix" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ - "arm" + "x64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "android" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ "x64" ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ - "x64" + "arm" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "darwin" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ - "x64" + "s390x" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ - "arm" + "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ - "ia32" + "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", "cpu": [ - "loong64" + "arm" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", "cpu": [ - "mips64el" + "arm64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", "cpu": [ - "ppc64" + "s390x" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ - "riscv64" + "x64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", "cpu": [ - "s390x" + "arm64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", "cpu": [ "x64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", "cpu": [ - "arm64" + "wasm32" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", "cpu": [ - "x64" + "ia32" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "openbsd" + "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", "cpu": [ "x64" ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", - "cpu": [ - "arm64" - ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", - "cpu": [ - "ia32" - ], + "node_modules/@inquirer/confirm": { + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.12.tgz", + "integrity": "sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@inquirer/core": "^10.1.13", + "@inquirer/type": "^3.0.7" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/core": { + "version": "10.1.13", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.13.tgz", + "integrity": "sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@inquirer/figures": "^1.0.12", + "@inquirer/type": "^3.0.7", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "dev": true, + "node_modules/@inquirer/core/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "type-fest": "^0.21.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/@inquirer/figures": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.12.tgz", + "integrity": "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==", + "license": "MIT", "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, + "node_modules/@inquirer/type": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.7.tgz", + "integrity": "sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==", "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@faker-js/faker": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", - "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/fakerjs" - } - ], - "license": "MIT", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0", - "npm": ">=6.14.13" + "node": ">=12" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/vertexai": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@google-cloud/vertexai/-/vertexai-1.10.0.tgz", - "integrity": "sha512-HqYqoivNtkq59po8m7KI0n+lWKdz4kabENncYQXZCX/hBWJfXtKAfR/2nUQsP+TwSfHKoA7zDL2RrJYIv/j3VQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "google-auth-library": "^9.1.0" + "node": ">=12" }, - "engines": { - "node": ">=18.0.0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@google/generative-ai": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.1.tgz", - "integrity": "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@gradio/client": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@gradio/client/-/client-1.15.1.tgz", - "integrity": "sha512-9WcemR708HYsyJgeP0l07jzGw8wPLVOUofaa9/ZeHSkeVnOXAIOfURxWHlP3rgpX3/1YDVZP5hs6NxyXhkV/gQ==", - "license": "ISC", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { - "@types/eventsource": "^1.1.15", - "bufferutil": "^4.0.7", - "eventsource": "^2.0.2", - "fetch-event-stream": "^0.1.5", - "msw": "^2.2.1", - "semiver": "^1.1.0", - "textlinestream": "^1.1.1", - "typescript": "^5.0.0", - "ws": "^8.13.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@hono/node-server": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.14.3.tgz", - "integrity": "sha512-KuDMwwghtFYSmIpr4WrKs1VpelTrptvJ+6x6mbUcZnFcc213cumTF5BdqfHyW93B19TNI4Vaev14vOI2a0Ie3w==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=18.14.1" + "node": ">=12" }, - "peerDependencies": { - "hono": "^4" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@huggingface/hub": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@huggingface/hub/-/hub-2.2.0.tgz", - "integrity": "sha512-G+VS1eMp80KovIHBlsiEigS6I6qmI4j+VQ1UZ8CaXT+pw2A7tj6e/crfxFdKNE2uOK5oQkRFiCBJykMwrWQ8OA==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", "dependencies": { - "@huggingface/tasks": "^0.19.11" - }, - "bin": { - "hfjs": "dist/cli.js" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@huggingface/inference": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-3.15.0.tgz", - "integrity": "sha512-C+Adt4fu4ztlq0Al9EOgEdK5Hl8ebV1eoDEWegJPdAJ97U8A1aqBbl1Sp4S4+wIy3nLApTrtcLuoizGZmLtDMA==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { - "@huggingface/jinja": "^0.5.0", - "@huggingface/tasks": "^0.19.9" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@huggingface/jinja": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.0.tgz", - "integrity": "sha512-Ptc03/jGRiYRoi0bUYKZ14MkDslsBRT24oxmsvUlfYrvQMldrxCevhPnT+hfX8awKTT8/f/0ZBBWldoeAcMHdQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@huggingface/mcp-client": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@huggingface/mcp-client/-/mcp-client-0.1.3.tgz", - "integrity": "sha512-oHYt2FcUXzI6kehMmXQBz4WqDPFl8sDbg4r64vYjI9MkVh6wOhNvQD7yWc2QHVoXTgUpEPLxFeaJlCqjvaN9KQ==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "license": "MIT", - "dependencies": { - "@huggingface/inference": "^3.11.0", - "@huggingface/tasks": "^0.19.1", - "@modelcontextprotocol/sdk": "^1.9.0" - }, - "bin": { - "tiny-agent": "dist/cli.js" - }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@huggingface/tasks": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.19.11.tgz", - "integrity": "sha512-oBhSgVlg7Pp643MsH8BiI3OAXIMJNxdSiMtv4mApRZV8dmAz8oasKhg6CVKIplO7vAO7F6dkmMn4bYM64I2A9w==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "license": "MIT" }, - "node_modules/@huggingface/transformers": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.5.2.tgz", - "integrity": "sha512-mfRXkmcL99+ibpjM++pvZmc2h3po8i1ZgSRI5Rtgh++P15GU0lY8UQteYt/w5V+GQw+Jpao93MoipcePzh3mKg==", - "license": "Apache-2.0", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { - "@huggingface/jinja": "^0.4.1", - "onnxruntime-node": "1.21.0", - "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", - "sharp": "^0.34.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@huggingface/transformers/node_modules/@huggingface/jinja": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.4.1.tgz", - "integrity": "sha512-3WXbMFaPkk03LRCM0z0sylmn8ddDm4ubjU7X+Hg4M2GOuMklwoGAFXp9V2keq7vltoB/c7McE5aHUVVddAewsw==", + "node_modules/@mongodb-js/saslprep": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.2.tgz", + "integrity": "sha512-EB0O3SCSNRUFk66iRCpI+cXzIjdswfCs7F6nOC3RAGJ7xr5YhaicvsRwJ9eyzYvYRlCSDUO/c7g4yNulxKC1WA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.38.7", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.38.7.tgz", + "integrity": "sha512-Jkb27iSn7JPdkqlTqKfhncFfnEZsIJVYxsFbUSWEkxdIPdsyngrhoDBk0/BGD2FQcRH99vlRrkHpNTyKqI+0/w==", "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, "engines": { "node": ">=18" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", - "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.1.0" + "engines": { + "node": ">= 8" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-darwin-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", - "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 8" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@resvg/resvg-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.2.tgz", + "integrity": "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==", + "license": "MPL-2.0", + "engines": { + "node": ">= 10" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.1.0" + "@resvg/resvg-js-android-arm-eabi": "2.6.2", + "@resvg/resvg-js-android-arm64": "2.6.2", + "@resvg/resvg-js-darwin-arm64": "2.6.2", + "@resvg/resvg-js-darwin-x64": "2.6.2", + "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", + "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", + "@resvg/resvg-js-linux-arm64-musl": "2.6.2", + "@resvg/resvg-js-linux-x64-gnu": "2.6.2", + "@resvg/resvg-js-linux-x64-musl": "2.6.2", + "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", + "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", + "@resvg/resvg-js-win32-x64-msvc": "2.6.2" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", - "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "node_modules/@resvg/resvg-js-android-arm-eabi": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.2.tgz", + "integrity": "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==", "cpu": [ - "arm64" + "arm" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ - "darwin" + "android" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", - "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "node_modules/@resvg/resvg-js-android-arm64": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.2.tgz", + "integrity": "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==", "cpu": [ - "x64" + "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ - "darwin" + "android" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", - "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "node_modules/@resvg/resvg-js-darwin-arm64": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.2.tgz", + "integrity": "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==", "cpu": [ - "arm" + "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ - "linux" + "darwin" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", - "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "node_modules/@resvg/resvg-js-darwin-x64": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.2.tgz", + "integrity": "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==", "cpu": [ - "arm64" + "x64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ - "linux" + "darwin" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", - "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "node_modules/@resvg/resvg-js-linux-arm-gnueabihf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.2.tgz", + "integrity": "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==", "cpu": [ - "s390x" + "arm" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", - "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "node_modules/@resvg/resvg-js-linux-arm64-gnu": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.2.tgz", + "integrity": "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==", "cpu": [ - "x64" + "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", - "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "node_modules/@resvg/resvg-js-linux-arm64-musl": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.2.tgz", + "integrity": "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==", "cpu": [ "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", - "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "node_modules/@resvg/resvg-js-linux-x64-gnu": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.2.tgz", + "integrity": "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==", "cpu": [ "x64" ], - "license": "LGPL-3.0-or-later", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-arm": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", - "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", + "node_modules/@resvg/resvg-js-linux-x64-musl": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.2.tgz", + "integrity": "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==", "cpu": [ - "arm" + "x64" ], - "license": "Apache-2.0", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0" + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", - "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", + "node_modules/@resvg/resvg-js-win32-arm64-msvc": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.2.tgz", + "integrity": "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==", "cpu": [ "arm64" ], - "license": "Apache-2.0", + "license": "MPL-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.1.0" + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-s390x": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", - "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", + "node_modules/@resvg/resvg-js-win32-ia32-msvc": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.2.tgz", + "integrity": "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==", "cpu": [ - "s390x" + "ia32" ], - "license": "Apache-2.0", + "license": "MPL-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.1.0" + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", - "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", + "node_modules/@resvg/resvg-js-win32-x64-msvc": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.2.tgz", + "integrity": "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==", "cpu": [ "x64" ], - "license": "Apache-2.0", + "license": "MPL-2.0", "optional": true, "os": [ - "linux" + "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" + "node": ">= 10" } }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", - "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" - } - }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", - "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" - } - }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-wasm32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", - "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, + "node_modules/@rollup/plugin-commonjs": { + "version": "28.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz", + "integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@emnapi/runtime": "^1.4.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-win32-ia32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", - "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=16.0.0 || 14 >= 14.17" }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@huggingface/transformers/node_modules/@img/sharp-win32-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", - "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" }, - "funding": { - "url": "https://opencollective.com/libvips" + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@huggingface/transformers/node_modules/sharp": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", - "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", - "hasInstallScript": true, - "license": "Apache-2.0", + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.4", - "semver": "^7.7.2" + "@rollup/pluginutils": "^5.1.0" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=14.0.0" }, - "funding": { - "url": "https://opencollective.com/libvips" + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.2", - "@img/sharp-darwin-x64": "0.34.2", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.2", - "@img/sharp-linux-arm64": "0.34.2", - "@img/sharp-linux-s390x": "0.34.2", - "@img/sharp-linux-x64": "0.34.2", - "@img/sharp-linuxmusl-arm64": "0.34.2", - "@img/sharp-linuxmusl-x64": "0.34.2", - "@img/sharp-wasm32": "0.34.2", - "@img/sharp-win32-arm64": "0.34.2", - "@img/sharp-win32-ia32": "0.34.2", - "@img/sharp-win32-x64": "0.34.2" + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" }, "engines": { - "node": ">=10.10.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" }, "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" + "node": ">=14.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@iconify-json/bi": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@iconify-json/bi/-/bi-1.2.4.tgz", - "integrity": "sha512-ipD8nm86ovjgXGEJj/B5oSJGaEIsGgzrKqNT1ei66nRExzK6Mgh4an/efG30Xtvp2eQjz9eWN5kHmadbnjUmzw==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", + "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@iconify/types": "*" - } - }, - "node_modules/@iconify-json/carbon": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@iconify-json/carbon/-/carbon-1.2.9.tgz", - "integrity": "sha512-RyeSAuFTzhs1GX4yrzVEKEbNQGt95p9zMR4S2F63vbThtNoUr5OKwaWbhO/GbHQCSgdbKuZv2ApAOsY2fLxLbQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@iconify/types": "*" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@iconify-json/eos-icons": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@iconify-json/eos-icons/-/eos-icons-1.2.2.tgz", - "integrity": "sha512-kYfV1WfgiHDbWdG9JEbV1K77MvksRmo9KIM4VjtYFMnF8pKqTv4MoLIOdCD2lbRlhBZspxr1GKde5Z/LYqz3Qw==", - "dev": true, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", + "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@iconify/types": "*" - } - }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "license": "MIT" + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@iconify/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", - "dev": true, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", + "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@antfu/utils": "^8.1.0", - "@iconify/types": "^2.0.0", - "debug": "^4.4.0", - "globals": "^15.14.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "mlly": "^1.7.4" - } - }, - "node_modules/@iconify/utils/node_modules/@antfu/install-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", - "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "package-manager-detector": "^1.3.0", - "tinyexec": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@iconify/utils/node_modules/@antfu/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@iconify/utils/node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@iconify/utils/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@iconify/utils/node_modules/local-pkg": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", - "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.0.1", - "quansync": "^0.2.8" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@iconify/utils/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@iconify/utils/node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", - "pathe": "^2.0.3" - } - }, - "node_modules/@iconify/utils/node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", "optional": true, "os": [ "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } + ] }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", + "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", "cpu": [ "x64" ], - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } + ] }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", + "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", "cpu": [ "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + "freebsd" + ] }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", + "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", "cpu": [ "x64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + "freebsd" + ] }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", + "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", "cpu": [ "arm" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", + "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", "cpu": [ - "arm64" + "arm" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", - "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", + "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", "cpu": [ - "ppc64" + "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", + "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", "cpu": [ - "s390x" + "arm64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", + "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", "cpu": [ - "x64" + "loong64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", + "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", "cpu": [ - "x64" + "ppc64" ], - "license": "LGPL-3.0-or-later", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } + ] }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", + "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", "cpu": [ - "arm" + "riscv64" ], - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } + ] }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", + "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", "cpu": [ - "arm64" + "riscv64" ], - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } + ] }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", + "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", "cpu": [ "s390x" ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } + ] }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", + "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", "cpu": [ "x64" ], - "license": "Apache-2.0", + "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", - "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.12.tgz", - "integrity": "sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.13", - "@inquirer/type": "^3.0.7" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } + ] }, - "node_modules/@inquirer/core": { - "version": "10.1.13", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.13.tgz", - "integrity": "sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==", - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.12", - "@inquirer/type": "^3.0.7", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/core/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.12.tgz", - "integrity": "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.7.tgz", - "integrity": "sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1" - } - }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.1.tgz", - "integrity": "sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw==", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.6", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "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.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "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.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.2.tgz", - "integrity": "sha512-EB0O3SCSNRUFk66iRCpI+cXzIjdswfCs7F6nOC3RAGJ7xr5YhaicvsRwJ9eyzYvYRlCSDUO/c7g4yNulxKC1WA==", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, - "node_modules/@mswjs/interceptors": { - "version": "0.38.7", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.38.7.tgz", - "integrity": "sha512-Jkb27iSn7JPdkqlTqKfhncFfnEZsIJVYxsFbUSWEkxdIPdsyngrhoDBk0/BGD2FQcRH99vlRrkHpNTyKqI+0/w==", - "license": "MIT", - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.4.3", - "strict-event-emitter": "^0.5.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@node-llama-cpp/linux-arm64": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/linux-arm64/-/linux-arm64-3.9.0.tgz", - "integrity": "sha512-/BaVWWxDkME+jC9KgptzWtcVo9zoeI9I4tw2f6hCZIhIgkLHxdiZe8wLvTW+dFaBC+ilmcwgQ6Fm8Y3RFUnoQw==", - "cpu": [ - "arm64", - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/linux-armv7l": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/linux-armv7l/-/linux-armv7l-3.9.0.tgz", - "integrity": "sha512-FDCPcYR/FRjgyusBZiqIbsCAVP6H/I5yBQq1jZpFPPTL0bGTyyJxXrPKEEHLvLoMV+pkAzhCUKNf4s2soIxDvw==", - "cpu": [ - "arm", - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/linux-x64": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/linux-x64/-/linux-x64-3.9.0.tgz", - "integrity": "sha512-PxYt0rwZpmkQ7gLwqloqSuwoyRWCyrVPw/KyY3pDAOPEfQXSMaCohhZj6nT1eQNEqCNbdR+5v8j+LuvuE3slMw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/linux-x64-cuda": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/linux-x64-cuda/-/linux-x64-cuda-3.9.0.tgz", - "integrity": "sha512-LHUKNjipOcS9MxFpP1fnWkViC9L6lGdYU93oDdYKVzhDn78gIVHnv2nvu2epPIVssoHAXIbDbf7s7764hLCGQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/linux-x64-vulkan": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/linux-x64-vulkan/-/linux-x64-vulkan-3.9.0.tgz", - "integrity": "sha512-Tt9OhStrqCaqaWrCZRFlBRbRePKtfiZUFJZTH1HAXf8V9bn8jMcMTtGxKIbkiOH/Zg6ZBu6ZJONSRM0DRbf7lA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/mac-arm64-metal": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/mac-arm64-metal/-/mac-arm64-metal-3.9.0.tgz", - "integrity": "sha512-wWwjcRQkeLscZUtaLE3JSdXDo2mVqqqeVciTM0ldQIG1txoBTuAxWojpju/bapoCru/scY7qK9M8QrVt/otrJQ==", - "cpu": [ - "arm64", - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/mac-x64": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/mac-x64/-/mac-x64-3.9.0.tgz", - "integrity": "sha512-FpeSxQtSGmgJECyFvsFi0BX03KiE6JN5fYugyrvhthqbFVmOakj0KFqZz14oPQ4EKtk0LPT5hTzBra6n3IPvXg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/win-arm64": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/win-arm64/-/win-arm64-3.9.0.tgz", - "integrity": "sha512-9yKfXzWD1jGta+2VC0uj9yHF6w36size1MokU33Otk3OVETFfSGOAZ1DDtnEZudTovvrYxMQI/7/379WfpsPdA==", - "cpu": [ - "arm64", - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/win-x64": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/win-x64/-/win-x64-3.9.0.tgz", - "integrity": "sha512-SM7CO4Z+4fYVUxnADneS1FGgZRnVDVz3jjTurHiaGuMt606+G2awElh8G+AOiCl58kutD3rVVqCXHiDrlPW4wA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/win-x64-cuda": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/win-x64-cuda/-/win-x64-cuda-3.9.0.tgz", - "integrity": "sha512-6NTPh7royOIwds3+H3wX3WTJz/8iSWYXvdkGtt706X3G/CUCo4Fiibtft7Rt42+annX3HUEMBDBu5KB1/eMusA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@node-llama-cpp/win-x64-vulkan": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@node-llama-cpp/win-x64-vulkan/-/win-x64-vulkan-3.9.0.tgz", - "integrity": "sha512-YPsSJhzrpwZy1aj4dgxUL8RSQGpIVcX1OTyJQdtAuU6SmbaUb5p6J2P8ofmYu+0de10GaaL0KMC9Tk4FJW05hw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/app": { - "version": "15.1.6", - "resolved": "https://registry.npmjs.org/@octokit/app/-/app-15.1.6.tgz", - "integrity": "sha512-WELCamoCJo9SN0lf3SWZccf68CF0sBNPQuLYmZ/n87p5qvBJDe9aBtr5dHkh7T9nxWZ608pizwsUbypSzZAiUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-app": "^7.2.1", - "@octokit/auth-unauthenticated": "^6.1.3", - "@octokit/core": "^6.1.5", - "@octokit/oauth-app": "^7.1.6", - "@octokit/plugin-paginate-rest": "^12.0.0", - "@octokit/types": "^14.0.0", - "@octokit/webhooks": "^13.6.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-app": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.2.1.tgz", - "integrity": "sha512-4jaopCVOtWN0V8qCx/1s2pkRqC6tcvIQM3kFB99eIpsP53GfsoIKO08D94b83n/V3iGihHmxWR2lXzE0NicUGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-oauth-app": "^8.1.4", - "@octokit/auth-oauth-user": "^5.1.4", - "@octokit/request": "^9.2.3", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "toad-cache": "^3.7.0", - "universal-github-app-jwt": "^2.2.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-oauth-app": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.4.tgz", - "integrity": "sha512-71iBa5SflSXcclk/OL3lJzdt4iFs56OJdpBGEBl1wULp7C58uiswZLV6TdRaiAzHP1LT8ezpbHlKuxADb+4NkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-oauth-device": "^7.1.5", - "@octokit/auth-oauth-user": "^5.1.4", - "@octokit/request": "^9.2.3", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-oauth-device": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.5.tgz", - "integrity": "sha512-lR00+k7+N6xeECj0JuXeULQ2TSBB/zjTAmNF2+vyGPDEFx1dgk1hTDmL13MjbSmzusuAmuJD8Pu39rjp9jH6yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/oauth-methods": "^5.1.5", - "@octokit/request": "^9.2.3", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-oauth-user": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.6.tgz", - "integrity": "sha512-/R8vgeoulp7rJs+wfJ2LtXEVC7pjQTIqDab7wPKwVG6+2v/lUnCOub6vaHmysQBbb45FknM3tbHW8TOVqYHxCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-oauth-device": "^7.1.5", - "@octokit/oauth-methods": "^5.1.5", - "@octokit/request": "^9.2.3", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-token": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", - "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/auth-unauthenticated": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.3.tgz", - "integrity": "sha512-d5gWJla3WdSl1yjbfMpET+hUSFCE15qM0KVSB0H1shyuJihf/RL1KqWoZMIaonHvlNojkL9XtLFp8QeLe+1iwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/core": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.5.tgz", - "integrity": "sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^5.0.0", - "@octokit/graphql": "^8.2.2", - "@octokit/request": "^9.2.3", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "before-after-hook": "^3.0.2", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/endpoint": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", - "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/graphql": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", - "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request": "^9.2.3", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/oauth-app": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@octokit/oauth-app/-/oauth-app-7.1.6.tgz", - "integrity": "sha512-OMcMzY2WFARg80oJNFwWbY51TBUfLH4JGTy119cqiDawSFXSIBujxmpXiKbGWQlvfn0CxE6f7/+c6+Kr5hI2YA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-oauth-app": "^8.1.3", - "@octokit/auth-oauth-user": "^5.1.3", - "@octokit/auth-unauthenticated": "^6.1.2", - "@octokit/core": "^6.1.4", - "@octokit/oauth-authorization-url": "^7.1.1", - "@octokit/oauth-methods": "^5.1.4", - "@types/aws-lambda": "^8.10.83", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/oauth-authorization-url": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz", - "integrity": "sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/oauth-methods": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.5.tgz", - "integrity": "sha512-Ev7K8bkYrYLhoOSZGVAGsLEscZQyq7XQONCBBAl2JdMg7IT3PQn/y8P0KjloPoYpI5UylqYrLeUcScaYWXwDvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/oauth-authorization-url": "^7.0.0", - "@octokit/request": "^9.2.3", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", - "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/openapi-webhooks-types": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-11.0.0.tgz", - "integrity": "sha512-ZBzCFj98v3SuRM7oBas6BHZMJRadlnDoeFfvm1olVxZnYeU6Vh97FhPxyS5aLh5pN51GYv2I51l/hVUAVkGBlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-graphql": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.4.tgz", - "integrity": "sha512-pLZES1jWaOynXKHOqdnwZ5ULeVR6tVVCMm+AUbp0htdcyXDU95WbkYdU4R2ej1wKj5Tu94Mee2Ne0PjPO9cCyA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-12.0.0.tgz", - "integrity": "sha512-MPd6WK1VtZ52lFrgZ0R2FlaoiWllzgqFHaSZxvp72NmoDeZ0m8GeJdg4oB6ctqMTYyrnDYp592Xma21mrgiyDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-14.0.0.tgz", - "integrity": "sha512-iQt6ovem4b7zZYZQtdv+PwgbL5VPq37th1m2x2TdkgimIDJpsi2A6Q/OI/23i/hR6z5mL0EgisNR4dcbmckSZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-retry": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.1.tgz", - "integrity": "sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-throttling": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-10.0.0.tgz", - "integrity": "sha512-Kuq5/qs0DVYTHZuBAzCZStCzo2nKvVRo/TDNhCcpC2TKiOGz/DisXMCvjt3/b5kr6SCI1Y8eeeJTHBxxpFvZEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "^6.1.3" - } - }, - "node_modules/@octokit/request": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.3.tgz", - "integrity": "sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^10.1.4", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^2.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/request-error": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", - "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", - "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^25.1.0" - } - }, - "node_modules/@octokit/webhooks": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-13.9.0.tgz", - "integrity": "sha512-5Kva+/Gi7c+39d0/0MM/v/5RCZuwqm75fUD+t7Es3Iz/adui54GnjfNmJpkkPkXGC+5IWnEvgqwY6gstK/JlUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-webhooks-types": "11.0.0", - "@octokit/request-error": "^6.1.7", - "@octokit/webhooks-methods": "^5.1.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/webhooks-methods": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-5.1.1.tgz", - "integrity": "sha512-NGlEHZDseJTCj8TMMFehzwa9g7On4KJMPVHDSrHxCQumL6uSQR8wIkP/qesv52fXqV1BPf4pTxwtS31ldAt9Xg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "license": "MIT" - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", - "license": "MIT", - "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" - } - }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", - "license": "MIT" - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@playwright/browser-chromium": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.52.0.tgz", - "integrity": "sha512-n2/e2Q0dFACFg/1JZ0t2IYLorDdno6q1QwKnNbPICHwCkAtW7+fSMqCvJ9FSMWSyPugxZqIFhownSpyATxtiTw==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.52.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "license": "MIT" - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", - "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/graph": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@reflink/reflink": { - "resolved": "node_modules/ipull/stub/@reflink/reflink", - "link": true - }, - "node_modules/@remusao/guess-url-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@remusao/guess-url-type/-/guess-url-type-1.3.0.tgz", - "integrity": "sha512-SNSJGxH5ckvxb3EUHj4DqlAm/bxNxNv2kx/AESZva/9VfcBokwKNS+C4D1lQdWIDM1R3d3UG+xmVzlkNG8CPTQ==", - "license": "MPL-2.0" - }, - "node_modules/@remusao/small": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@remusao/small/-/small-1.3.0.tgz", - "integrity": "sha512-bydAhJI+ywmg5xMUcbqoR8KahetcfkFywEZpsyFZ8EBofilvWxbXnMSe4vnjDI1Y+SWxnNhR4AL/2BAXkf4b8A==", - "license": "MPL-2.0" - }, - "node_modules/@remusao/smaz": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@remusao/smaz/-/smaz-1.10.0.tgz", - "integrity": "sha512-GQzCxmmMpLkyZwcwNgz8TpuBEWl0RUQa8IcvKiYlPxuyYKqyqPkCr0hlHI15ckn3kDUPS68VmTVgyPnLNrdVmg==", - "license": "MPL-2.0", - "dependencies": { - "@remusao/smaz-compress": "^1.10.0", - "@remusao/smaz-decompress": "^1.10.0" - } - }, - "node_modules/@remusao/smaz-compress": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@remusao/smaz-compress/-/smaz-compress-1.10.0.tgz", - "integrity": "sha512-E/lC8OSU+3bQrUl64vlLyPzIxo7dxF2RvNBe9KzcM4ax43J/d+YMinmMztHyCIHqRbz7rBCtkp3c0KfeIbHmEg==", - "license": "MPL-2.0", - "dependencies": { - "@remusao/trie": "^1.5.0" - } - }, - "node_modules/@remusao/smaz-decompress": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@remusao/smaz-decompress/-/smaz-decompress-1.10.0.tgz", - "integrity": "sha512-aA5ImUH480Pcs5/cOgToKmFnzi7osSNG6ft+7DdmQTaQEEst3nLq3JLlBEk+gwidURymjbx6DYs60LHaZ415VQ==", - "license": "MPL-2.0" - }, - "node_modules/@remusao/trie": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@remusao/trie/-/trie-1.5.0.tgz", - "integrity": "sha512-UX+3utJKgwCsg6sUozjxd38gNMVRXrY4TNX9VvCdSrlZBS1nZjRPi98ON3QjRAdf6KCguJFyQARRsulTeqQiPg==", - "license": "MPL-2.0" - }, - "node_modules/@resvg/resvg-js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js/-/resvg-js-2.6.2.tgz", - "integrity": "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==", - "license": "MPL-2.0", - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@resvg/resvg-js-android-arm-eabi": "2.6.2", - "@resvg/resvg-js-android-arm64": "2.6.2", - "@resvg/resvg-js-darwin-arm64": "2.6.2", - "@resvg/resvg-js-darwin-x64": "2.6.2", - "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", - "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", - "@resvg/resvg-js-linux-arm64-musl": "2.6.2", - "@resvg/resvg-js-linux-x64-gnu": "2.6.2", - "@resvg/resvg-js-linux-x64-musl": "2.6.2", - "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", - "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", - "@resvg/resvg-js-win32-x64-msvc": "2.6.2" - } - }, - "node_modules/@resvg/resvg-js-android-arm-eabi": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm-eabi/-/resvg-js-android-arm-eabi-2.6.2.tgz", - "integrity": "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-android-arm64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-android-arm64/-/resvg-js-android-arm64-2.6.2.tgz", - "integrity": "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-darwin-arm64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-arm64/-/resvg-js-darwin-arm64-2.6.2.tgz", - "integrity": "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-darwin-x64": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-darwin-x64/-/resvg-js-darwin-x64-2.6.2.tgz", - "integrity": "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm-gnueabihf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm-gnueabihf/-/resvg-js-linux-arm-gnueabihf-2.6.2.tgz", - "integrity": "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-gnu/-/resvg-js-linux-arm64-gnu-2.6.2.tgz", - "integrity": "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-arm64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-arm64-musl/-/resvg-js-linux-arm64-musl-2.6.2.tgz", - "integrity": "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-x64-gnu": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-gnu/-/resvg-js-linux-x64-gnu-2.6.2.tgz", - "integrity": "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-linux-x64-musl": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-linux-x64-musl/-/resvg-js-linux-x64-musl-2.6.2.tgz", - "integrity": "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-arm64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-arm64-msvc/-/resvg-js-win32-arm64-msvc-2.6.2.tgz", - "integrity": "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-ia32-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-ia32-msvc/-/resvg-js-win32-ia32-msvc-2.6.2.tgz", - "integrity": "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==", - "cpu": [ - "ia32" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@resvg/resvg-js-win32-x64-msvc": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@resvg/resvg-js-win32-x64-msvc/-/resvg-js-win32-x64-msvc-2.6.2.tgz", - "integrity": "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz", - "integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", - "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.1.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", - "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", - "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", - "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", - "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", - "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", - "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", - "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", - "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", - "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", - "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", - "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", - "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", - "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", - "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", - "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", - "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", - "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", - "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", - "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", - "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", - "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@scalar/openapi-types": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.1.1.tgz", - "integrity": "sha512-NMy3QNk6ytcCoPUGJH0t4NNr36OWXgZhA3ormr3TvhX1NDgoF95wFyodGVH8xiHeUyn2/FxtETm8UBLbB5xEmg==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@scalar/themes": { - "version": "0.9.86", - "resolved": "https://registry.npmjs.org/@scalar/themes/-/themes-0.9.86.tgz", - "integrity": "sha512-QUHo9g5oSWi+0Lm1vJY9TaMZRau8LHg+vte7q5BVTBnu6NuQfigCaN+ouQ73FqIVd96TwMO6Db+dilK1B+9row==", - "license": "MIT", - "dependencies": { - "@scalar/types": "0.1.7" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@scalar/themes/node_modules/@scalar/openapi-types": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.2.0.tgz", - "integrity": "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA==", - "license": "MIT", - "dependencies": { - "zod": "^3.23.8" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@scalar/themes/node_modules/@scalar/types": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.1.7.tgz", - "integrity": "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw==", - "license": "MIT", - "dependencies": { - "@scalar/openapi-types": "0.2.0", - "@unhead/schema": "^1.11.11", - "nanoid": "^5.1.5", - "type-fest": "^4.20.0", - "zod": "^3.23.8" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@scalar/themes/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@scalar/types": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.0.12.tgz", - "integrity": "sha512-XYZ36lSEx87i4gDqopQlGCOkdIITHHEvgkuJFrXFATQs9zHARop0PN0g4RZYWj+ZpCUclOcaOjbCt8JGe22mnQ==", - "license": "MIT", - "dependencies": { - "@scalar/openapi-types": "0.1.1", - "@unhead/schema": "^1.9.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@shuding/opentype.js": { - "version": "1.4.0-beta.0", - "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", - "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==", - "license": "MIT", - "dependencies": { - "fflate": "^0.7.3", - "string.prototype.codepointat": "^0.2.1" - }, - "bin": { - "ot": "bin/ot" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@shuding/opentype.js/node_modules/fflate": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", - "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==", - "license": "MIT" - }, - "node_modules/@sinclair/typebox": { - "version": "0.34.33", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.33.tgz", - "integrity": "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g==", - "license": "MIT", - "optional": true - }, - "node_modules/@smithy/abort-controller": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", - "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", - "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.5.3.tgz", - "integrity": "sha512-xa5byV9fEguZNofCclv6v9ra0FYh5FATQW/da7FQUVTic94DfrN/NvmKZjrMyzbpqfot9ZjBaO8U1UeTbmSLuA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.8", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", - "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", - "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.3.1", - "@smithy/util-hex-encoding": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz", - "integrity": "sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz", - "integrity": "sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz", - "integrity": "sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz", - "integrity": "sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/eventstream-codec": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz", - "integrity": "sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", - "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", - "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", - "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", - "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.11.tgz", - "integrity": "sha512-zDogwtRLzKl58lVS8wPcARevFZNBOOqnmzWWxVe9XiaXU2CADFjvJ9XfNibgkOWs08sxLuSr81NrpY4mgp9OwQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.5.3", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-middleware": "^4.0.4", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.12.tgz", - "integrity": "sha512-wvIH70c4e91NtRxdaLZF+mbLZ/HcC6yg7ySKUiufL6ESp6zJUSnJucZ309AvG9nqCFHSRB5I6T3Ez1Q9wCh0Ww==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/service-error-classification": "^4.0.5", - "@smithy/smithy-client": "^4.4.3", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.5", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", - "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", - "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", - "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz", - "integrity": "sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", - "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", - "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", - "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "@smithy/util-uri-escape": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", - "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.5.tgz", - "integrity": "sha512-LvcfhrnCBvCmTee81pRlh1F39yTS/+kYleVeLCwNtkY8wtGg8V/ca9rbZZvYIl8OjlMtL6KIjaiL/lgVqHD2nA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", - "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", - "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-uri-escape": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.3.tgz", - "integrity": "sha512-xxzNYgA0HD6ETCe5QJubsxP0hQH3QK3kbpJz3QrosBCuIWyEXLR/CO5hFb2OeawEKUxMNhz3a1nuJNN2np2RMA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.5.3", - "@smithy/middleware-endpoint": "^4.1.11", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", - "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", - "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", - "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", - "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", - "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", - "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", - "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.19", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.19.tgz", - "integrity": "sha512-mvLMh87xSmQrV5XqnUYEPoiFFeEGYeAKIDDKdhE2ahqitm8OHM3aSvhqL6rrK6wm1brIk90JhxDf5lf2hbrLbQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.3", - "@smithy/types": "^4.3.1", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.19", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.19.tgz", - "integrity": "sha512-8tYnx+LUfj6m+zkUUIrIQJxPM1xVxfRBvoGHua7R/i6qAxOMjqR6CpEpDwKoIs1o0+hOjGvkKE23CafKL0vJ9w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.1.4", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", - "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", - "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", - "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.5.tgz", - "integrity": "sha512-V7MSjVDTlEt/plmOFBn1762Dyu5uqMrV2Pl2X0dYk4XvWfdWJNe9Bs5Bzb56wkCuiWjSfClVMGcsuKrGj7S/yg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.0.5", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.2.tgz", - "integrity": "sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/types": "^4.3.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-waiter": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.5.tgz", - "integrity": "sha512-4QvC49HTteI1gfemu0I1syWovJgPvGn7CVUoN9ZFkdvr/cCFkrEL7qNCdx/2eICqDWEGnnr68oMdSIPCLAriSQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/types": "^4.3.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", - "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8.9.0" - } - }, - "node_modules/@sveltejs/adapter-node": { - "version": "5.2.12", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.12.tgz", - "integrity": "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/plugin-commonjs": "^28.0.1", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^16.0.0", - "rollup": "^4.9.5" - }, - "peerDependencies": { - "@sveltejs/kit": "^2.4.0" - } - }, - "node_modules/@sveltejs/kit": { - "version": "2.21.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.21.2.tgz", - "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/acorn-typescript": "^1.0.5", - "@types/cookie": "^0.6.0", - "acorn": "^8.14.1", - "cookie": "^0.6.0", - "devalue": "^5.1.0", - "esm-env": "^1.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.30.5", - "mrmime": "^2.0.0", - "sade": "^1.8.1", - "set-cookie-parser": "^2.6.0", - "sirv": "^3.0.0" - }, - "bin": { - "svelte-kit": "svelte-kit.js" - }, - "engines": { - "node": ">=18.13" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", - "vite": "^5.0.3 || ^6.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.0.tgz", - "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", - "debug": "^4.4.1", - "deepmerge": "^4.3.1", - "kleur": "^4.1.5", - "magic-string": "^0.30.17", - "vitefu": "^1.0.6" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", - "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.7" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.0", - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@tailwindcss/typography": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", - "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "postcss-selector-parser": "6.0.10" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.6.1", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", - "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@tinyhttp/content-disposition": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@tinyhttp/content-disposition/-/content-disposition-2.2.2.tgz", - "integrity": "sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20.0" - }, - "funding": { - "type": "individual", - "url": "https://github.com/tinyhttp/tinyhttp?sponsor=1" - } - }, - "node_modules/@tokenizer/inflate": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", - "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "fflate": "^0.8.2", - "token-types": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.149", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.149.tgz", - "integrity": "sha512-NXSZIhfJjnXqJgtS7IwutqIF/SOy1Wz5Px4gUY1RWITp3AYTyuJS4xaXr/bIJY1v15XMzrJ5soGnPM+7uigZjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*" - } - }, - "node_modules/@types/chrome": { - "version": "0.0.278", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.278.tgz", - "integrity": "sha512-PDIJodOu7o54PpSOYLybPW/MDZBCjM1TKgf31I3Q/qaEbNpIH09rOM3tSEH3N7Q+FAqb1933LhF8ksUPYeQLNg==", - "license": "MIT", - "dependencies": { - "@types/filesystem": "*", - "@types/har-format": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "license": "MIT" - }, - "node_modules/@types/dompurify": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", - "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/trusted-types": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/eventsource": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.1.15.tgz", - "integrity": "sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==", - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", - "integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/filesystem": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz", - "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", - "license": "MIT", - "dependencies": { - "@types/filewriter": "*" - } - }, - "node_modules/@types/filewriter": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz", - "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==", - "license": "MIT" - }, - "node_modules/@types/firefox-webext-browser": { - "version": "120.0.4", - "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-120.0.4.tgz", - "integrity": "sha512-lBrpf08xhiZBigrtdQfUaqX1UauwZ+skbFiL8u2Tdra/rklkKadYmIzTwkNZSWtuZ7OKpFqbE2HHfDoFqvZf6w==", - "license": "MIT" - }, - "node_modules/@types/fs-extra": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", - "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jsonfile": "*", - "@types/node": "*" - } - }, - "node_modules/@types/har-format": { - "version": "1.2.16", - "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", - "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==", - "license": "MIT" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsdom": { - "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonfile": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", - "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/jsonpath": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@types/jsonpath/-/jsonpath-0.2.4.tgz", - "integrity": "sha512-K3hxB8Blw0qgW6ExKgMbXQv2UPZBoE2GqLpVY+yr7nMD2Pq86lsuIzyAaiQ7eMqFL5B6di6pxSkogLJEyEHoGA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/katex": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", - "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime-types": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", - "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/node-int64": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.32.tgz", - "integrity": "sha512-xf/JsSlnXQ+mzvc0IpXemcrO4BrCfpgNpMco+GLcXkFk01k/gW9lGJu+Vof0ZSvHK6DsHJDPSbjFPs36QkWXqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parquetjs": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/@types/parquetjs/-/parquetjs-0.10.6.tgz", - "integrity": "sha512-ZCsD6j97YD0mGU8/VnVs3NjORXa7zeHvqlpJpCqy4jU8a1O21dalL+MFn9QNbdEfy8rszR1N7NHeT7/LdtHf+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node-int64": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sbd": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/sbd/-/sbd-1.0.5.tgz", - "integrity": "sha512-60PxBBWhg0C3yb5bTP+wwWYGTKMcuB0S6mTEa1sedMC79tYY0Ei7YjU4qsWzGn++lWscLQde16SnElJrf5/aTw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/statuses": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", - "license": "MIT" - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "license": "MIT" - }, - "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "node_modules/@types/yazl": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@types/yazl/-/yazl-3.3.0.tgz", - "integrity": "sha512-mFL6lGkk2N5u5nIxpNV/K5LW3qVSbxhJrMxYGOOxZndWxMgCamr/iCsq/1t9kd8pEwhuNP91LC5qZm/qS9pOEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@unhead/schema": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.20.tgz", - "integrity": "sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==", - "license": "MIT", - "dependencies": { - "hookable": "^5.5.3", - "zhead": "^2.2.4" - }, - "funding": { - "url": "https://github.com/sponsors/harlan-zw" - } - }, - "node_modules/@vitest/browser": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.2.tgz", - "integrity": "sha512-LJk8ZhCGhgG6G6jFFJ9LX83ibRY8FszLuu9zPaYFDrcHbBwNXwt1v06HRs/vHVYxwjw3/BGzSIgn9Et2P6rCiA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@testing-library/dom": "^10.4.0", - "@testing-library/user-event": "^14.6.1", - "@vitest/mocker": "3.2.2", - "@vitest/utils": "3.2.2", - "magic-string": "^0.30.17", - "sirv": "^3.0.1", - "tinyrainbow": "^2.0.0", - "ws": "^8.18.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "playwright": "*", - "vitest": "3.2.2", - "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true - } - } - }, - "node_modules/@vitest/expect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", - "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", - "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.2.2", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", - "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", - "license": "MIT", - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", - "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", - "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.2", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "license": "MIT" - }, - "node_modules/@vitest/snapshot": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", - "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.2", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "license": "MIT" - }, - "node_modules/@vitest/spy": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", - "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", - "license": "MIT", - "dependencies": { - "tinyspy": "^4.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", - "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.2", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "license": "BSD-3-Clause" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/afinn-165": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/afinn-165/-/afinn-165-1.0.4.tgz", - "integrity": "sha512-7+Wlx3BImrK0HiG6y3lU4xX7SpBPSSu8T9iguPMlaueRFxjbYwAQrp9lqZUuFikqKbd/en8lVREILvP2J80uJA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/afinn-165-financialmarketnews": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/afinn-165-financialmarketnews/-/afinn-165-financialmarketnews-3.0.0.tgz", - "integrity": "sha512-0g9A1S3ZomFIGDTzZ0t6xmv4AuokBvBmpes8htiyHpH7N4xDmvSQL6UxL/Zcs2ypRb3VwgCscaD8Q3zEawKYhw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/apparatus": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/apparatus/-/apparatus-0.0.10.tgz", - "integrity": "sha512-KLy/ugo33KZA7nugtQ7O0E1c8kQ52N3IvD/XgIh4w/Nr28ypfkwDfA67F1ev4N1m5D+BOk1+b2dEJDfpj/VvZg==", - "license": "MIT", - "dependencies": { - "sylvester": ">= 0.0.8" - }, - "engines": { - "node": ">=0.2.6" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/async-mutex": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", - "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/aws-sigv4-fetch": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/aws-sigv4-fetch/-/aws-sigv4-fetch-4.4.1.tgz", - "integrity": "sha512-0eG8a6/LIoTMHbY1GRkZZfdRsQfKKEGS/IuApIyS/Jt+6mSJNKoQBHisjB4D7UGz+wDrZHeTKJgSKV1Yn1WFRA==", - "license": "MIT", - "dependencies": { - "aws-sigv4-sign": "1.2.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/aws-sigv4-sign": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/aws-sigv4-sign/-/aws-sigv4-sign-1.2.1.tgz", - "integrity": "sha512-iS0pV4xGzhexBCMG9ggXM5CaxTHa3KxOxkw2tphLgA/60vSycSWjJWso0s4xzGRrtABSi0b3LlxG5Jek7NjuqA==", - "license": "MIT", - "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-sdk/credential-provider-node": "^3.609.0", - "@smithy/protocol-http": "^4.0.3", - "@smithy/signature-v4": "^3.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/protocol-http": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", - "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/signature-v4": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.1.2.tgz", - "integrity": "sha512-3BcPylEsYtD0esM4Hoyml/+s7WP2LFhcM3J2AGdcL2vx9O60TtfpDOL72gjb4lU8NeRPeKAwR77YNyyGvMbuEA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/types": "^3.3.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.3", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/types": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", - "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/util-middleware": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", - "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws-sigv4-sign/node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "license": "MIT" - }, - "node_modules/aws4fetch": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/aws4fetch/-/aws4fetch-1.0.20.tgz", - "integrity": "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==", - "license": "MIT", - "optional": true - }, - "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/before-after-hook": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", - "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/bignumber.js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", - "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha512-u4cBQNepWxYA55FunZSM7wMi55yQaN0otnhhilNoWHq0MfOfJeQx0v0mRRpolGOExPjZcl6FtB0BB8Xkb88F0g==", - "license": "MIT", - "optional": true - }, - "node_modules/bintrees": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", - "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/body-parser/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT" - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.1.2" - } - }, - "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bson": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", - "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", - "license": "Apache-2.0", - "engines": { - "node": ">=14.20.1" - } - }, - "node_modules/bson-objectid": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-2.0.4.tgz", - "integrity": "sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/bufferutil": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", - "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", + "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", + "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", + "cpu": [ + "arm64" ], - "license": "CC-BY-4.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", + "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", + "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "node_modules/@scalar/openapi-types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.1.1.tgz", + "integrity": "sha512-NMy3QNk6ytcCoPUGJH0t4NNr36OWXgZhA3ormr3TvhX1NDgoF95wFyodGVH8xiHeUyn2/FxtETm8UBLbB5xEmg==", "license": "MIT", "engines": { - "node": ">= 16" + "node": ">=18" } }, - "node_modules/chmodrp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chmodrp/-/chmodrp-1.0.2.tgz", - "integrity": "sha512-TdngOlFV1FLTzU0o1w8MB6/BFywhtLC0SzRTGJU7T9lmdjlCWeMRt1iVo0Ki+ldwNk0BqNiKoc8xpLZEQ8mY1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, + "node_modules/@scalar/themes": { + "version": "0.9.86", + "resolved": "https://registry.npmjs.org/@scalar/themes/-/themes-0.9.86.tgz", + "integrity": "sha512-QUHo9g5oSWi+0Lm1vJY9TaMZRau8LHg+vte7q5BVTBnu6NuQfigCaN+ouQ73FqIVd96TwMO6Db+dilK1B+9row==", "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" + "@scalar/types": "0.1.7" }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/ci-info": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", - "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/@scalar/themes/node_modules/@scalar/openapi-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.2.0.tgz", + "integrity": "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA==", "license": "MIT", + "dependencies": { + "zod": "^3.23.8" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/@scalar/themes/node_modules/@scalar/types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.1.7.tgz", + "integrity": "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw==", "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "@scalar/openapi-types": "0.2.0", + "@unhead/schema": "^1.11.11", + "nanoid": "^5.1.5", + "type-fest": "^4.20.0", + "zod": "^3.23.8" }, "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", + "node_modules/@scalar/themes/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=6" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "node_modules/@scalar/types": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.0.12.tgz", + "integrity": "sha512-XYZ36lSEx87i4gDqopQlGCOkdIITHHEvgkuJFrXFATQs9zHARop0PN0g4RZYWj+ZpCUclOcaOjbCt8JGe22mnQ==", "license": "MIT", "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" + "@scalar/openapi-types": "0.1.1", + "@unhead/schema": "^1.9.5" }, "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "license": "ISC", - "engines": { - "node": ">= 12" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", + "node_modules/@shuding/opentype.js": { + "version": "1.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", + "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "fflate": "^0.7.3", + "string.prototype.codepointat": "^0.2.1" + }, + "bin": { + "ot": "bin/ot" }, "engines": { - "node": ">=12" + "node": ">= 8.0.0" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/@shuding/opentype.js/node_modules/fflate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", + "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==", "license": "MIT" }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@sinclair/typebox": { + "version": "0.34.33", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.33.tgz", + "integrity": "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g==", "license": "MIT", - "engines": { - "node": ">=8" + "optional": true + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", + "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@sveltejs/adapter-node": { + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.12.tgz", + "integrity": "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==", + "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@rollup/plugin-commonjs": "^28.0.1", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^16.0.0", + "rollup": "^4.9.5" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@sveltejs/kit": "^2.4.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/@sveltejs/kit": { + "version": "2.21.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.21.2.tgz", + "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/cookie": "^0.6.0", + "acorn": "^8.14.1", + "cookie": "^0.6.0", + "devalue": "^5.1.0", + "esm-env": "^1.2.2", + "kleur": "^4.1.5", + "magic-string": "^0.30.5", + "mrmime": "^2.0.0", + "sade": "^1.8.1", + "set-cookie-parser": "^2.6.0", + "sirv": "^3.0.0" + }, + "bin": { + "svelte-kit": "svelte-kit.js" }, "engines": { - "node": ">=10" + "node": ">=18.13" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.0", + "vite": "^5.0.3 || ^6.0.0" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.0.tgz", + "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==", + "dev": true, "license": "MIT", + "dependencies": { + "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", + "debug": "^4.4.1", + "deepmerge": "^4.3.1", + "kleur": "^4.1.5", + "magic-string": "^0.30.17", + "vitefu": "^1.0.6" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" + "node": "^18.0.0 || ^20.0.0 || >=22" + }, + "peerDependencies": { + "svelte": "^5.0.0", + "vite": "^6.0.0" } }, - "node_modules/cmake-js": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.3.1.tgz", - "integrity": "sha512-aJtHDrTFl8qovjSSqXT9aC2jdGfmP8JQsPtjdLAXFfH1BF4/ImZ27Jx0R61TFg8Apc3pl6e2yBKMveAeRXx2Rw==", + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", + "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", "dev": true, "license": "MIT", "dependencies": { - "axios": "^1.6.5", - "debug": "^4", - "fs-extra": "^11.2.0", - "memory-stream": "^1.0.0", - "node-api-headers": "^1.1.0", - "npmlog": "^6.0.2", - "rc": "^1.2.7", - "semver": "^7.5.4", - "tar": "^6.2.0", - "url-join": "^4.0.1", - "which": "^2.0.2", - "yargs": "^17.7.2" - }, - "bin": { - "cmake-js": "bin/cmake-js" + "debug": "^4.3.7" }, "engines": { - "node": ">= 14.15.0" + "node": "^18.0.0 || ^20.0.0 || >=22" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^5.0.0", + "svelte": "^5.0.0", + "vite": "^6.0.0" } }, - "node_modules/cohere-ai": { - "version": "7.17.1", - "resolved": "https://registry.npmjs.org/cohere-ai/-/cohere-ai-7.17.1.tgz", - "integrity": "sha512-GI/uWVYYGIN3gdjJRlbjEaLJNJVXsUJyOlPqwBWgAmK18kP4CJoErxKwU0aLe3tHHOBcC2RqXe6PmGO0dz7dpQ==", - "optional": true, - "dependencies": { - "@aws-sdk/client-sagemaker": "^3.583.0", - "@aws-sdk/credential-providers": "^3.583.0", - "@aws-sdk/protocol-http": "^3.374.0", - "@aws-sdk/signature-v4": "^3.374.0", - "convict": "^6.2.4", - "form-data": "^4.0.0", - "form-data-encoder": "^4.0.2", - "formdata-node": "^6.0.3", - "js-base64": "3.7.2", - "node-fetch": "2.7.0", - "qs": "6.11.2", - "readable-stream": "^4.5.2", - "url-join": "4.0.1" - } - }, - "node_modules/cohere-ai/node_modules/form-data-encoder": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.1.0.tgz", - "integrity": "sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==", + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": ">= 18" + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, - "node_modules/cohere-ai/node_modules/formdata-node": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-6.0.3.tgz", - "integrity": "sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==", + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "license": "MIT", - "optional": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, + "peer": true, "engines": { - "node": ">=12.5.0" + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@tokenizer/inflate": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", + "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "debug": "^4.4.0", + "fflate": "^0.8.2", + "token-types": "^6.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", "license": "MIT" }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "license": "MIT", + "peer": true + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "@types/deep-eql": "*" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "@types/trusted-types": "*" } }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "license": "MIT", - "engines": { - "node": ">= 12" - } + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "node_modules/@types/eventsource": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.1.15.tgz", + "integrity": "sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==", + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", "dev": true, "license": "MIT" }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/@types/mime-types": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz", + "integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==", "dev": true, "license": "MIT" }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true, "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/@types/node": { + "version": "22.15.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", + "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" + "undici-types": "~6.21.0" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/@types/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convict": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", - "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", - "license": "Apache-2.0", - "optional": true, "dependencies": { - "lodash.clonedeep": "^4.5.0", - "yargs-parser": "^20.2.7" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "@types/node": "*", + "form-data": "^4.0.0" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "node_modules/@types/node-int64": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.32.tgz", + "integrity": "sha512-xf/JsSlnXQ+mzvc0IpXemcrO4BrCfpgNpMco+GLcXkFk01k/gW9lGJu+Vof0ZSvHK6DsHJDPSbjFPs36QkWXqw==", "dev": true, "license": "MIT", "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "@types/node": "*" } }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/@types/parquetjs": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@types/parquetjs/-/parquetjs-0.10.6.tgz", + "integrity": "sha512-ZCsD6j97YD0mGU8/VnVs3NjORXa7zeHvqlpJpCqy4jU8a1O21dalL+MFn9QNbdEfy8rszR1N7NHeT7/LdtHf+A==", + "dev": true, "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" + "@types/node-int64": "*" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, "license": "MIT" }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "node_modules/@types/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } + "license": "MIT" }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "license": "MIT" }, - "node_modules/css-background-parser": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", - "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==", + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "license": "MIT" }, - "node_modules/css-box-shadow": { - "version": "1.0.0-3", - "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz", - "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, "license": "MIT" }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "license": "ISC", - "engines": { - "node": ">=4" - } + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "license": "MIT", "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" + "@types/node": "*", + "@types/webidl-conversions": "*" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/@types/yazl": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@types/yazl/-/yazl-3.3.0.tgz", + "integrity": "sha512-mFL6lGkk2N5u5nIxpNV/K5LW3qVSbxhJrMxYGOOxZndWxMgCamr/iCsq/1t9kd8pEwhuNP91LC5qZm/qS9pOEw==", + "dev": true, "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" + "dependencies": { + "@types/node": "*" } }, - "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=14" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", - "license": "MIT", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=14" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.21.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": ">=0.11" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=6.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "typescript": { "optional": true } } }, - "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", - "license": "MIT" - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "license": "MIT", "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, "engines": { - "node": ">=0.4.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/@unhead/schema": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.20.tgz", + "integrity": "sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==", "license": "MIT", - "engines": { - "node": ">= 0.8" + "dependencies": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "node_modules/@vitest/browser": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.2.tgz", + "integrity": "sha512-LJk8ZhCGhgG6G6jFFJ9LX83ibRY8FszLuu9zPaYFDrcHbBwNXwt1v06HRs/vHVYxwjw3/BGzSIgn9Et2P6rCiA==", "license": "MIT", "peer": true, - "engines": { - "node": ">=6" + "dependencies": { + "@testing-library/dom": "^10.4.0", + "@testing-library/user-event": "^14.6.1", + "@vitest/mocker": "3.2.2", + "@vitest/utils": "3.2.2", + "magic-string": "^0.30.17", + "sirv": "^3.0.1", + "tinyrainbow": "^2.0.0", + "ws": "^8.18.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "playwright": "*", + "vitest": "3.2.2", + "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/@vitest/expect": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", + "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.2", + "@vitest/utils": "3.2.2", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "node_modules/@vitest/mocker": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", + "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "license": "MIT" - }, - "node_modules/devalue": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", - "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", - "dev": true, - "license": "MIT" - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "license": "Apache-2.0" + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "node_modules/@vitest/pretty-format": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", + "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, + "node_modules/@vitest/runner": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", + "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "@vitest/utils": "3.2.2", + "pathe": "^2.0.3" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "node_modules/@vitest/runner/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "license": "MIT" }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@vitest/snapshot": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", + "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "@vitest/pretty-format": "3.2.2", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "license": "MIT", - "peer": true + "node_modules/@vitest/snapshot/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/@vitest/spy": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", + "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "tinyspy": "^4.0.3" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "node_modules/@vitest/utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", + "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.2", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=6.5" } }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">=0.4.0" } }, - "node_modules/dompurify": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", - "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/dotenv": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", - "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", - "license": "BSD-2-Clause", + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 14" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "humanize-ms": "^1.2.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 8.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", - "license": "ISC" - }, - "node_modules/elysia": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.3.4.tgz", - "integrity": "sha512-kAfM3Zwovy3z255IZgTKVxBw91HbgKhYl3TqrGRdZqqr+Fd+4eKOfvxgaKij22+MZLczPzIHtscAmvfpI3+q/A==", + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "license": "MIT", "dependencies": { - "cookie": "^1.0.2", - "exact-mirror": "0.1.2", - "fast-decode-uri-component": "^1.0.1" + "environment": "^1.0.0" }, - "optionalDependencies": { - "@sinclair/typebox": "^0.34.33", - "openapi-types": "^12.1.3" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "@sinclair/typebox": ">= 0.34.0", - "exact-mirror": ">= 0.0.9", - "file-type": ">= 20.0.0", - "openapi-types": ">= 12.0.0", - "typescript": ">= 5.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/elysia/node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, "engines": { - "node": ">= 0.8" + "node": ">= 8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", - "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/env-var": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/env-var/-/env-var-7.5.0.tgz", - "integrity": "sha512-mKZOzLRN0ETzau2W2QXefbFjo5EF4yWq28OyKb9ICdeNhHJlOE/pHHnz4hdYJ9cNZXcJHo5xN4OT4pzuSHSNvA==", + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "dequal": "^2.0.3" } }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=8.0.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", - "hasInstallScript": true, - "license": "MIT", "bin": { - "esbuild": "bin/esbuild" + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=18" + "node": "^10 || ^12 || >=14" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "license": "BSD-2-Clause", + "node_modules/bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha512-u4cBQNepWxYA55FunZSM7wMi55yQaN0otnhhilNoWHq0MfOfJeQx0v0mRRpolGOExPjZcl6FtB0BB8Xkb88F0g==", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" }, "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">=8" } }, - "node_modules/escodegen/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browserslist": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "browserslist": "cli.js" }, "engines": { - "node": ">=4" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", + "node_modules/bson": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": ">=14.20.1" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "node_modules/bson-objectid": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-2.0.4.tgz", + "integrity": "sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": "*" } }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/bufferutil": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.14.2" } }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" } }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, - "bin": { - "eslint": "bin/eslint.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001721", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", + "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/eslint-compat-utils": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", - "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", - "dev": true, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { - "semver": "^7.5.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, - "peerDependencies": { - "eslint": ">=6.0.0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", - "dev": true, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": ">= 16" } }, - "node_modules/eslint-plugin-svelte": { - "version": "2.46.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz", - "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@jridgewell/sourcemap-codec": "^1.4.15", - "eslint-compat-utils": "^0.5.1", - "esutils": "^2.0.3", - "known-css-properties": "^0.35.0", - "postcss": "^8.4.38", - "postcss-load-config": "^3.1.4", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.1.0", - "semver": "^7.6.2", - "svelte-eslint-parser": "^0.43.0" + "readdirp": "^4.0.1" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0", - "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "svelte": { - "optional": true - } + "url": "https://paulmillr.com/funding/" } }, - "node_modules/eslint-plugin-svelte/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=12" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/esm-env": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", - "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", - "license": "MIT" - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/esprima": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", - "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=12.5.0" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10" + "node": ">=7.0.0" } }, - "node_modules/esrap": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.7.tgz", - "integrity": "sha512-0ZxW6guTF/AeKeKi7he93lmgv7Hx7giD1tBrOeVqkqsZGQJd2/kfnL7LdIsr9FT/AtkBK9XeDTov+gxprBqdEg==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.8" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 12" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, "license": "MIT" }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dev": true, "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, "engines": { - "node": ">=6" + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.8.x" + "node": ">= 8" } }, - "node_modules/eventsource": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", - "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", - "license": "MIT", + "node_modules/css-background-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", + "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==", + "license": "MIT" + }, + "node_modules/css-box-shadow": { + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz", + "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==", + "license": "MIT" + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", "engines": { - "node": ">=12.0.0" + "node": ">=4" } }, - "node_modules/eventsource-parser": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.2.tgz", - "integrity": "sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==", + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", "license": "MIT", - "engines": { - "node": ">=18.0.0" + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" } }, - "node_modules/exact-mirror": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exact-mirror/-/exact-mirror-0.1.2.tgz", - "integrity": "sha512-wFCPCDLmHbKGUb8TOi/IS7jLsgR8WVDGtDK3CzcB4Guf/weq7G+I+DkXiRSZfbemBFOxOINKpraM6ml78vo8Zw==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "license": "MIT", - "peerDependencies": { - "@sinclair/typebox": "^0.34.15" + "bin": { + "cssesc": "bin/cssesc" }, - "peerDependenciesMeta": { - "@sinclair/typebox": { - "optional": true - } + "engines": { + "node": ">=4" } }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "@babel/runtime": "^7.21.0" }, "engines": { - "node": ">=16.17" + "node": ">=0.11" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/execa/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, - "node_modules/expect-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", - "license": "Apache-2.0", + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=12.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" + "node": ">=0.10.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.4.0" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "peer": true, + "engines": { + "node": ">=6" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/exsolve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-content-type-parse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", - "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "node_modules/devalue": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", "license": "MIT" }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "path-type": "^4.0.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=8" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "is-glob": "^4.0.1" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 6" + "node": ">=6.0.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "license": "MIT", + "peer": true }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "license": "MIT" + "node_modules/dompurify": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", + "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "license": "MIT", + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, - "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, - "bin": { - "fxparser": "src/cli/cli.js" + "engines": { + "node": ">= 0.4" } }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, - "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "node_modules/electron-to-chromium": { + "version": "1.5.165", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", + "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "license": "ISC" + }, + "node_modules/elysia": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.3.4.tgz", + "integrity": "sha512-kAfM3Zwovy3z255IZgTKVxBw91HbgKhYl3TqrGRdZqqr+Fd+4eKOfvxgaKij22+MZLczPzIHtscAmvfpI3+q/A==", "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" + "dependencies": { + "cookie": "^1.0.2", + "exact-mirror": "0.1.2", + "fast-decode-uri-component": "^1.0.1" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "optionalDependencies": { + "@sinclair/typebox": "^0.34.33", + "openapi-types": "^12.1.3" + }, + "peerDependencies": { + "@sinclair/typebox": ">= 0.34.0", + "exact-mirror": ">= 0.0.9", + "file-type": ">= 20.0.0", + "openapi-types": ">= 12.0.0", + "typescript": ">= 5.0.0" + } + }, + "node_modules/elysia/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/fetch-event-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/fetch-event-stream/-/fetch-event-stream-0.1.5.tgz", - "integrity": "sha512-V1PWovkspxQfssq/NnxoEyQo1DV+MRK/laPuPblIZmSjMN8P5u46OhlFQznSr9p/t0Sp8Uc6SbM3yCMfr0KU8g==", - "license": "MIT" - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "license": "MIT" }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "once": "^1.4.0" } }, - "node_modules/file-type": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", - "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.7", - "strtok3": "^10.2.2", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, + "node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=20" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/filename-reserved-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", - "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", - "dev": true, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/filenamify": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", - "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", - "dev": true, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^3.0.0" - }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=8" + "node": ">=18" }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { "node": ">=10" }, @@ -10260,1241 +4676,1177 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatbuffers": { - "version": "25.2.10", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.2.10.tgz", - "integrity": "sha512-7JlN9ZvLDG1McO3kbX0k4v+SUAg48L1rIwEvN6ZQl/eCtgJz9UylTMzE9wrmYrcorgxm3CX/3T/w5VAub99UUw==", - "license": "Apache-2.0" - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=14" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "semver": "^7.5.4" }, "engines": { - "node": ">= 6" + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" } }, - "node_modules/form-data-encoder": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", - "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, "license": "MIT", - "optional": true + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } }, - "node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "node_modules/eslint-plugin-svelte": { + "version": "2.46.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz", + "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" + "@eslint-community/eslint-utils": "^4.4.0", + "@jridgewell/sourcemap-codec": "^1.4.15", + "eslint-compat-utils": "^0.5.1", + "esutils": "^2.0.3", + "known-css-properties": "^0.35.0", + "postcss": "^8.4.38", + "postcss-load-config": "^3.1.4", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.1.0", + "semver": "^7.6.2", + "svelte-eslint-parser": "^0.43.0" }, "engines": { - "node": ">= 12.20" + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0", + "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/eslint-plugin-svelte/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "license": "MIT", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": "*" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" + "url": "https://opencollective.com/eslint" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 0.6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 8" + "node": "*" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "license": "MIT" + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "yallist": "^4.0.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" + "estraverse": "^5.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=0.10" } }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/esrap": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.7.tgz", + "integrity": "sha512-0ZxW6guTF/AeKeKi7he93lmgv7Hx7giD1tBrOeVqkqsZGQJd2/kfnL7LdIsr9FT/AtkBK9XeDTov+gxprBqdEg==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" } }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/gaxios": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", - "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^9.0.1" - }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=14" + "node": ">=4.0" } }, - "node_modules/gaxios/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" }, - "node_modules/gcp-metadata": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", - "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^6.1.1", - "google-logging-utils": "^0.0.2", - "json-bigint": "^1.0.0" - }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=14" + "node": ">=0.10.0" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.x" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/exact-mirror": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exact-mirror/-/exact-mirror-0.1.2.tgz", + "integrity": "sha512-wFCPCDLmHbKGUb8TOi/IS7jLsgR8WVDGtDK3CzcB4Guf/weq7G+I+DkXiRSZfbemBFOxOINKpraM6ml78vo8Zw==", "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "peerDependencies": { + "@sinclair/typebox": "^0.34.15" }, - "engines": { - "node": ">= 0.4" + "peerDependenciesMeta": { + "@sinclair/typebox": { + "optional": true + } } }, - "node_modules/get-stream": { + "node_modules/execa": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, "engines": { - "node": ">=16" + "node": ">=16.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", "engines": { - "node": "*" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, + "node_modules/expect-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", + "license": "Apache-2.0", "engines": { - "node": ">=10.13.0" + "node": ">=12.0.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/exsolve": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", + "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "license": "MIT" }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "license": "BSD-3-Clause", - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "license": "MIT" }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.6.0" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "license": "MIT", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, + "license": "MIT" + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/google-auth-library": { - "version": "9.15.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", - "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14" - } + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" }, - "node_modules/google-logging-utils": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", - "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/fdir": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, + "node_modules/fetch-event-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/fetch-event-stream/-/fetch-event-stream-0.1.5.tgz", + "integrity": "sha512-V1PWovkspxQfssq/NnxoEyQo1DV+MRK/laPuPblIZmSjMN8P5u46OhlFQznSr9p/t0Sp8Uc6SbM3yCMfr0KU8g==", "license": "MIT" }, - "node_modules/graphql": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", - "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" }, - "node_modules/gtoken": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", - "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "license": "MIT", "dependencies": { - "gaxios": "^6.0.0", - "jws": "^4.0.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=14.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/guid-typescript": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", - "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", - "license": "ISC" - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/file-type": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", + "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "@tokenizer/inflate": "^0.2.7", + "strtok3": "^10.2.2", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=0.4.7" + "node": ">=20" }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "license": "MIT", - "bin": { - "he": "bin/he" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/headers-polyfill": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", - "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", - "license": "MIT" - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, - "node_modules/hex-rgb": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz", - "integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==", + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "license": "MIT", "engines": { - "node": ">=6" + "node": ">=4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/highlight.js": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", - "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", - "license": "BSD-3-Clause", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, "engines": { - "node": ">=12.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/hono": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.7.11.tgz", - "integrity": "sha512-rv0JMwC0KALbbmwJDEnxvQCeJh+xbS3KEWW5PC9cMJ08Ur9xgatI0HmtgYZfOdOSOeYsp5LO2cOhdI8cLEbDEQ==", - "dev": true, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "license": "MIT", - "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, "engines": { - "node": ">=16.9.0" + "node": ">= 6" } }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", "license": "MIT" }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", "license": "MIT", "dependencies": { - "whatwg-encoding": "^2.0.0" + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" }, "engines": { - "node": ">=12" + "node": ">= 12.20" } }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": "*" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "type": "patreon", + "url": "https://github.com/sponsors/rawify" } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=14.14" } }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { - "node": ">= 6" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "license": "MIT", - "dependencies": { - "debug": "4" - }, "engines": { - "node": ">= 6.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, - "node_modules/http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "bin": { - "http-server": "bin/http-server" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 0.4" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "license": "Apache-2.0", + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "license": "MIT", "engines": { - "node": ">=16.17.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "license": "MIT", - "optional": true, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", - "license": "MIT", - "bin": { - "husky": "bin.js" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=18" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/typicode" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" + "node": ">=10.13.0" + } }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/image-size": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", - "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", - "license": "MIT", + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16.x" + "node": "*" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, "engines": { - "node": ">=0.8.19" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "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.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/int53": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/int53/-/int53-0.2.4.tgz", - "integrity": "sha512-a5jlKftS7HUOhkUyYD7j2sJ/ZnvWiNlZS1ldR+g1ifQ+/UuZXIE+YTc/lK1qGj/GwAU5F8Z0e1eVq2t1J5Ob2g==", - "license": "BSD-3-Clause" + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "license": "MIT", "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">= 12" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/ipull": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/ipull/-/ipull-3.9.2.tgz", - "integrity": "sha512-YbCDsqcf0ytc3b8304ygBlvRtKJTvyygkQX2xcmPkih6vdVKbRw13pDdtSR+vEqLql3owyuPj9m6iT6IfwFaCg==", - "dev": true, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", - "dependencies": { - "@tinyhttp/content-disposition": "^2.2.0", - "async-retry": "^1.3.3", - "chalk": "^5.3.0", - "ci-info": "^4.0.0", - "cli-spinners": "^2.9.2", - "commander": "^10.0.0", - "eventemitter3": "^5.0.1", - "filenamify": "^6.0.0", - "fs-extra": "^11.1.1", - "is-unicode-supported": "^2.0.0", - "lifecycle-utils": "^1.3.1", - "lodash.debounce": "^4.0.8", - "lowdb": "^7.0.1", - "pretty-bytes": "^6.1.0", - "pretty-ms": "^8.0.0", - "sleep-promise": "^9.1.0", - "slice-ansi": "^7.1.0", - "stdout-update": "^4.0.1", - "strip-ansi": "^7.1.0" - }, - "bin": { - "ipull": "dist/cli/cli.js" - }, "engines": { - "node": ">=18.0.0" + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/ido-pluto/ipull?sponsor=1" - }, - "optionalDependencies": { - "@reflink/reflink": "^0.1.16" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ipull/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ipull/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/ipull/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "license": "MIT" + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/hex-rgb": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.3.0.tgz", + "integrity": "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/ipull/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, "engines": { - "node": ">=14" + "node": ">= 14" } }, - "node_modules/ipull/node_modules/is-fullwidth-code-point": { + "node_modules/human-signals": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.0.0" + "bin": { + "husky": "bin.js" }, "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/ipull/node_modules/lifecycle-utils": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-1.7.3.tgz", - "integrity": "sha512-T7zs7J6/sgsqwVyG34Sfo5LTQmlPmmqaUe3yBhdF8nq24RtR/HtbkNZRhNbr9BEaKySdSgH+P9H5U9X+p0WjXw==", - "dev": true, - "license": "MIT" + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/ipull/node_modules/parse-ms": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz", - "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/ipull/node_modules/pretty-ms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", - "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { - "parse-ms": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ipull/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=0.8.19" } }, - "node_modules/ipull/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "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.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, + "license": "ISC" + }, + "node_modules/int53": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/int53/-/int53-0.2.4.tgz", + "integrity": "sha512-a5jlKftS7HUOhkUyYD7j2sJ/ZnvWiNlZS1ldR+g1ifQ+/UuZXIE+YTc/lK1qGj/GwAU5F8Z0e1eVq2t1J5Ob2g==", + "license": "BSD-3-Clause" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 12" } }, - "node_modules/ipull/stub/@reflink/reflink": { - "dev": true, - "optional": true - }, "node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", @@ -11561,19 +5913,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -11606,25 +5945,11 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "license": "MIT" - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, "license": "MIT" }, "node_modules/is-reference": { @@ -11641,22 +5966,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11920,15 +6233,6 @@ "jiti": "bin/jiti.js" } }, - "node_modules/jose": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", - "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -11938,13 +6242,6 @@ "node": ">=10" } }, - "node_modules/js-base64": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", - "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==", - "license": "BSD-3-Clause", - "optional": true - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11971,82 +6268,6 @@ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "license": "MIT" }, - "node_modules/jsdom": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", - "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", - "license": "MIT", - "dependencies": { - "abab": "^2.0.6", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", - "decimal.js": "^10.4.3", - "domexception": "^4.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -12058,6 +6279,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -12067,12 +6289,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -12086,9 +6302,9 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -12098,57 +6314,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonpath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", - "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", - "license": "MIT", - "dependencies": { - "esprima": "1.2.2", - "static-eval": "2.0.2", - "underscore": "1.12.1" - } - }, - "node_modules/jsonrepair": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.12.0.tgz", - "integrity": "sha512-SWfjz8SuQ0wZjwsxtSJ3Zy8vvLg6aO/kxcp9TWNPGwJKgTZVfhNEQBMk/vPOpYCDFWRxD6QWuI6IHR1t615f0w==", - "dev": true, - "license": "ISC", - "bin": { - "jsonrepair": "bin/cli.js" - } - }, - "node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/katex": { "version": "0.16.22", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", @@ -12213,13 +6378,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lifecycle-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lifecycle-utils/-/lifecycle-utils-2.0.0.tgz", - "integrity": "sha512-KIkV6NeD2n0jZnO+fdIGKI5Or7alyhb6UTFzeaqf6EnE5y3pdK821+kd7yOMBUL/sPYhHU5ny74J0QKslLikGw==", - "dev": true, - "license": "MIT" - }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -12364,20 +6522,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "license": "MIT", - "optional": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -12392,23 +6536,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-symbols": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", - "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -12498,33 +6625,11 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "license": "MIT" - }, - "node_modules/lowdb": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz", - "integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==", - "dev": true, - "license": "MIT", - "dependencies": { - "steno": "^4.0.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "license": "MIT" }, "node_modules/lru-cache": { "version": "6.0.0", @@ -12594,13 +6699,6 @@ "semver": "bin/semver.js" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true, - "license": "ISC" - }, "node_modules/marked": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", @@ -12613,18 +6711,6 @@ "node": ">= 18" } }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -12634,64 +6720,13 @@ "node": ">= 0.4" } }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memjs": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/memjs/-/memjs-1.3.2.tgz", - "integrity": "sha512-qUEg2g8vxPe+zPn09KidjIStHPtoBO8Cttm8bgJFWWabbsjQ9Av9Ky+6UcvKx6ue0LLb/LEhtcyQpRyKfzeXcg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "devOptional": true, "license": "MIT" }, - "node_modules/memory-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", - "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^3.4.0" - } - }, - "node_modules/memory-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12707,15 +6742,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -12741,18 +6767,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -12832,46 +6846,6 @@ "node": ">=8" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mlly": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", @@ -13011,281 +6985,31 @@ "version": "11.0.5", "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.20.1" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/gaxios": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", - "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/gcp-metadata": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", - "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "gaxios": "^5.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/mongodb": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz", - "integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.0" - }, - "engines": { - "node": ">=16.20.1" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", - "gcp-metadata": "^5.2.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", - "socks": "^2.7.1" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-memory-server-core/node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/mongodb-memory-server-core/node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/mongoose": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.15.1.tgz", - "integrity": "sha512-RhQ4DzmBi5BNGcS0w4u1vdMRIKcteXTCNzDt1j7XRcdWYBz1MjMjulBhPaeC5jBCHOD1yinuOFTTSOWLLGexWw==", - "license": "MIT", - "dependencies": { - "bson": "^6.10.3", - "kareem": "2.6.3", - "mongodb": "~6.16.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "17.1.3" - }, - "engines": { - "node": ">=16.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mongoose/node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/mongoose/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" + "@types/webidl-conversions": "*" } }, - "node_modules/mongoose/node_modules/bson": { + "node_modules/mongodb-memory-server-core/node_modules/bson": { "version": "6.10.4", "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=16.20.1" } }, - "node_modules/mongoose/node_modules/gaxios": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", - "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongoose/node_modules/gcp-metadata": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", - "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "gaxios": "^5.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mongoose/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.16.0.tgz", - "integrity": "sha512-D1PNcdT0y4Grhou5Zi/qgipZOYeWrhLEpk33n3nm6LGtz61jvO88WlrWCK/bigMjpnOdAUKKQwsGIl0NtWMyYw==", + "node_modules/mongodb-memory-server-core/node_modules/mongodb": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz", + "integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.3", + "bson": "^6.10.4", "mongodb-connection-string-url": "^3.0.0" }, "engines": { @@ -13324,20 +7048,22 @@ } } }, - "node_modules/mongoose/node_modules/mongodb-connection-string-url": { + "node_modules/mongodb-memory-server-core/node_modules/mongodb-connection-string-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@types/whatwg-url": "^11.0.2", "whatwg-url": "^14.1.0 || ^13.0.0" } }, - "node_modules/mongoose/node_modules/tr46": { + "node_modules/mongodb-memory-server-core/node_modules/tr46": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -13346,10 +7072,11 @@ "node": ">=18" } }, - "node_modules/mongoose/node_modules/whatwg-url": { + "node_modules/mongodb-memory-server-core/node_modules/whatwg-url": { "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, "license": "MIT", "dependencies": { "tr46": "^5.1.0", @@ -13359,27 +7086,6 @@ "node": ">=18" } }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "license": "MIT", - "dependencies": { - "debug": "4.x" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -13505,32 +7211,6 @@ "node": "^18 || >=20" } }, - "node_modules/natural": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/natural/-/natural-8.1.0.tgz", - "integrity": "sha512-qHKU+BzPXzEDwToFBzlI+3oI2jeN3xRNP421ifoF2Fw7ej+5zEO3Z5wUKPjz00jhz9/ESerIUGfhPqqkOqlWPA==", - "license": "MIT", - "dependencies": { - "afinn-165": "^1.0.2", - "afinn-165-financialmarketnews": "^3.0.0", - "apparatus": "^0.0.10", - "dotenv": "^16.4.5", - "http-server": "^14.1.1", - "memjs": "^1.3.2", - "mongoose": "^8.2.0", - "pg": "^8.11.3", - "redis": "^4.6.13", - "safe-stable-stringify": "^2.2.0", - "stopwords-iso": "^1.1.0", - "sylvester": "^0.0.12", - "underscore": "^1.9.1", - "uuid": "^9.0.1", - "wordnet-db": "^3.1.11" - }, - "engines": { - "node": ">=0.4.10" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13538,28 +7218,6 @@ "dev": true, "license": "MIT" }, - "node_modules/natural/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -13579,23 +7237,6 @@ "node": ">=12.22.0" } }, - "node_modules/node-addon-api": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", - "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, - "node_modules/node-api-headers": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.5.0.tgz", - "integrity": "sha512-Yi/FgnN8IU/Cd6KeLxyHkylBUvDTsSScT0Tna2zTrz8klmc8qF2ppj6Q1LHsmOueJWhigQwR4cO2p0XBGW5IaQ==", - "dev": true, - "license": "MIT" - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -13612,7 +7253,6 @@ } ], "license": "MIT", - "optional": true, "engines": { "node": ">=10.5.0" } @@ -13676,202 +7316,6 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "license": "MIT" }, - "node_modules/node-llama-cpp": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/node-llama-cpp/-/node-llama-cpp-3.9.0.tgz", - "integrity": "sha512-ogJhT7aZQLO3j3R7zdR4l6ym1QGxuTK0LaHHT5j3ObkcCMvkS8CkbsdarYdd5ScJ/OssfTp+PbGnwARWwSRVOA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@huggingface/jinja": "^0.5.0", - "async-retry": "^1.3.3", - "bytes": "^3.1.2", - "chalk": "^5.4.1", - "chmodrp": "^1.0.2", - "cmake-js": "^7.3.1", - "cross-env": "^7.0.3", - "cross-spawn": "^7.0.6", - "env-var": "^7.5.0", - "filenamify": "^6.0.0", - "fs-extra": "^11.3.0", - "ignore": "^7.0.4", - "ipull": "^3.9.2", - "is-unicode-supported": "^2.1.0", - "lifecycle-utils": "^2.0.0", - "log-symbols": "^7.0.0", - "nanoid": "^5.1.5", - "node-addon-api": "^8.3.1", - "octokit": "^4.1.3", - "ora": "^8.2.0", - "pretty-ms": "^9.2.0", - "proper-lockfile": "^4.1.2", - "semver": "^7.7.1", - "simple-git": "^3.27.0", - "slice-ansi": "^7.1.0", - "stdout-update": "^4.0.1", - "strip-ansi": "^7.1.0", - "validate-npm-package-name": "^6.0.0", - "which": "^5.0.0", - "yargs": "^17.7.2" - }, - "bin": { - "nlc": "dist/cli/cli.js", - "node-llama-cpp": "dist/cli/cli.js" - }, - "engines": { - "node": ">=20.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/giladgd" - }, - "optionalDependencies": { - "@node-llama-cpp/linux-arm64": "3.9.0", - "@node-llama-cpp/linux-armv7l": "3.9.0", - "@node-llama-cpp/linux-x64": "3.9.0", - "@node-llama-cpp/linux-x64-cuda": "3.9.0", - "@node-llama-cpp/linux-x64-vulkan": "3.9.0", - "@node-llama-cpp/mac-arm64-metal": "3.9.0", - "@node-llama-cpp/mac-x64": "3.9.0", - "@node-llama-cpp/win-arm64": "3.9.0", - "@node-llama-cpp/win-x64": "3.9.0", - "@node-llama-cpp/win-x64-cuda": "3.9.0", - "@node-llama-cpp/win-x64-vulkan": "3.9.0" - }, - "peerDependencies": { - "typescript": ">=5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/node-llama-cpp/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/node-llama-cpp/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/node-llama-cpp/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/node-llama-cpp/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/node-llama-cpp/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/node-llama-cpp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/node-llama-cpp/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/node-llama-cpp/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/node-llama-cpp/node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -13923,27 +7367,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/nwsapi": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", + "dev": true, "license": "MIT" }, "node_modules/object-assign": { @@ -13964,27 +7392,6 @@ "node": ">= 6" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/object-stream": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/object-stream/-/object-stream-0.0.1.tgz", @@ -13993,29 +7400,6 @@ "node": ">=0.10" } }, - "node_modules/octokit": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/octokit/-/octokit-4.1.4.tgz", - "integrity": "sha512-cRvxRte6FU3vAHRC9+PMSY3D+mRAs2Rd9emMoqp70UGRvJRM3sbAoim2IXRZNNsf8wVfn4sGxVBHRAP+JBVX/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/app": "^15.1.6", - "@octokit/core": "^6.1.5", - "@octokit/oauth-app": "^7.1.6", - "@octokit/plugin-paginate-graphql": "^5.2.4", - "@octokit/plugin-paginate-rest": "^12.0.0", - "@octokit/plugin-rest-endpoint-methods": "^14.0.0", - "@octokit/plugin-retry": "^7.2.1", - "@octokit/plugin-throttling": "^10.0.0", - "@octokit/request-error": "^6.1.8", - "@octokit/types": "^14.0.0", - "@octokit/webhooks": "^13.8.3" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/oidc-token-hash": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", @@ -14034,18 +7418,6 @@ "node": ">=14.0.0" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -14070,126 +7442,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onnxruntime-common": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", - "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", - "license": "MIT" - }, - "node_modules/onnxruntime-node": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", - "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", - "hasInstallScript": true, - "license": "MIT", - "os": [ - "win32", - "darwin", - "linux" - ], - "dependencies": { - "global-agent": "^3.0.0", - "onnxruntime-common": "1.21.0", - "tar": "^7.0.1" - } - }, - "node_modules/onnxruntime-node/node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/onnxruntime-node/node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/onnxruntime-node/node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/onnxruntime-node/node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-web": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", - "license": "MIT", - "dependencies": { - "flatbuffers": "^25.1.24", - "guid-typescript": "^1.0.9", - "long": "^5.2.3", - "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", - "platform": "^1.3.6", - "protobufjs": "^7.2.4" - } - }, - "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", - "license": "MIT" - }, "node_modules/openai": { "version": "4.104.0", "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", "license": "Apache-2.0", - "optional": true, "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -14220,7 +7477,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.111.tgz", "integrity": "sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==", "license": "MIT", - "optional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -14229,8 +7485,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/openapi-types": { "version": "12.1.3", @@ -14238,15 +7493,6 @@ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "license": "MIT" }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" - } - }, "node_modules/openid-client": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", @@ -14289,102 +7535,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -14505,29 +7655,11 @@ "hex-rgb": "^4.1.0" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", - "license": "MIT" - }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -14536,15 +7668,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -14600,148 +7723,53 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/peek-readable": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", - "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/pg": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.0.tgz", - "integrity": "sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==", - "license": "MIT", - "dependencies": { - "pg-connection-string": "^2.9.0", - "pg-pool": "^3.10.0", - "pg-protocol": "^1.10.0", - "pg-types": "2.2.0", - "pgpass": "1.0.5" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.2.5" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", - "integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.0.tgz", - "integrity": "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==", - "license": "MIT" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } + "license": "ISC" }, - "node_modules/pg-pool": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.0.tgz", - "integrity": "sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" + "engines": { + "node": ">=8" } }, - "node_modules/pg-protocol": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.0.tgz", - "integrity": "sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==", + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "license": "MIT" }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">= 14.16" } }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "node_modules/peek-readable": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", + "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", "license": "MIT", - "dependencies": { - "split2": "^4.1.0" + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -14852,15 +7880,6 @@ "node": ">= 6" } }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -14949,55 +7968,6 @@ "dev": true, "license": "MIT" }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", - "license": "MIT" - }, - "node_modules/playwright": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", - "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.52.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", - "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/portfinder": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz", - "integrity": "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw==", - "license": "MIT", - "dependencies": { - "async": "^3.2.6", - "debug": "^4.3.6" - }, - "engines": { - "node": ">= 10.12" - } - }, "node_modules/postcss": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", @@ -15232,45 +8202,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -15387,19 +8318,6 @@ } } }, - "node_modules/pretty-bytes": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", - "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -15428,22 +8346,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pretty-ms": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -15469,93 +8371,6 @@ ], "license": "MIT" }, - "node_modules/prom-client": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz", - "integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.4.0", - "tdigest": "^0.1.1" - }, - "engines": { - "node": "^16 || ^18 || >=20" - } - }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proper-lockfile/node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/proper-lockfile/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/protobufjs": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz", - "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, - "license": "MIT" - }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", @@ -15598,21 +8413,6 @@ "teleport": ">=0.2.0" } }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/quansync": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", @@ -15636,15 +8436,6 @@ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "license": "MIT" }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "license": "MIT", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -15671,68 +8462,6 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -15788,23 +8517,6 @@ "node": ">= 12.13.0" } }, - "node_modules/redis": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz", - "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==", - "license": "MIT", - "workspaces": [ - "./packages/*" - ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.1", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -15881,16 +8593,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -15924,23 +8626,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "license": "BSD-3-Clause", - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/rollup": { "version": "4.41.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", @@ -15977,44 +8662,13 @@ "@rollup/rollup-win32-arm64-msvc": "4.41.1", "@rollup/rollup-win32-ia32-msvc": "4.41.1", "@rollup/rollup-win32-x64-msvc": "4.41.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "license": "MIT" - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "license": "MIT", - "engines": { - "node": ">=16" + "fsevents": "~2.3.2" } }, - "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "license": "MIT" }, "node_modules/run-parallel": { @@ -16086,34 +8740,9 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, "license": "MIT" }, - "node_modules/sanitize-html": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.0.tgz", - "integrity": "sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==", - "license": "MIT", - "dependencies": { - "deepmerge": "^4.2.2", - "escape-string-regexp": "^4.0.0", - "htmlparser2": "^8.0.0", - "is-plain-object": "^5.0.0", - "parse-srcset": "^1.0.2", - "postcss": "^8.3.11" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "license": "MIT", - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/satori": { "version": "0.10.14", "resolved": "https://registry.npmjs.org/satori/-/satori-0.10.14.tgz", @@ -16148,6 +8777,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -16156,21 +8786,6 @@ "node": ">=v12.22.7" } }, - "node_modules/sbd": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/sbd/-/sbd-1.0.19.tgz", - "integrity": "sha512-b5RyZMGSrFuIB4AHdbv12uYHS8YGEJ36gtuvG3RflbJGY+T0dXmAL0E4vZjQqT2RsX0v+ZwVqhV2zsGr5aFK9w==", - "license": "MIT", - "dependencies": { - "sanitize-html": "^2.3.2" - } - }, - "node_modules/secure-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "license": "MIT" - }, "node_modules/secure-json-parse": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", @@ -16198,118 +8813,6 @@ "node": ">=10" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serpapi": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/serpapi/-/serpapi-1.1.1.tgz", - "integrity": "sha512-t5Bqu/6VMJ9naX8K+qCgUStpZOaNQFvIM4AudhMJLS6sqQT/EHaYrhGidDZHVx8QvcEdY6y1wNlxizOCtvJtUQ==", - "license": "MIT", - "dependencies": { - "undici": "^5.12.0" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -16317,12 +8820,6 @@ "dev": true, "license": "MIT" }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -16383,84 +8880,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sift": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", - "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", - "license": "MIT" - }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -16479,22 +8898,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-git": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.28.0.tgz", - "integrity": "sha512-Rs/vQRwsn1ILH1oBUy8NucJlXmnnLeLCfcvbSehkPzbv3wwoFWIdtfd6Ndo6ZPhlPsCZ60CPI4rxurnwAa+a2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.4.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -16528,13 +8931,6 @@ "node": ">=8" } }, - "node_modules/sleep-promise": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz", - "integrity": "sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==", - "dev": true, - "license": "MIT" - }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -16624,6 +9020,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "devOptional": true, "license": "MIT", "dependencies": { "memory-pager": "^1.0.2" @@ -16650,15 +9047,6 @@ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "license": "MIT" }, - "node_modules/static-eval": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", - "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", - "license": "MIT", - "dependencies": { - "escodegen": "^1.8.1" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -16674,112 +9062,6 @@ "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "license": "MIT" }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stdout-update": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/stdout-update/-/stdout-update-4.0.1.tgz", - "integrity": "sha512-wiS21Jthlvl1to+oorePvcyrIkiG/6M3D3VTmDUlJm7Cy6SbFhKkAvX+YBuHLxck/tO3mrdpC/cNesigQc3+UQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^6.2.0", - "ansi-styles": "^6.2.1", - "string-width": "^7.1.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/stdout-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stdout-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/stdout-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/stdout-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/steno": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz", - "integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/stopwords-iso": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stopwords-iso/-/stopwords-iso-1.1.0.tgz", - "integrity": "sha512-I6GPS/E0zyieHehMRPQcqkiBMJKGgLta+1hREixhoLPqEA0AlVFiC43dl8uPpmkkeRdDMzYRWFWk5/l9x7nmNg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/streamx": { "version": "2.22.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz", @@ -16940,24 +9222,12 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/strtok3": { "version": "10.2.2", @@ -17190,18 +9460,11 @@ "@types/estree": "^1.0.6" } }, - "node_modules/sylvester": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/sylvester/-/sylvester-0.0.12.tgz", - "integrity": "sha512-SzRP5LQ6Ts2G5NyAa/jg16s8e3R7rfdFjizy1zeoecYWw+nGL+YA1xZvW/+iJmidBGSdLkuvdwTYEyJEb+EiUw==", - "engines": { - "node": ">=0.2.6" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, "license": "MIT" }, "node_modules/tailwind-scrollbar": { @@ -17370,24 +9633,6 @@ "node": ">=8.10.0" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/tar-stream": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", @@ -17400,16 +9645,6 @@ "streamx": "^2.15.0" } }, - "node_modules/tdigest": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", - "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bintrees": "1.0.2" - } - }, "node_modules/text-decoder": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", @@ -17555,17 +9790,9 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, "license": "MIT" }, - "node_modules/tldts-experimental": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-experimental/-/tldts-experimental-6.1.86.tgz", - "integrity": "sha512-X3N3+SrwSajvANDyIBFa6tf/nO0VoqaXvvINSnQkZMGbzNlD+9G7Xb24Mtk3ZBVZJRGY7UynAJJL8kRVt6Z46Q==", - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.86" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -17578,25 +9805,6 @@ "node": ">=8.0" } }, - "node_modules/toad-cache": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", - "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/token-types": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", @@ -17647,18 +9855,6 @@ "node": ">= 4.0.0" } }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -17678,61 +9874,11 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true, - "license": "MIT" - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "devOptional": true, "license": "0BSD" }, "node_modules/type-check": { @@ -17761,19 +9907,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -17825,24 +9958,6 @@ "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", "license": "MIT" }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", - "license": "MIT" - }, - "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", - "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -17859,31 +9974,6 @@ "tiny-inflate": "^1.0.0" } }, - "node_modules/union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dependencies": { - "qs": "^6.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/universal-github-app-jwt": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.2.tgz", - "integrity": "sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "dev": true, - "license": "ISC" - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -17894,15 +9984,6 @@ "node": ">= 10.0.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/unplugin": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz", @@ -17994,17 +10075,12 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "license": "MIT" - }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -18021,15 +10097,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -18043,38 +10110,12 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-name": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.1.tgz", - "integrity": "sha512-OaI//3H0J7ZkR1OqlhGA8cA+Cbk/2xFOQpJOt5+s27/ta9eZwpeervh4Mxh4w0im/kdgktowaqVNR7QOrUd7Yg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, "node_modules/varint": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", "license": "MIT" }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/vite": { "version": "6.3.5", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", @@ -18305,24 +10346,11 @@ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "license": "MIT" }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "license": "MIT", - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", "license": "MIT", - "optional": true, "engines": { "node": ">= 14" } @@ -18343,52 +10371,6 @@ "dev": true, "license": "MIT" }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", - "license": "MIT", - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -18420,66 +10402,16 @@ "node": ">=8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/wordnet-db": { - "version": "3.1.14", - "resolved": "https://registry.npmjs.org/wordnet-db/-/wordnet-db-3.1.14.tgz", - "integrity": "sha512-zVyFsvE+mq9MCmwXUWHIcpfbrHHClZWZiVOzKSxNJruIcFn2RbY55zkhiAMMxM8zCVSmtNiViq8FsAZSFpMYag==", - "license": "MIT", - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -18616,30 +10548,13 @@ } } }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "license": "Apache-2.0", - "engines": { - "node": ">=12" - } - }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, "license": "MIT" }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -18685,16 +10600,6 @@ "node": ">=12" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -18767,16 +10672,6 @@ "node": ">=8.0.0" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -18790,19 +10685,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yoctocolors-cjs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", @@ -18844,15 +10726,6 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } } } } diff --git a/package.json b/package.json index 5b4807abab8fdf6f6e56c00b0b74ac8ee8d28d70..d033053c0f9a818bbbb0f69d7999dfa9eef5a7ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chat-ui", - "version": "0.10.0", + "version": "0.20.0", "private": true, "packageManager": "npm@9.5.0", "scripts": { @@ -18,9 +18,7 @@ "prepare": "husky" }, "devDependencies": { - "@elysiajs/cors": "^1.3.3", "@elysiajs/eden": "^1.3.2", - "@elysiajs/node": "^1.2.6", "@faker-js/faker": "^8.4.1", "@iconify-json/carbon": "^1.1.16", "@iconify-json/eos-icons": "^1.1.6", @@ -29,17 +27,12 @@ "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/typography": "^0.5.9", "@types/dompurify": "^3.0.5", - "@types/express": "^4.17.21", - "@types/fs-extra": "^11.0.4", "@types/js-yaml": "^4.0.9", - "@types/jsdom": "^21.1.1", - "@types/jsonpath": "^0.2.4", "@types/katex": "^0.16.7", "@types/mime-types": "^2.1.4", "@types/minimist": "^1.2.5", "@types/node": "^22.1.0", "@types/parquetjs": "^0.10.3", - "@types/sbd": "^1.0.5", "@types/uuid": "^9.0.8", "@types/yazl": "^3.3.0", "@typescript-eslint/eslint-plugin": "^6.x", @@ -50,23 +43,19 @@ "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte": "^2.45.1", - "fs-extra": "^11.3.0", + "fs-extra": "^11.3.1", "isomorphic-dompurify": "^2.13.0", "js-yaml": "^4.1.0", - "jsonrepair": "^3.12.0", "minimist": "^1.2.8", "mongodb-memory-server": "^10.1.2", - "node-llama-cpp": "^3.6.0", "prettier": "^3.5.3", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.6.11", - "prom-client": "^15.1.2", "sade": "^1.8.1", "superjson": "^2.2.2", "svelte": "^5.33.3", "svelte-check": "^4.0.0", "svelte-gestures": "^5.1.3", - "ts-node": "^10.9.1", "tslib": "^2.4.1", "typescript": "^5.5.0", "unplugin-icons": "^0.16.1", @@ -77,52 +66,34 @@ }, "type": "module", "dependencies": { - "@aws-sdk/credential-providers": "^3.592.0", - "@cliqz/adblocker-playwright": "^1.34.0", "@elysiajs/swagger": "^1.3.0", "@gradio/client": "^1.8.0", "@huggingface/hub": "^2.2.0", "@huggingface/inference": "^3.12.1", - "@huggingface/mcp-client": "^0.1.1", - "@huggingface/tasks": "^0.19.1", - "@huggingface/transformers": "^3.1.1", "@iconify-json/bi": "^1.1.21", - "@playwright/browser-chromium": "^1.52.0", "@resvg/resvg-js": "^2.6.2", "autoprefixer": "^10.4.14", - "aws-sigv4-fetch": "^4.0.1", - "aws4": "^1.13.0", "date-fns": "^2.29.3", "dotenv": "^16.5.0", - "express": "^4.21.2", "file-type": "^21.0.0", - "google-auth-library": "^9.13.0", "handlebars": "^4.7.8", "highlight.js": "^11.7.0", "husky": "^9.0.11", - "image-size": "^1.2.1", "ip-address": "^9.0.5", - "jose": "^5.3.0", - "jsdom": "^22.0.0", "json5": "^2.2.3", - "jsonpath": "^1.1.1", "katex": "^0.16.21", "lint-staged": "^15.2.7", "marked": "^12.0.1", "mongodb": "^5.8.0", "nanoid": "^5.0.9", - "natural": "^8.1.0", + "openai": "^4.44.0", "openid-client": "^5.4.2", "parquetjs": "^0.11.2", "pino": "^9.0.0", "pino-pretty": "^11.0.0", - "playwright": "^1.52.0", "postcss": "^8.4.31", - "saslprep": "^1.0.3", "satori": "^0.10.11", "satori-html": "^0.3.2", - "sbd": "^1.0.19", - "serpapi": "^1.1.1", "sharp": "^0.33.4", "tailwind-scrollbar": "^3.0.0", "tailwindcss": "^3.4.0", @@ -130,16 +101,6 @@ "vitest-browser-svelte": "^0.1.0", "zod": "^3.22.3" }, - "optionalDependencies": { - "@anthropic-ai/sdk": "^0.32.1", - "@anthropic-ai/vertex-sdk": "^0.4.1", - "@aws-sdk/client-bedrock-runtime": "^3.631.0", - "@google-cloud/vertexai": "^1.1.0", - "@google/generative-ai": "^0.24.0", - "aws4fetch": "^1.0.17", - "cohere-ai": "^7.9.0", - "openai": "^4.44.0" - }, "overrides": { "@reflink/reflink": "file:stub/@reflink/reflink" } diff --git a/scripts/populate.ts b/scripts/populate.ts index 25a415050237a74794f35a647596a40e159a201c..0c12bc18c95e6b6cb6bfcae749e242f0f1bcc7f5 100755 --- a/scripts/populate.ts +++ b/scripts/populate.ts @@ -15,8 +15,6 @@ import type { User } from "../src/lib/types/User"; import type { Assistant } from "../src/lib/types/Assistant"; import type { Conversation } from "../src/lib/types/Conversation"; import type { Settings } from "../src/lib/types/Settings"; -import type { CommunityToolDB, ToolLogoColor, ToolLogoIcon } from "../src/lib/types/Tool"; -import { defaultEmbeddingModel } from "../src/lib/server/embeddingModels.ts"; import { Message } from "../src/lib/types/Message.ts"; import { addChildren } from "../src/lib/utils/tree/addChildren.ts"; @@ -40,7 +38,7 @@ rl.on("close", function () { const samples = fs.readFileSync(path.join(__dirname, "samples.txt"), "utf8").split("\n---\n"); -const possibleFlags = ["reset", "all", "users", "settings", "assistants", "conversations", "tools"]; +const possibleFlags = ["reset", "all", "users", "settings", "assistants", "conversations"]; const argv = minimist(process.argv.slice(2)); const flags = argv["_"].filter((flag) => possibleFlags.includes(flag)); @@ -156,7 +154,6 @@ async function seed() { await collections.settings.deleteMany({}); await collections.assistants.deleteMany({}); await collections.conversations.deleteMany({}); - await collections.tools.deleteMany({}); await collections.migrationResults.deleteMany({}); await collections.semaphores.deleteMany({}); console.log("Reset done"); @@ -186,12 +183,12 @@ async function seed() { userId: user._id, shareConversationsWithModelAuthors: faker.datatype.boolean(0.25), hideEmojiOnSidebar: faker.datatype.boolean(0.25), - ethicsModalAcceptedAt: faker.date.recent({ days: 30 }), activeModel: faker.helpers.arrayElement(modelIds), createdAt: faker.date.recent({ days: 30 }), updatedAt: faker.date.recent({ days: 30 }), disableStream: faker.datatype.boolean(0.25), directPaste: faker.datatype.boolean(0.25), + hidePromptExamples: {}, customPrompts: {}, assistants: [], }; @@ -272,7 +269,7 @@ async function seed() { updatedAt: faker.date.recent({ days: 145 }), model: faker.helpers.arrayElement(modelIds), title: faker.internet.emoji() + " " + faker.hacker.phrase(), - embeddingModel: defaultEmbeddingModel.id, + // embeddings removed in this build messages, rootMessageId: messages[0].id, } satisfies Conversation; @@ -287,80 +284,6 @@ async function seed() { ); console.log("Done creating conversations."); } - - // generate Community Tools - if (flags.includes("tools") || flags.includes("all")) { - const tools = await Promise.all( - faker.helpers.multiple( - () => { - const _id = new ObjectId(); - const displayName = faker.company.catchPhrase(); - const description = faker.company.catchPhrase(); - const color = faker.helpers.arrayElement([ - "purple", - "blue", - "green", - "yellow", - "red", - ]) satisfies ToolLogoColor; - const icon = faker.helpers.arrayElement([ - "wikis", - "tools", - "camera", - "code", - "email", - "cloud", - "terminal", - "game", - "chat", - "speaker", - "video", - ]) satisfies ToolLogoIcon; - const baseUrl = faker.helpers.arrayElement([ - "stabilityai/stable-diffusion-3-medium", - "multimodalart/cosxl", - "gokaygokay/SD3-Long-Captioner", - "xichenhku/MimicBrush", - ]); - - // keep empty for populate for now - - const user: User = faker.helpers.arrayElement(users); - const createdById = user._id; - const createdByName = user.username ?? user.name; - - return { - type: "community" as const, - _id, - createdById, - createdByName, - displayName, - name: displayName.toLowerCase().replace(" ", "_"), - endpoint: "/test", - description, - color, - icon, - baseUrl, - inputs: [], - outputPath: null, - outputType: "str" as const, - showOutput: false, - useCount: faker.number.int({ min: 0, max: 100000 }), - last24HoursUseCount: faker.number.int({ min: 0, max: 1000 }), - createdAt: faker.date.recent({ days: 30 }), - updatedAt: faker.date.recent({ days: 30 }), - searchTokens: generateSearchTokens(displayName), - review: faker.helpers.enumValue(ReviewStatus), - outputComponent: null, - outputComponentIdx: null, - }; - }, - { count: faker.number.int({ min: 10, max: 200 }) } - ) - ); - - await collections.tools.insertMany(tools satisfies CommunityToolDB[]); - } } // run seed diff --git a/server.log b/server.log new file mode 100644 index 0000000000000000000000000000000000000000..9a27281e85b88b6d68f3e9e36d327fcbe1d14e4d --- /dev/null +++ b/server.log @@ -0,0 +1,2 @@ +/Users/vm/.venv/bin/python3: No module named uvicorn +/Users/vm/.venv/bin/python3: No module named uvicorn diff --git a/src/ambient.d.ts b/src/ambient.d.ts index 10d56a1ad2da5a0ea32e2180c6aeb04d39290b8c..406da97f6882cf6aaa3c594e7ac5afb1a96e7fe3 100644 --- a/src/ambient.d.ts +++ b/src/ambient.d.ts @@ -2,3 +2,6 @@ declare module "*.ttf" { const value: ArrayBuffer; export default value; } + +// Legacy helpers removed: web search support is deprecated, so we intentionally +// avoid leaking those shapes into the global ambient types. diff --git a/src/app.html b/src/app.html index 1bf87c74f9fc1402320865bf498eda3219d95146..43f0ca64088ec2bd4f7035c01fcc4d8122ffe020 100644 --- a/src/app.html +++ b/src/app.html @@ -5,15 +5,18 @@ - -
{ - e.preventDefault(); - if (!e.target) { - return; - } - const formData = new FormData(e.target as HTMLFormElement, e.submitter); - - loading = true; - if (files?.[0] && files[0].size > 0) { - formData.set("avatar", files[0]); - } - - if (deleteExistingAvatar === true) { - if (assistant?.avatar) { - // if there is an avatar we explicitly removei t - formData.set("avatar", "null"); - } else { - // else we just remove it from the input - formData.delete("avatar"); - } - } else { - if (files === null) { - formData.delete("avatar"); - } - } - - formData.delete("ragMode"); - - if (ragMode === false || !page.data.enableAssistantsRAG) { - formData.set("ragAllowAll", "false"); - formData.set("ragLinkList", ""); - formData.set("ragDomainList", ""); - } else if (ragMode === "all") { - formData.set("ragAllowAll", "true"); - formData.set("ragLinkList", ""); - formData.set("ragDomainList", ""); - } else if (ragMode === "links") { - formData.set("ragAllowAll", "false"); - formData.set("ragDomainList", ""); - } else if (ragMode === "domains") { - formData.set("ragAllowAll", "false"); - formData.set("ragLinkList", ""); - } - - formData.set("tools", tools.join(",")); - - let response: Response; - if (assistant?._id) { - response = await fetch(`${base}/api/assistant/${assistant._id}`, { - method: "PATCH", - body: formData, - }); - if (response.ok) { - goto(`${base}/settings/assistants/${assistant?._id}`, { invalidateAll: true }); - } else { - if (response.status === 400) { - const data = await response.json(); - errors = data.errors; - } else { - $error = response.statusText; - } - loading = false; - } - } else { - response = await fetch(`${base}/api/assistant`, { - method: "POST", - body: formData, - }); - - if (response.ok) { - const { assistantId } = await response.json(); - goto(`${base}/settings/assistants/${assistantId}`, { invalidateAll: true }); - } else { - if (response.status === 400) { - const data = await response.json(); - errors = data.errors; - } else { - $error = response.statusText; - } - loading = false; - } - } - }} -> - {#if assistant} -

- Edit Assistant: {assistant?.name ?? "assistant"} -

-

- Modifying an existing assistant will propagate the changes to all users. -

- {:else} -

Create new assistant

-

- Create and share your own AI Assistant. All assistants are public -

- {/if} - -
-
-
-
Avatar
- - - {#if (files && files[0]) || (assistant?.avatar && !deleteExistingAvatar)} -
- {#if files && files[0]} - avatar - {:else if assistant?.avatar} - avatar - {/if} - - -
-
- -
- {:else} -
- -
- {/if} -

{getError("avatar")}

-
- - - - - - - - - {#if selectedModel?.tools} -
- Tools - - Experimental - -

- Choose up to 3 community tools that will be used with this assistant. -

-
- - {/if} - {#if page.data.enableAssistantsRAG} -
- Internet access - - - {#if publicConfig.isHuggingChat} - Give feedback - {/if} - - - - - - - - {#if ragMode === "domains"} - - Specify domains and URLs that the application can search, separated by commas. - - - clearError("ragDomainList")} - /> -

{getError("ragDomainList")}

- {/if} - - - {#if ragMode === "links"} - - Specify a maximum of 10 direct URLs that the Assistant will access. HTML & Plain Text - only, separated by commas - - clearError("ragLinkList")} - /> -

{getError("ragLinkList")}

- {/if} -
- {/if} -
- -
-
- Instructions (System Prompt) - {#if dynamicPrompt && templateVariables.length} -
- - -
- {/if} -
- - -
- - {#if modelId} - {@const model = models.find((_model) => _model.id === modelId)} - {#if model?.tokenizer && systemPrompt} - - {/if} - {/if} - -

{getError("preprompt")}

-
-
- - Cancel - - -
-
-
-
diff --git a/src/lib/components/AssistantToolPicker.svelte b/src/lib/components/AssistantToolPicker.svelte deleted file mode 100644 index 5661cda502c383f383357568c9c16ea04c6f4482..0000000000000000000000000000000000000000 --- a/src/lib/components/AssistantToolPicker.svelte +++ /dev/null @@ -1,150 +0,0 @@ - - -{#if selectedValues.length > 0} -
- {#each selectedValues as value} -
- {#key value.color + value.icon} - - {/key} -
- {value.displayName} - {#if value.createdByName} -

- Created by - {value.createdByName} -

- {:else} -

Official HuggingChat tool

- {/if} -
- -
- {/each} -
-{/if} - -{#if selectedValues.length < maxValues} -
- { - inputValue = ev.currentTarget.value; - debouncedFetch(inputValue); - }} - disabled={selectedValues.length >= maxValues} - class="w-full rounded border border-gray-200 bg-gray-100 px-3 py-2" - class:opacity-50={selectedValues.length >= maxValues} - class:bg-gray-100={selectedValues.length >= maxValues} - placeholder="Type to search tools..." - tabindex="0" - /> - {#if suggestions.length > 0} - - {/if} -
-{/if} diff --git a/src/lib/components/CodeBlock.svelte b/src/lib/components/CodeBlock.svelte index db8513825d62f5c32a0949769c9ef60cf5b042ce..950f8e5ba80dd84fd999d0179e7b153c96e6ae00 100644 --- a/src/lib/components/CodeBlock.svelte +++ b/src/lib/components/CodeBlock.svelte @@ -1,22 +1,74 @@
+
+
+ {#if showPreview} + + {/if} + +
+
{@html DOMPurify.sanitize(code)}
- + + {#if previewOpen} + (previewOpen = false)} /> + {/if}
diff --git a/src/lib/components/CopyToClipBoardBtn.svelte b/src/lib/components/CopyToClipBoardBtn.svelte index b04953b237e869425a2dcaa10cd8921ec337bffd..ecd6e18e31a6e058c27992d947c100f93f360ef2 100644 --- a/src/lib/components/CopyToClipBoardBtn.svelte +++ b/src/lib/components/CopyToClipBoardBtn.svelte @@ -1,17 +1,26 @@ - - -
-

- - {publicConfig.PUBLIC_APP_NAME} -

- -

- {publicConfig.PUBLIC_APP_DESCRIPTION} -

- -

- {publicConfig.PUBLIC_APP_DISCLAIMER_MESSAGE} -

- -
- - {#if page.data.loginEnabled} - - Sign in - {#if publicConfig.isHuggingChat} - -  with Hugging - Face - - {/if} - - {/if} -
-
-
diff --git a/src/lib/components/EditConversationModal.svelte b/src/lib/components/EditConversationModal.svelte new file mode 100644 index 0000000000000000000000000000000000000000..54badb0f34e73defcc44cdc25dc6c06416222016 --- /dev/null +++ b/src/lib/components/EditConversationModal.svelte @@ -0,0 +1,100 @@ + + +{#if open} + +
{ + e.preventDefault(); + save(); + }} + > +
+

Rename conversation

+ +
+ +
+ + (newTitle = (e.currentTarget as HTMLInputElement).value)} + class="w-full rounded-xl border border-gray-200 bg-white px-3 py-2 text-[15px] text-gray-800 outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 dark:placeholder:text-gray-500 dark:focus:ring-gray-700" + placeholder="Enter a title" + /> +
+ +
+ + +
+
+
+{/if} diff --git a/src/lib/components/HtmlPreviewModal.svelte b/src/lib/components/HtmlPreviewModal.svelte new file mode 100644 index 0000000000000000000000000000000000000000..2ef8c4cffd8f2da39b3442728f2e6b28f1489cbc --- /dev/null +++ b/src/lib/components/HtmlPreviewModal.svelte @@ -0,0 +1,146 @@ + + + onclose?.()}> +
+
+ + + {#if errors.length > 0} + + {/if} +
+
+
diff --git a/src/lib/components/InfiniteScroll.svelte b/src/lib/components/InfiniteScroll.svelte index 52f026b4847aa0610d52e38d68092fc74ecb85f0..ca8926cf11b95c81bf2902cdeb6d219092939254 100644 --- a/src/lib/components/InfiniteScroll.svelte +++ b/src/lib/components/InfiniteScroll.svelte @@ -1,7 +1,11 @@ -
-
-
-
-
+
diff --git a/src/lib/components/LoginModal.svelte b/src/lib/components/LoginModal.svelte index 87b95d5b237baa98d52107687ef3a1f279148c4d..8a04bbc12018bfe0ea6fb7bcebb7712361780dd9 100644 --- a/src/lib/components/LoginModal.svelte +++ b/src/lib/components/LoginModal.svelte @@ -4,16 +4,20 @@ import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte"; import Modal from "$lib/components/Modal.svelte"; - import { useSettingsStore } from "$lib/stores/settings"; import { cookiesAreEnabled } from "$lib/utils/cookiesAreEnabled"; import Logo from "./icons/Logo.svelte"; import { usePublicConfig } from "$lib/utils/PublicConfig.svelte"; const publicConfig = usePublicConfig(); - const settings = useSettingsStore(); + + interface Props { + onclose?: () => void; + } + + let { onclose }: Props = $props(); - + onclose?.()} width="!max-w-[400px] !m-4">
@@ -49,7 +53,7 @@ e.preventDefault(); window.open(window.location.href, "_blank"); } - $settings.ethicsModalAccepted = true; + onclose?.(); }} > Start chatting diff --git a/src/lib/components/MobileNav.svelte b/src/lib/components/MobileNav.svelte index d6d199a00561cb7cf55649e65ff342e7476960f1..a7b5a2f6849d32412c9d7441200cdd394bc83cce 100644 --- a/src/lib/components/MobileNav.svelte +++ b/src/lib/components/MobileNav.svelte @@ -12,10 +12,11 @@ import { base } from "$app/paths"; import { page } from "$app/state"; import IconNew from "$lib/components/icons/IconNew.svelte"; + import IconShare from "$lib/components/icons/IconShare.svelte"; + import IconBurger from "$lib/components/icons/IconBurger.svelte"; import { Spring } from "svelte/motion"; - import CarbonClose from "~icons/carbon/close"; - import CarbonTextAlignJustify from "~icons/carbon/text-align-justify"; import { pan, type GestureCustomEvent, type PanCustomEvent } from "svelte-gestures"; + import { shareModal } from "$lib/stores/shareModal"; interface Props { title: string | undefined; children?: import("svelte").Snippet; @@ -30,6 +31,11 @@ let panStart: number | undefined = $state(undefined); let panStartTime: number | undefined = undefined; + const isHuggingChat = $derived(Boolean(page.data?.publicConfig?.isHuggingChat)); + const canShare = $derived( + isHuggingChat && Boolean(page.params?.id) && page.route.id?.startsWith("/conversation/") + ); + // Define the width for the drawer (less than 100% to create the gap) const drawerWidthPercentage = 85; @@ -74,25 +80,39 @@ @@ -153,17 +173,8 @@ Math.min(0, tween.current) )}%); width: {drawerWidthPercentage}%;" class:shadow-[5px_0_15px_0_rgba(0,0,0,0.3)]={isOpen} - class="fixed bottom-0 left-0 top-0 z-30 grid max-h-screen - grid-cols-1 grid-rows-[auto,1fr,auto,auto] bg-white pt-4 dark:bg-gray-900 md:hidden" + class="fixed bottom-0 left-0 top-0 z-30 grid max-h-screen grid-cols-1 + grid-rows-[auto,1fr,auto,auto] rounded-r-xl bg-white pt-4 dark:bg-gray-900 md:hidden" > - {#if page.url.pathname === base + "/"} - - {/if} {@render children?.()} diff --git a/src/lib/components/Modal.svelte b/src/lib/components/Modal.svelte index 48d16ca8d9c54f29a4687fe270cd9135b98165ba..4b8ebf0168862914053a16cb846d89371ad99c9a 100644 --- a/src/lib/components/Modal.svelte +++ b/src/lib/components/Modal.svelte @@ -1,5 +1,5 @@ @@ -59,23 +71,43 @@ transition:fade|local={{ easing: cubicOut, duration: 300 }} class="fixed inset-0 z-40 flex items-center justify-center bg-black/80 backdrop-blur-sm dark:bg-black/50" > - + {#if disableFly} + + {:else} + + {/if}
diff --git a/src/lib/components/NavConversationItem.svelte b/src/lib/components/NavConversationItem.svelte index ec4d030b319f81561b91c67d83685d3837a9cc98..1266cbd2519c5dcdd21bc4fdbc96eff996c0f770 100644 --- a/src/lib/components/NavConversationItem.svelte +++ b/src/lib/components/NavConversationItem.svelte @@ -1,7 +1,6 @@ -
+
{#if confirmDelete} - Delete - {/if} - {#if conv.avatarUrl} - {#await conv.avatarUrl then avatarUrl} - {#if avatarUrl} - Assistant avatar - {/if} - {/await} - {conv.title.replace(/\p{Emoji}/gu, "")} - {:else if conv.assistantId} -
- {conv.title.replace(/\p{Emoji}/gu, "")} - {:else} - {conv.title} + Delete? {/if} + {conv.title}
- {#if showDescription && description && searchInput} -

- {#each description.split(searchInput) as segment, i}{segment}{#if i < description.split(searchInput).length - 1}{searchInput}{/if} - {/each} -

- {/if}
{#if !readOnly} @@ -93,7 +61,7 @@ onclick={(e) => { e.preventDefault(); confirmDelete = false; - dispatch("deleteConversation", conv.id.toString()); + ondeleteConversation?.(conv.id.toString()); }} > { e.preventDefault(); - const newTitle = prompt("Edit this conversation title:", conv.title); - if (!newTitle) return; - dispatch("editConversationTitle", { id: conv.id.toString(), title: newTitle }); + renameOpen = true; }} > @@ -122,7 +88,7 @@ onclick={(event) => { event.preventDefault(); if (event.shiftKey) { - dispatch("deleteConversation", conv.id.toString()); + ondeleteConversation?.(conv.id.toString()); } else { confirmDelete = true; } @@ -135,3 +101,16 @@ {/if} {/if}
+ + +{#if renameOpen} + (renameOpen = false)} + onsave={(payload) => { + renameOpen = false; + oneditConversationTitle?.({ id: conv.id.toString(), title: payload.title }); + }} + /> +{/if} diff --git a/src/lib/components/NavMenu.svelte b/src/lib/components/NavMenu.svelte index 3d115ff6c0852905544438d69231282335e02e64..926f13004492e9277642bc69bee820de4053e31c 100644 --- a/src/lib/components/NavMenu.svelte +++ b/src/lib/components/NavMenu.svelte @@ -11,6 +11,8 @@ import { base } from "$app/paths"; import Logo from "$lib/components/icons/Logo.svelte"; + import IconSun from "$lib/components/icons/IconSun.svelte"; + import IconMoon from "$lib/components/icons/IconMoon.svelte"; import { switchTheme } from "$lib/switchTheme"; import { isAborted } from "$lib/stores/isAborted"; @@ -18,17 +20,12 @@ import type { LayoutData } from "../../routes/$types"; import type { ConvSidebar } from "$lib/types/ConvSidebar"; import type { Model } from "$lib/types/Model"; - import { page } from "$app/stores"; + import { page } from "$app/state"; import InfiniteScroll from "./InfiniteScroll.svelte"; import { CONV_NUM_PER_PAGE } from "$lib/constants/pagination"; import { goto } from "$app/navigation"; import { browser } from "$app/environment"; - import { toggleSearch } from "./chat/Search.svelte"; - import CarbonSearch from "~icons/carbon/search"; - import { closeMobileNav } from "./MobileNav.svelte"; import { usePublicConfig } from "$lib/utils/PublicConfig.svelte"; - - import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard"; import { useAPIClient, handleResponse } from "$lib/APIClient"; const publicConfig = usePublicConfig(); @@ -39,9 +36,18 @@ canLogin: boolean; user: LayoutData["user"]; p?: number; + ondeleteConversation?: (id: string) => void; + oneditConversationTitle?: (payload: { id: string; title: string }) => void; } - let { conversations = $bindable(), canLogin, user, p = $bindable(0) }: Props = $props(); + let { + conversations = $bindable(), + canLogin, + user, + p = $bindable(0), + ondeleteConversation, + oneditConversationTitle, + }: Props = $props(); let hasMore = $state(true); @@ -66,7 +72,7 @@ older: conversations.filter(({ updatedAt }) => updatedAt.getTime() < dateRanges[2]), }); - const nModels: number = $page.data.models.filter((el: Model) => !el.unlisted).length; + const nModels: number = page.data.models.filter((el: Model) => !el.unlisted).length; async function handleVisible() { p++; @@ -78,7 +84,7 @@ }) .then(handleResponse) .then((r) => r.conversations) - .catch(() => []); + .catch((): ConvSidebar[] => []); if (newConvs.length === 0) { hasMore = false; @@ -102,71 +108,43 @@ class="sticky top-0 flex flex-none touch-none items-center justify-between px-1.5 py-3.5 max-sm:pt-0" > - + {publicConfig.PUBLIC_APP_NAME} - {#if $page.url.pathname !== base + "/"} - - New Chat - - {/if} + + New Chat +
+
- - {#await groupedConversations} - {#if $page.data.nConversations > 0} -
-
-
- {#each Array(100) as _} -
- {/each} -
-
- {/if} - {:then groupedConversations} -
- {#each Object.entries(groupedConversations) as [group, convs]} - {#if convs.length} -

- {titles[group]} -

- {#each convs as conv} - - {/each} - {/if} - {/each} -
- {#if hasMore} - - {/if} - {/await} +
+ {#each Object.entries(groupedConversations) as [group, convs]} + {#if convs.length} +

+ {titles[group]} +

+ {#each convs as conv} + + {/each} + {/if} + {/each} +
+ {#if hasMore} + + {/if}
{#if user?.username || user?.email} diff --git a/src/lib/components/OpenWebSearchResults.svelte b/src/lib/components/OpenWebSearchResults.svelte deleted file mode 100644 index 80f534186a13da98d44c2b69ca8a99d6e29cbf6b..0000000000000000000000000000000000000000 --- a/src/lib/components/OpenWebSearchResults.svelte +++ /dev/null @@ -1,138 +0,0 @@ - - -
- -
- - - - -
-
-
Web Search
-
- {#if sources} - Completed - {:else} - {"message" in lastMessage ? lastMessage.message : "An error occurred"} - {/if} -
-
- -
- -
- {#if webSearchMessages.length === 0} -
- -
- {:else} -
    - {#each webSearchMessages as message} - {#if message.subtype === MessageWebSearchUpdateType.Update} -
  1. -
    -
    -

    - {message.message} -

    -
    - {#if message.args} -

    - {message.args} -

    - {/if} -
  2. - {:else if message.subtype === MessageWebSearchUpdateType.Error} -
  3. -
    - -

    - {message.message} -

    -
    - {#if message.args} -

    - {message.args} -

    - {/if} -
  4. - {/if} - {/each} -
- {/if} -
-
- - diff --git a/src/lib/components/OverloadedModal.svelte b/src/lib/components/OverloadedModal.svelte index 14aa6228fc8cd4b1da957f5d80e65c90fe8e63a2..2aec396e76b14e8b21d5151b0d3db64e1fd47ebf 100644 --- a/src/lib/components/OverloadedModal.svelte +++ b/src/lib/components/OverloadedModal.svelte @@ -8,7 +8,7 @@ let { onClose }: { onClose: () => void } = $props(); - +
diff --git a/src/lib/components/Pagination.svelte b/src/lib/components/Pagination.svelte index b55f4cdbf418fb108783c73d748b342432bb1592..078410911ada587d9981c3afb417e904cd710612 100644 --- a/src/lib/components/Pagination.svelte +++ b/src/lib/components/Pagination.svelte @@ -1,5 +1,5 @@ @@ -64,7 +64,7 @@ >
  • @@ -79,7 +79,7 @@ : ''} " class:pointer-events-none={pageIdx === ELLIPSIS_IDX || pageIndex === pageIdx} - href={getHref($page.url, { newKeys: { p: pageIdx.toString() } })} + href={getHref(page.url, { newKeys: { p: pageIdx.toString() } })} > {pageIdx === ELLIPSIS_IDX ? "..." : pageIdx + 1} @@ -87,7 +87,7 @@ {/each}
  • = numTotalPages} /> diff --git a/src/lib/components/ShareConversationModal.svelte b/src/lib/components/ShareConversationModal.svelte new file mode 100644 index 0000000000000000000000000000000000000000..acbc4cd004cc8f3fd148e95bef2ab4a515888941 --- /dev/null +++ b/src/lib/components/ShareConversationModal.svelte @@ -0,0 +1,185 @@ + + +{#if open} + +
    + + {#if createdUrl} +
    +
    + Public link created +
    + +
    +
    + A public link to your chat has been created. +
    + {:else} +
    +
    + Share public link to chat +
    + +
    +
    + Any messages you add after sharing stay private. Learn more. +
    + {/if} + + {#if errorMsg} +
    + {errorMsg} +
    + {/if} + + +
    + + + {#if createdUrl} + { + justCopied = true; + oncopied?.(); + setTimeout(() => (justCopied = false), 1200); + }} + > + {#snippet children()} + + {#if justCopied} + + Copied + {:else} + + + Copy link + {/if} + + {/snippet} + + {:else} + + {/if} +
    +
    +
    +{/if} diff --git a/src/lib/components/StopGeneratingBtn.svelte b/src/lib/components/StopGeneratingBtn.svelte index 0b457e18502fee3a5fe0df3a292af7ebd539e2a7..595b0da75b1f1e7076b56d62cd5800b7fd14b3c5 100644 --- a/src/lib/components/StopGeneratingBtn.svelte +++ b/src/lib/components/StopGeneratingBtn.svelte @@ -4,15 +4,66 @@ interface Props { classNames?: string; onClick?: () => void; + showBorder?: boolean; } - let { classNames = "", onClick }: Props = $props(); + let { classNames = "", onClick, showBorder = false }: Props = $props(); + + diff --git a/src/lib/components/Switch.svelte b/src/lib/components/Switch.svelte index df8fcfec02fd7f95bf176a0157e3dcc3b479d523..4bc094edc51700d6c6c1e323ef6e030c8896cd6a 100644 --- a/src/lib/components/Switch.svelte +++ b/src/lib/components/Switch.svelte @@ -5,6 +5,17 @@ } let { checked = $bindable(), name }: Props = $props(); + + function toggle() { + checked = !checked; + } + + function onKeydown(e: KeyboardEvent) { + if (e.key === " " || e.key === "Enter") { + e.preventDefault(); + toggle(); + } + } @@ -14,7 +25,9 @@ aria-label="switch" role="switch" tabindex="0" - class="relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full bg-gray-300 p-1 shadow-inner ring-gray-400 transition-all peer-checked:bg-blue-600 peer-focus-visible:ring peer-focus-visible:ring-offset-1 hover:bg-gray-400 dark:bg-gray-600 peer-checked:[&>div]:translate-x-3.5" + onclick={toggle} + onkeydown={onKeydown} + class="relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full bg-gray-300 p-1 shadow-inner ring-gray-400 peer-checked:bg-black hover:bg-gray-400 focus-visible:ring focus-visible:ring-offset-1 dark:bg-gray-600 dark:ring-gray-700 dark:peer-checked:bg-blue-600 dark:hover:bg-gray-500 peer-checked:[&>div]:translate-x-3.5" > -
    +
  • diff --git a/src/lib/components/SystemPromptModal.svelte b/src/lib/components/SystemPromptModal.svelte index b78c26c1a41875cb161eda2c1a2d59564739b1f8..f58b026137df977dfb3538d6cb57ffc7d2b60de6 100644 --- a/src/lib/components/SystemPromptModal.svelte +++ b/src/lib/components/SystemPromptModal.svelte @@ -22,18 +22,22 @@ {#if isOpen} - (isOpen = false)} width="w-full !max-w-xl"> + (isOpen = false)} width="w-full !max-w-xl">
    -
    +

    System Prompt

    diff --git a/src/lib/components/Toast.svelte b/src/lib/components/Toast.svelte index 30acb6e7292d591dfd0ee7d4e0a4b942d7a310ee..14d72d17acf9cec54c87d0abf6eaece603025c70 100644 --- a/src/lib/components/Toast.svelte +++ b/src/lib/components/Toast.svelte @@ -19,7 +19,9 @@ class="pointer-events-auto flex items-center rounded-full bg-white/90 px-3 py-1 shadow-sm dark:bg-gray-900/80" > -

    {message}

    +

    + {message} +

    diff --git a/src/lib/components/TokensCounter.svelte b/src/lib/components/TokensCounter.svelte deleted file mode 100644 index 1c50702cca27f7e49f66cb9a238bb1c8bcddd5b2..0000000000000000000000000000000000000000 --- a/src/lib/components/TokensCounter.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - -
    -

    - {nTokens}{truncate ? `/${truncate}` : ""} -

    - -
    diff --git a/src/lib/components/ToolBadge.svelte b/src/lib/components/ToolBadge.svelte deleted file mode 100644 index b496b1082790ab5ed7365ee10d3f4da9fc1effa0..0000000000000000000000000000000000000000 --- a/src/lib/components/ToolBadge.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - -
    - {#if browser} - {#await client.tools({ id: toolId }).get().then(handleResponse) then value} - {#key value.color + value.icon} - - {/key} -
    - {value.displayName} - {#if value.createdByName} -

    - Created by - {value.createdByName} -

    - {:else} -

    Official HuggingChat tool

    - {/if} -
    - {/await} - {/if} -
    diff --git a/src/lib/components/ToolLogo.svelte b/src/lib/components/ToolLogo.svelte deleted file mode 100644 index 1ab351edd954a25f5a7e0f479aacc9a7bd341496..0000000000000000000000000000000000000000 --- a/src/lib/components/ToolLogo.svelte +++ /dev/null @@ -1,114 +0,0 @@ - - -
    - - - - - - - - - - - - - -
    diff --git a/src/lib/components/ToolsMenu.svelte b/src/lib/components/ToolsMenu.svelte deleted file mode 100644 index 9bd169c6bb253f22210e84404196e51f72dd0181..0000000000000000000000000000000000000000 --- a/src/lib/components/ToolsMenu.svelte +++ /dev/null @@ -1,163 +0,0 @@ - - -
    { - if (detailsEl?.hasAttribute("open")) { - detailsEl.removeAttribute("open"); - } - }} -> - - - Tools - ({activeToolCount}) - -
    -
    -
    - Available tools - {#if publicConfig.isHuggingChat} - - {/if} - -
    - {#if page.data.enableCommunityTools} - - - new - - Browse community tools ({page.data.communityToolCount ?? 0}) - - {/if} - {#each tools as tool} - {@const isChecked = $settings?.tools?.includes(tool._id)} -
    - {#if tool.type === "community"} - { - e.preventDefault(); - e.stopPropagation(); - await settings.instantSet({ - tools: $settings?.tools?.filter((t) => t !== tool._id) ?? [], - }); - }} - /> - {:else} - { - e.preventDefault(); - e.stopPropagation(); - if (isChecked) { - await settings.instantSet({ - tools: ($settings?.tools ?? []).filter((t) => t !== tool._id), - }); - } else { - await settings.instantSet({ - tools: [...($settings?.tools ?? []), tool._id], - }); - } - }} - /> - {/if} - - {#if tool.type === "community"} - - - - {/if} -
    - {/each} -
    -
    -
    - - diff --git a/src/lib/components/UploadBtn.svelte b/src/lib/components/UploadBtn.svelte deleted file mode 100644 index fe722b6d405135fbf5b8fc3e0c68b7dd8340e3a8..0000000000000000000000000000000000000000 --- a/src/lib/components/UploadBtn.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - - diff --git a/src/lib/components/WebSearchToggle.svelte b/src/lib/components/WebSearchToggle.svelte deleted file mode 100644 index a9bfa56575b450b9d70d8433c5143d2eea18b316..0000000000000000000000000000000000000000 --- a/src/lib/components/WebSearchToggle.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -
    - - -
    - -
    -

    - When enabled, the model will try to complement its answer with information queried from the - web. -

    -
    -
    -
    diff --git a/src/lib/components/WelcomeModal.svelte b/src/lib/components/WelcomeModal.svelte new file mode 100644 index 0000000000000000000000000000000000000000..9db568253fb67272aedfdfbbcf3a4b2470e2daae --- /dev/null +++ b/src/lib/components/WelcomeModal.svelte @@ -0,0 +1,57 @@ + + + +
    +
    + + +
    + +
    +

    + Welcome to {publicConfig.PUBLIC_APP_NAME}, the chat app powered by open source AI models. +

    +

    + Omni automatically picks the best AI model to give + you optimal answers depending on your requests. +

    +

    + You can also choose from any available open source models to chat with directly. +

    +
    + + +
    +
    diff --git a/src/lib/components/chat/Alternatives.svelte b/src/lib/components/chat/Alternatives.svelte index 2bdd9f3afadb838b62f3ff66bf88ea34ef3165dd..4973e258e00021c6554b9f60aab2c69519a0d2b0 100644 --- a/src/lib/components/chat/Alternatives.svelte +++ b/src/lib/components/chat/Alternatives.svelte @@ -1,39 +1,35 @@
    - {#if !loading && message.children} +
    diff --git a/src/lib/components/chat/AssistantIntroduction.svelte b/src/lib/components/chat/AssistantIntroduction.svelte deleted file mode 100644 index 5d98590f99d12211f728f35003462d7a381ebe3b..0000000000000000000000000000000000000000 --- a/src/lib/components/chat/AssistantIntroduction.svelte +++ /dev/null @@ -1,204 +0,0 @@ - - -
    -
    -
    -
    - {#if assistant.avatar} - avatar - {:else} -
    - {assistant?.name[0]} -
    - {/if} -
    - {assistant.name} -
    -
    -

    - {assistant.description || "No description provided."} -

    - - -
    -
    -
    -
    -
    -
    - - {#if assistant.createdByName} - - - {#if !import.meta.env.SSR && window.innerWidth < 640}By - {/if}{assistant.createdByName} - - {/if} -
    -
    - - -
    -
    -
    -
    - {#if hasRag} -
    - - Internet access -
    - {/if} - - {#if assistant?.tools?.length} -
    - - Has tools -
    - {/if} - - {#if assistant.userCount && assistant.userCount > 1} -
    - - {formatUserCount(assistant.userCount)} users -
    - {/if} -
    -
    -
    -
    - {#if assistant.exampleInputs && assistant.exampleInputs.length > 0} -
    -

    Examples

    -
    - {#each assistant.exampleInputs as example} - - {/each} -
    -
    - {/if} -
    -
    diff --git a/src/lib/components/chat/ChatInput.svelte b/src/lib/components/chat/ChatInput.svelte index 0242070f0958e4b7340422b019a8151f83dcd401..748bfb998bec82bf8c2caa8579dfd017065a04f4 100644 --- a/src/lib/components/chat/ChatInput.svelte +++ b/src/lib/components/chat/ChatInput.svelte @@ -1,27 +1,9 @@
    @@ -179,78 +125,6 @@ "scrollbar-custom -ml-0.5 flex max-w-[calc(100%-40px)] flex-wrap items-center justify-start gap-2.5 px-3 pb-2.5 pt-1.5 text-gray-500 dark:text-gray-400 max-md:flex-nowrap max-md:overflow-x-auto sm:gap-2", ]} > - {#if showWebSearch} - - - - {/if} - {#if showImageGen} - - - - {/if} {#if showFileUpload} {@const mimeTypesString = mimeTypes .map((m) => { @@ -270,7 +144,7 @@ position="top" TooltipClassNames="text-xs !text-left !w-auto whitespace-nowrap !py-1 !mb-0 max-sm:hidden" > -
    - {#if mimeTypes.includes("image/*")} - - - - {/if} - {/if} - {#if showExtraTools} - {#each extraTools as tool} - - {/each} - - - - - {/if} {/if} diff --git a/src/lib/components/chat/ChatIntroduction.svelte b/src/lib/components/chat/ChatIntroduction.svelte index bd1c47f19db480d5f5cf16d72cf4110fccd2692f..16d9e773b6f21c3c6875c2cac225dcb7b7782292 100644 --- a/src/lib/components/chat/ChatIntroduction.svelte +++ b/src/lib/components/chat/ChatIntroduction.svelte @@ -1,35 +1,40 @@ -
    -
    +
    +
    + + {publicConfig.PUBLIC_APP_NAME} +
    +
    diff --git a/src/lib/components/chat/ChatMessage.svelte b/src/lib/components/chat/ChatMessage.svelte index 925fa5e3f8d6c8639eb1cc1d222e128b99fd924f..2e64352d3c0cf2380aedb49b29f44fa30545cc2a 100644 --- a/src/lib/components/chat/ChatMessage.svelte +++ b/src/lib/components/chat/ChatMessage.svelte @@ -1,33 +1,26 @@ { e.preventDefault(); - bubble("dragover"); }} ondrop={(e) => { e.preventDefault(); @@ -248,36 +309,18 @@ />
    + {#if shareModalOpen} + shareModal.close()} /> + {/if}
    message.content)} + use:snapScrollToBottom={scrollSignal} bind:this={chatContainer} >
    - {#if assistant && !!messages.length} - - {#if assistant.avatar} - Avatar - {:else} -
    - {assistant.name[0]} -
    - {/if} - - {assistant.name} -
    - {:else if preprompt && preprompt != currentModel.preprompt} + {#if preprompt && preprompt != currentModel.preprompt} {/if} @@ -292,10 +335,8 @@ readOnly={isReadOnly} isLast={idx === messages.length - 1} bind:editMsdgId - on:retry - on:vote - on:continue - on:showAlternateMsg + onretry={(payload) => onretry?.(payload)} + onshowAlternateMsg={(payload) => onshowAlternateMsg?.(payload)} /> {/each} {#if isReadOnly} @@ -314,28 +355,14 @@ isAuthor={!shared} readOnly={isReadOnly} /> - {:else if !assistant} + {:else} { + onmessage={(content) => { if (page.data.loginRequired) { - ev.preventDefault(); $loginModalOpen = true; } else { - dispatch("message", ev.detail); - } - }} - /> - {:else} - { - if (page.data.loginRequired) { - ev.preventDefault(); - $loginModalOpen = true; - } else { - dispatch("message", ev.detail); + onmessage?.(content); } }} /> @@ -352,6 +379,7 @@ scrollNode={chatContainer} />
    +
    + {#if !message.length && !messages.length && !sources.length && !loading && currentModel.isRouter && routerExamples.length && !hideRouterExamples} +
    + {#each routerExamples as ex} + + {/each} +
    + {/if} + {#if shouldShowRouterFollowUps} +
    + + {#each routerFollowUps as followUp} + + {/each} +
    + {/if} {#if sources?.length && !loading}
    { + onclose={() => { files = files.filter((_, i) => i !== index); }} /> @@ -379,31 +435,31 @@
    - {#if loading} - dispatch("stop")} /> - {:else if lastIsError} - { - if (lastMessage && lastMessage.ancestors) { - dispatch("retry", { - id: lastMessage.id, - }); - } - }} - /> - {:else if messages && lastMessage && lastMessage.interrupted && !isReadOnly} -
    - { if (lastMessage && lastMessage.ancestors) { - dispatch("continue", { - id: lastMessage?.id, + onretry?.({ + id: lastMessage.id, }); } }} /> -
    + {:else if messages && lastMessage && lastMessage.interrupted && !isReadOnly} +
    + { + if (lastMessage && lastMessage.ancestors) { + oncontinue?.({ + id: lastMessage?.id, + }); + } + }} + /> +
    + {/if} {/if}
    {:else} {/if} {#if loading} - + onstop?.()} + showBorder={true} + classNames="absolute bottom-2 right-2 size-7 self-end rounded-full border bg-white text-black shadow transition-none dark:border-transparent dark:bg-gray-600 dark:text-white" + /> {:else} + {:else} + + {currentModel.id} + + {/if} + {#if !messages.length} + Generated content may be inaccurate or false. {/if} -
    +
    diff --git a/src/lib/components/chat/FileDropzone.svelte b/src/lib/components/chat/FileDropzone.svelte index 4320fd4c8d9614d1737187407bb9930409e472c4..a29ae03ba466db8dbc5adf7e448f1a2fe267edd9 100644 --- a/src/lib/components/chat/FileDropzone.svelte +++ b/src/lib/components/chat/FileDropzone.svelte @@ -1,9 +1,4 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/components/chat/OpenReasoningResults.svelte b/src/lib/components/chat/OpenReasoningResults.svelte index a052f12b937f9c572b0c4c12033130d18f89c892..10080786d88b8d8b538b4d405f4d4a93dea5b7c2 100644 --- a/src/lib/components/chat/OpenReasoningResults.svelte +++ b/src/lib/components/chat/OpenReasoningResults.svelte @@ -18,11 +18,11 @@
    @@ -65,14 +65,16 @@ : summary + "..."} - +
    {#key content} - + {/key}
    diff --git a/src/lib/components/chat/Search.svelte b/src/lib/components/chat/Search.svelte deleted file mode 100644 index 7e4063fe0d3db0b7ea21a04d90388631df1a008f..0000000000000000000000000000000000000000 --- a/src/lib/components/chat/Search.svelte +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - -{#if searchOpen} -
    - - = 3, - }} - /> - -
    - {#if debouncedInput && debouncedInput.length >= 3} - {#if pending} - {#each Array(5) as _} -
    - {/each} - {:else if conversations.length === 0} -

    - No conversations found matching that query -

    - {:else} - {#each Object.entries(groupedConversations) as [group, convs]} - {#if convs.length} -

    - {titles[group]} -

    - {#each convs as conv} - - {/each} - {/if} - {/each} - {#if hasMore} - handleVisible(searchInput)} /> - {/if} - {/if} - {/if} -
    -
    -{/if} diff --git a/src/lib/components/chat/ToolUpdate.svelte b/src/lib/components/chat/ToolUpdate.svelte deleted file mode 100644 index 4b52d93d16dda26dc181070289ac8c8f86913d1e..0000000000000000000000000000000000000000 --- a/src/lib/components/chat/ToolUpdate.svelte +++ /dev/null @@ -1,182 +0,0 @@ - - -{#if toolFnName && toolFnName !== "websearch"} -
    - - - -
    - - - - -
    - - - {toolError ? "Error calling" : toolDone ? "Called" : "Calling"} tool - {availableTools.find((tool) => tool.name === toolFnName)?.displayName ?? - toolFnName} - -
    - {#each tool as toolUpdate} - {#if toolUpdate.subtype === MessageToolUpdateType.Call} -
    -

    Parameters

    -
    -
    -
      - {#each Object.entries(toolUpdate.call.parameters ?? {}) as [k, v]} - {#if v !== null} -
    • - {k}: - {v} -
    • - {/if} - {/each} -
    - {:else if toolUpdate.subtype === MessageToolUpdateType.Error} -
    -

    Error

    -
    -
    -

    {toolUpdate.message}

    - {:else if isMessageToolResultUpdate(toolUpdate) && toolUpdate.result.status === ToolResultStatus.Success && toolUpdate.result.display} -
    -

    Result

    -
    -
    -
      - {#each toolUpdate.result.outputs as output} - {#each Object.entries(output) as [k, v]} - {#if v !== null} -
    • - {k}: - {v} -
    • - {/if} - {/each} - {/each} -
    - {/if} - {/each} -
    -{/if} - - diff --git a/src/lib/components/chat/UploadedFile.svelte b/src/lib/components/chat/UploadedFile.svelte index 7d3a2ae6efe8db1db2fbfafde65d5a4b33270749..359c7073677edbb3e745733f65b9419000838c54 100644 --- a/src/lib/components/chat/UploadedFile.svelte +++ b/src/lib/components/chat/UploadedFile.svelte @@ -1,6 +1,5 @@ - - - diff --git a/src/lib/components/icons/IconBurger.svelte b/src/lib/components/icons/IconBurger.svelte new file mode 100644 index 0000000000000000000000000000000000000000..64a13801479d562cbac3bb7ed56b28cf2b85b303 --- /dev/null +++ b/src/lib/components/icons/IconBurger.svelte @@ -0,0 +1,20 @@ + + + + diff --git a/src/lib/components/icons/IconCopy.svelte b/src/lib/components/icons/IconCopy.svelte deleted file mode 100644 index 1676b170402de387a944dc409c71fc614a178931..0000000000000000000000000000000000000000 --- a/src/lib/components/icons/IconCopy.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/src/lib/components/icons/IconDazzled.svelte b/src/lib/components/icons/IconDazzled.svelte index 10599690445360ec78ac926552c7989fba24c9ee..764ca7c78e04da39f69858854115d8e612220e5d 100644 --- a/src/lib/components/icons/IconDazzled.svelte +++ b/src/lib/components/icons/IconDazzled.svelte @@ -15,7 +15,7 @@ viewBox="0 0 26 23" > - interface Props { - classNames?: string; - } - - let { classNames = "" }: Props = $props(); - - - diff --git a/src/lib/components/icons/IconInternet.svelte b/src/lib/components/icons/IconInternet.svelte deleted file mode 100644 index 74eba8bbc1a56cb95eb98745755b2effdfc62e20..0000000000000000000000000000000000000000 --- a/src/lib/components/icons/IconInternet.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/lib/components/icons/IconMoon.svelte b/src/lib/components/icons/IconMoon.svelte new file mode 100644 index 0000000000000000000000000000000000000000..986f59880a7656bf5d2aec33e45bb603468cbcf2 --- /dev/null +++ b/src/lib/components/icons/IconMoon.svelte @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/components/icons/IconNew.svelte b/src/lib/components/icons/IconNew.svelte index a617467c809353ba0cc86897fda4e7b4d61fd219..3ac50480d922f60ae621992c7cb089c061a84205 100644 --- a/src/lib/components/icons/IconNew.svelte +++ b/src/lib/components/icons/IconNew.svelte @@ -12,11 +12,9 @@ width="1em" height="1em" fill="none" - viewBox="0 0 32 32" + viewBox="0 0 16 16" > diff --git a/src/lib/components/icons/IconOmni.svelte b/src/lib/components/icons/IconOmni.svelte new file mode 100644 index 0000000000000000000000000000000000000000..c027809a872dc6e2d84c78a077016a429dd3b54e --- /dev/null +++ b/src/lib/components/icons/IconOmni.svelte @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/src/lib/components/icons/IconScreenshot.svelte b/src/lib/components/icons/IconScreenshot.svelte deleted file mode 100644 index c9edf133bb45331c84041869d52b6b391880aa33..0000000000000000000000000000000000000000 --- a/src/lib/components/icons/IconScreenshot.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/lib/components/icons/IconShare.svelte b/src/lib/components/icons/IconShare.svelte new file mode 100644 index 0000000000000000000000000000000000000000..f1cbae541dde035850f967cf980d012cef1514b4 --- /dev/null +++ b/src/lib/components/icons/IconShare.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/icons/IconSun.svelte b/src/lib/components/icons/IconSun.svelte new file mode 100644 index 0000000000000000000000000000000000000000..f06c96b5ec8a2e30602eee7b21de1b1f8510fbee --- /dev/null +++ b/src/lib/components/icons/IconSun.svelte @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/components/icons/IconTool.svelte b/src/lib/components/icons/IconTool.svelte deleted file mode 100644 index 49b35e8000c35e5dde9531c85e8a5c715fc2313b..0000000000000000000000000000000000000000 --- a/src/lib/components/icons/IconTool.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/lib/components/icons/Logo.svelte b/src/lib/components/icons/Logo.svelte index 9d5675d027b1bbfea2502be632803887ed32f505..011ce8b00506f992eecea7aeea81d0cf9ec0f131 100644 --- a/src/lib/components/icons/Logo.svelte +++ b/src/lib/components/icons/Logo.svelte @@ -10,23 +10,8 @@ let { classNames = "" }: Props = $props(); -{#if publicConfig.PUBLIC_APP_ASSETS === "chatui"} - - - -{:else} - {publicConfig.PUBLIC_APP_NAME} logo -{/if} +{publicConfig.PUBLIC_APP_NAME} logo diff --git a/src/lib/constants/routerExamples.ts b/src/lib/constants/routerExamples.ts new file mode 100644 index 0000000000000000000000000000000000000000..345e03c5c1fd366db9b64db9347d5c5ffe6b4b16 --- /dev/null +++ b/src/lib/constants/routerExamples.ts @@ -0,0 +1,150 @@ +export type RouterFollowUp = { + title: string; + prompt: string; +}; + +export type RouterExample = { + title: string; + prompt: string; + followUps?: RouterFollowUp[]; +}; + +export const routerExamples: RouterExample[] = [ + { + title: "Pong game", + prompt: "Create a minimalist pong game using HTML and tailwindcss", + followUps: [ + { + title: "README.md file", + prompt: "Create a comprehensive README.md for the Pong game project.", + }, + { + title: "Add power-ups", + prompt: + "Add a power-up mechanic to the Pong game so paddles temporarily grow when a player scores twice in a row.", + }, + + { + title: "CRT Screen", + prompt: "Add a CRT screen effect to the game", + }, + ], + }, + { + title: "Landing page", + prompt: + "Build a responsive SaaS landing page using Tailwind CSS with a hero, features, testimonials, and pricing sections.", + followUps: [ + { + title: "Dark mode", + prompt: + "Extend the Tailwind CSS landing page with a toggleable dark mode that remembers the user's choice.", + }, + { + title: "Add blog teasers", + prompt: + "Add a latest blog posts section to the Tailwind CSS landing page with three article cards and call-to-action buttons.", + }, + { + title: "Translate to Italian", + prompt: "Translate the visible content of the page into italian", + }, + ], + }, + { + title: "Eminem song", + prompt: + "Write an Eminem-style rap battling AI taking over hip-hop, with two energetic verses and a catchy hook.", + followUps: [ + { + title: "Psychological analysis", + prompt: "Provide a psychological analysis of Eminem’s emotions in this song.", + }, + { + title: "Wired Article", + prompt: "Write an article in the style of Wired explaining this Eminem release.", + }, + { + title: "Roleplay", + prompt: "Roleplay as Eminem so I can discuss the song with him.", + }, + ], + }, + { + title: "Act as Yoda", + prompt: "Act as Yoda", + followUps: [ + { + title: "Give advice", + prompt: + "Continue acting as Yoda and offer three pieces of life advice for staying focused under pressure.", + }, + { + title: "Explain the Force", + prompt: + "In Yoda's voice, explain the concept of the Force to a young padawan using modern language.", + }, + { + title: "Plain English", + prompt: + "Rewrite the previous response from Yoda into plain English while keeping the same meaning.", + }, + ], + }, + { + title: "Generate prompts", + prompt: `Generate 5 creative prompts Text-to-image prompts like: "Cyberpunk cityscape at night, neon lights, flying cars, rain-slicked streets, blade runner aesthetic, highly detailed`, + followUps: [ + { + title: "Turn into JSON", + prompt: `Generate a detailed JSON object for each prompt. Include fields for subjects (list of objects), scene (setting, environment, background details), actions (what’s happening), style (artistic style or medium)`, + }, + { + title: "Sci-fi portraits", + prompt: + "Produce five futuristic character portrait prompts with unique professions and settings.", + }, + ], + }, + { + title: "Explain LLMs", + prompt: + "Explain how large language models based on transformers work, covering attention, embeddings, and training objectives.", + followUps: [ + { + title: "Generate a Quiz", + prompt: "Craft a 5-question multiple-choice quiz to validate what I learned.", + }, + { + title: "Compare to RNNs", + prompt: + "Compare transformer-based large language models to recurrent neural networks, focusing on training efficiency and capabilities.", + }, + { + title: "Student summary", + prompt: + "Summarize the explanation of large language models for a high school student using relatable analogies.", + }, + ], + }, + { + title: "Translate in Italian", + prompt: `Translate in Italian: Some are born great, some achieve greatness, and some have greatness thrust upon ’em`, + followUps: [ + { + title: "Back to English", + prompt: + "Translate the Italian version back into English while keeping Shakespeare's tone intact.", + }, + { + title: "Explain choices", + prompt: "Explain your translation choices for each key phrase from the Italian version.", + }, + { + title: "Modernize", + prompt: + "Modernize the Italian translation into contemporary informal Italian suitable for social media.", + }, + ], + }, +]; diff --git a/src/lib/createShareLink.ts b/src/lib/createShareLink.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1f9446ae851a45d64cf255b6e478ce915d4a0cb --- /dev/null +++ b/src/lib/createShareLink.ts @@ -0,0 +1,27 @@ +import { base } from "$app/paths"; +import { page } from "$app/state"; + +// Returns a public share URL for a conversation id. +// If `id` is already a 7-char share id, no network call is made. +export async function createShareLink(id: string): Promise { + const prefix = + page.data.publicConfig.PUBLIC_SHARE_PREFIX || + `${page.data.publicConfig.PUBLIC_ORIGIN || page.url.origin}${base}`; + + if (id.length === 7) { + return `${prefix}/r/${id}`; + } + + const res = await fetch(`${base}/conversation/${id}/share`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + }); + + if (!res.ok) { + const text = await res.text().catch(() => ""); + throw new Error(text || "Failed to create share link"); + } + + const { shareId } = await res.json(); + return `${prefix}/r/${shareId}`; +} diff --git a/src/lib/jobs/refresh-assistants-counts.ts b/src/lib/jobs/refresh-assistants-counts.ts deleted file mode 100644 index a722ad907286e475e4af3182ce7946e3aab64303..0000000000000000000000000000000000000000 --- a/src/lib/jobs/refresh-assistants-counts.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Database } from "$lib/server/database"; -import { acquireLock, refreshLock } from "$lib/migrations/lock"; -import type { ObjectId } from "mongodb"; -import { subDays } from "date-fns"; -import { logger } from "$lib/server/logger"; -import { collections } from "$lib/server/database"; -import { Semaphores } from "$lib/types/Semaphore"; -let hasLock = false; -let lockId: ObjectId | null = null; - -async function getLastComputationTime(): Promise { - const lastStats = await collections.assistantStats.findOne({}, { sort: { "date.at": -1 } }); - return lastStats?.date?.at || new Date(0); -} - -async function shouldComputeStats(): Promise { - const lastComputationTime = await getLastComputationTime(); - const oneDayAgo = new Date(Date.now() - 24 * 3_600_000); - return lastComputationTime < oneDayAgo; -} - -async function refreshAssistantsCountsHelper() { - if (!hasLock) { - return; - } - - try { - await (await Database.getInstance()).getClient().withSession((session) => - session.withTransaction(async () => { - await ( - await Database.getInstance() - ) - .getCollections() - .assistants.aggregate([ - { $project: { _id: 1 } }, - { $set: { last24HoursCount: 0 } }, - { - $unionWith: { - coll: "assistants.stats", - pipeline: [ - { - $match: { "date.at": { $gte: subDays(new Date(), 1) }, "date.span": "hour" }, - }, - { - $group: { - _id: "$assistantId", - last24HoursCount: { $sum: "$count" }, - }, - }, - ], - }, - }, - { - $group: { - _id: "$_id", - last24HoursCount: { $sum: "$last24HoursCount" }, - }, - }, - { - $merge: { - into: "assistants", - on: "_id", - whenMatched: "merge", - whenNotMatched: "discard", - }, - }, - ]) - .next(); - }) - ); - } catch (e) { - logger.error(e, "Refresh assistants counter failed!"); - } -} - -async function maintainLock() { - if (hasLock && lockId) { - hasLock = await refreshLock(Semaphores.ASSISTANTS_COUNT, lockId); - - if (!hasLock) { - lockId = null; - } - } else if (!hasLock) { - lockId = (await acquireLock(Semaphores.ASSISTANTS_COUNT)) || null; - hasLock = !!lockId; - } - - setTimeout(maintainLock, 10_000); -} - -export function refreshAssistantsCounts() { - const ONE_HOUR_MS = 3_600_000; - - maintainLock().then(async () => { - if (await shouldComputeStats()) { - refreshAssistantsCountsHelper(); - } - - setInterval(async () => { - if (await shouldComputeStats()) { - refreshAssistantsCountsHelper(); - } - }, 24 * ONE_HOUR_MS); - }); -} diff --git a/src/lib/migrations/routines/03-add-tools-in-settings.ts b/src/lib/migrations/routines/03-add-tools-in-settings.ts deleted file mode 100644 index 0036242a1c1828f9f3822981ee6eae01a68457b8..0000000000000000000000000000000000000000 --- a/src/lib/migrations/routines/03-add-tools-in-settings.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Migration } from "."; -import { collections } from "$lib/server/database"; -import { ObjectId } from "mongodb"; -import { logger } from "$lib/server/logger"; - -const addToolsToSettings: Migration = { - _id: new ObjectId("5c9c4c4c4c4c4c4c4c4c4c4c"), - name: "Add empty 'tools' record in settings", - up: async () => { - const { settings } = collections; - - // Find all assistants whose modelId is not in modelIds, and update it to use defaultModelId - await settings.updateMany( - { - tools: { $exists: false }, - }, - { $set: { tools: [] } } - ); - - settings - .createIndex({ tools: 1 }) - .catch((e) => logger.error(e, "Error creating index during tools migration")); - - return true; - }, - runEveryTime: false, -}; - -export default addToolsToSettings; diff --git a/src/lib/migrations/routines/04-update-message-updates.ts b/src/lib/migrations/routines/04-update-message-updates.ts index 8be3d91cd94f006b8efbcc9b25c6c780122aa236..4617d2c86096d2ba312f8f638657d9730f7f3b2e 100644 --- a/src/lib/migrations/routines/04-update-message-updates.ts +++ b/src/lib/migrations/routines/04-update-message-updates.ts @@ -2,16 +2,13 @@ import type { Migration } from "."; import { collections } from "$lib/server/database"; import { ObjectId, type WithId } from "mongodb"; import type { Conversation } from "$lib/types/Conversation"; -import type { WebSearchSource } from "$lib/types/WebSearch"; import { MessageUpdateStatus, MessageUpdateType, - MessageWebSearchUpdateType, type MessageUpdate, - type MessageWebSearchFinishedUpdate, } from "$lib/types/MessageUpdate"; import type { Message } from "$lib/types/Message"; -import { isMessageWebSearchSourcesUpdate } from "$lib/utils/messageUpdates"; +// isMessageWebSearchSourcesUpdate removed from utils; use inline predicate // ----------- // Copy of the previous message update types @@ -30,7 +27,7 @@ type WebSearchUpdate = { messageType: "update" | "error" | "sources"; message: string; args?: string[]; - sources?: WebSearchSource[]; + sources?: { title?: string; link: string }[]; }; type StatusUpdate = { @@ -115,28 +112,7 @@ function convertMessageUpdate(message: Message, update: OldMessageUpdate): Messa // Web Search else if (update.type === "webSearch") { - if (update.messageType === "update") { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Update, - message: update.message, - args: update.args, - }; - } else if (update.messageType === "error") { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Error, - message: update.message, - args: update.args, - }; - } else if (update.messageType === "sources") { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Sources, - message: update.message, - sources: update.sources ?? [], - }; - } + return null; // Web search updates are no longer supported } console.warn("Unknown message update during migration:", update); return null; @@ -160,20 +136,6 @@ const updateMessageUpdates: Migration = { ?.map((update) => convertMessageUpdate(message, update as OldMessageUpdate)) .filter((update): update is MessageUpdate => Boolean(update)); - // Add the new web search finished update if the sources update exists and webSearch is defined - const webSearchSourcesUpdateIndex = updates?.findIndex(isMessageWebSearchSourcesUpdate); - if ( - message.webSearch && - updates && - webSearchSourcesUpdateIndex && - webSearchSourcesUpdateIndex !== -1 - ) { - const webSearchFinishedUpdate: MessageWebSearchFinishedUpdate = { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Finished, - }; - updates.splice(webSearchSourcesUpdateIndex + 1, 0, webSearchFinishedUpdate); - } return { ...message, updates }; }); diff --git a/src/lib/migrations/routines/06-trim-message-updates.ts b/src/lib/migrations/routines/06-trim-message-updates.ts index 64c080b735e3cc702d226c6ad49ab8e38a4a7ad3..bea7a54f8280601faebaaed17d3214c35f01a334 100644 --- a/src/lib/migrations/routines/06-trim-message-updates.ts +++ b/src/lib/migrations/routines/06-trim-message-updates.ts @@ -2,38 +2,21 @@ import type { Migration } from "."; import { collections } from "$lib/server/database"; import { ObjectId, type WithId } from "mongodb"; import type { Conversation } from "$lib/types/Conversation"; -import { - MessageUpdateType, - MessageWebSearchUpdateType, - type MessageUpdate, -} from "$lib/types/MessageUpdate"; import type { Message } from "$lib/types/Message"; +import type { MessageUpdate } from "$lib/types/MessageUpdate"; import { logger } from "$lib/server/logger"; // ----------- /** Converts the old message update to the new schema */ -function convertMessageUpdate(message: Message, update: MessageUpdate): MessageUpdate | null { +function convertMessageUpdate(message: Message, update: unknown): MessageUpdate | null { try { - // trim final websearch update, and sources update - - if (update.type === "webSearch") { - if (update.subtype === MessageWebSearchUpdateType.Sources) { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Sources, - message: update.message, - sources: update.sources.map(({ link, title }) => ({ link, title })), - }; - } else if (update.subtype === MessageWebSearchUpdateType.Finished) { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Finished, - }; - } + // Trim legacy web search updates entirely + if (typeof update === "object" && update !== null && (update as any).type === "webSearch") { + return null; } - return update; + return update as MessageUpdate; } catch (error) { logger.error(error, "Error converting message update during migration. Skipping it.."); return null; diff --git a/src/lib/migrations/routines/07-reset-tools-in-settings.ts b/src/lib/migrations/routines/07-reset-tools-in-settings.ts deleted file mode 100644 index 03d0b89d04c8a18e4cda2df992d33a64c50af7b3..0000000000000000000000000000000000000000 --- a/src/lib/migrations/routines/07-reset-tools-in-settings.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Migration } from "."; -import { collections } from "$lib/server/database"; -import { ObjectId } from "mongodb"; - -const resetTools: Migration = { - _id: new ObjectId("000000000000000000000007"), - name: "Reset tools to empty", - up: async () => { - const { settings } = collections; - - await settings.updateMany({}, { $set: { tools: [] } }); - - return true; - }, - runEveryTime: false, -}; - -export default resetTools; diff --git a/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts b/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts index 0248d82d5c4fcc6a48a3cbce47c1ecff1434d7a6..f807e61917ece332f305c852f236ae372385e20e 100644 --- a/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts +++ b/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts @@ -52,7 +52,7 @@ const conversationBase = { createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), updatedAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), model: "model-id", - embeddingModel: "embedding-model-id", + title: "title", messages: [], } satisfies Conversation; diff --git a/src/lib/migrations/routines/index.ts b/src/lib/migrations/routines/index.ts index 44e56e989b7ab35b4481f552f2c3cea3d7e381cb..2526e2b30b3915df4cefaabfce8ec2843d45141a 100644 --- a/src/lib/migrations/routines/index.ts +++ b/src/lib/migrations/routines/index.ts @@ -3,11 +3,9 @@ import type { ObjectId } from "mongodb"; import updateSearchAssistant from "./01-update-search-assistants"; import updateAssistantsModels from "./02-update-assistants-models"; import type { Database } from "$lib/server/database"; -import addToolsToSettings from "./03-add-tools-in-settings"; import updateMessageUpdates from "./04-update-message-updates"; import updateMessageFiles from "./05-update-message-files"; import trimMessageUpdates from "./06-trim-message-updates"; -import resetTools from "./07-reset-tools-in-settings"; import updateFeaturedToReview from "./08-update-featured-to-review"; import deleteEmptyConversations from "./09-delete-empty-conversations"; import updateReportsAssistantId from "./10-update-reports-assistantid"; @@ -25,11 +23,9 @@ export interface Migration { export const migrations: Migration[] = [ updateSearchAssistant, updateAssistantsModels, - addToolsToSettings, updateMessageUpdates, updateMessageFiles, trimMessageUpdates, - resetTools, updateFeaturedToReview, deleteEmptyConversations, updateReportsAssistantId, diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index 31029fffa20d1c91e42b6660802200239f6ecbd8..5e63df3e86946afed9c5dfc2e2906f0acc48eb2b 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -1,10 +1,9 @@ import { authPlugin } from "$api/authPlugin"; import { conversationGroup } from "$api/routes/groups/conversations"; -import { assistantGroup } from "$api/routes/groups/assistants"; import { userGroup } from "$api/routes/groups/user"; -import { toolGroup } from "$api/routes/groups/tools"; import { misc } from "$api/routes/groups/misc"; import { modelGroup } from "$api/routes/groups/models"; +import { debugGroup } from "$api/routes/groups/debug"; import { Elysia } from "elysia"; import { base } from "$app/paths"; @@ -41,10 +40,9 @@ export const app = new Elysia({ prefix }) ) .use(authPlugin) .use(conversationGroup) - .use(toolGroup) - .use(assistantGroup) .use(userGroup) .use(modelGroup) - .use(misc); + .use(misc) + .use(debugGroup); export type App = typeof app; diff --git a/src/lib/server/api/routes/groups/assistants.ts b/src/lib/server/api/routes/groups/assistants.ts deleted file mode 100644 index 9d2b181bfef157e517784350a4b6a06a3ca5f27d..0000000000000000000000000000000000000000 --- a/src/lib/server/api/routes/groups/assistants.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { Elysia, t } from "elysia"; -import { authPlugin } from "$api/authPlugin"; -import { collections } from "$lib/server/database"; -import { ObjectId, type Filter } from "mongodb"; -import { authCondition } from "$lib/server/auth"; -import { SortKey, type Assistant } from "$lib/types/Assistant"; -import type { User } from "$lib/types/User"; -import { ReviewStatus } from "$lib/types/Review"; -import { generateQueryTokens } from "$lib/utils/searchTokens"; -import { config } from "$lib/server/config"; - -const NUM_PER_PAGE = 24; - -export const assistantGroup = new Elysia().use(authPlugin).group("/assistants", (app) => { - return app - .get("/", () => { - // todo: get assistants - throw new Error("Not implemented"); - }) - .post("/", () => { - // todo: post new assistant - throw new Error("Not implemented"); - }) - .get( - "/search", - async ({ query, locals, error }) => { - if (!config.ENABLE_ASSISTANTS) { - error(403, "Assistants are not enabled"); - } - const modelId = query.modelId; - const pageIndex = query.p ?? 0; - const username = query.user; - const search = query.q?.trim() ?? null; - const sort = query.sort ?? SortKey.TRENDING; - const showUnfeatured = query.showUnfeatured ?? false; - const createdByCurrentUser = locals.user?.username && locals.user.username === username; - - let user: Pick | null = null; - if (username) { - user = await collections.users.findOne>( - { username }, - { projection: { _id: 1 } } - ); - if (!user) { - error(404, `User "${username}" doesn't exist`); - } - } - // if we require featured assistants, that we are not on a user page and we are not an admin who wants to see unfeatured assistants, we show featured assistants - let shouldBeFeatured = {}; - - if (config.REQUIRE_FEATURED_ASSISTANTS === "true" && !(locals.isAdmin && showUnfeatured)) { - if (!user) { - // only show featured assistants on the community page - shouldBeFeatured = { review: ReviewStatus.APPROVED }; - } else if (!createdByCurrentUser) { - // on a user page show assistants that have been approved or are pending - shouldBeFeatured = { review: { $in: [ReviewStatus.APPROVED, ReviewStatus.PENDING] } }; - } - } - - const noSpecificSearch = !user && !search; - // fetch the top assistants sorted by user count from biggest to smallest. - // filter by model too if modelId is provided or query if query is provided - // only show assistants that have been used by more than 5 users if no specific search is made - const filter: Filter = { - ...(modelId && { modelId }), - ...(user && { createdById: user._id }), - ...(search && { searchTokens: { $all: generateQueryTokens(search) } }), - ...(noSpecificSearch && { userCount: { $gte: 5 } }), - ...shouldBeFeatured, - }; - - const assistants = await collections.assistants - .find(filter) - .sort({ - ...(sort === SortKey.TRENDING && { last24HoursCount: -1 }), - userCount: -1, - _id: 1, - }) - .skip(NUM_PER_PAGE * pageIndex) - .limit(NUM_PER_PAGE) - .toArray(); - - const numTotalItems = await collections.assistants.countDocuments(filter); - - return { - assistants, - selectedModel: modelId ?? "", - numTotalItems, - numItemsPerPage: NUM_PER_PAGE, - query: search, - sort, - showUnfeatured, - }; - }, - { - query: t.Object({ - user: t.Optional(t.String()), - q: t.Optional(t.String()), - sort: t.Optional(t.Enum(SortKey)), - p: t.Optional(t.Numeric()), - showUnfeatured: t.Optional(t.Boolean()), - modelId: t.Optional(t.String()), - }), - } - ) - .group("/:id", (app) => { - return app - .derive(async ({ params, error }) => { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.id), - }); - - if (!assistant) { - return error(404, "Assistant not found"); - } - - return { assistant }; - }) - .get("", ({ assistant }) => { - return assistant; - }) - .patch("", () => { - // todo: patch assistant - throw new Error("Not implemented"); - }) - .delete("/", () => { - // todo: delete assistant - throw new Error("Not implemented"); - }) - .post("/report", () => { - // todo: report assistant - throw new Error("Not implemented"); - }) - .patch("/review", () => { - // todo: review assistant - throw new Error("Not implemented"); - }) - .post("/follow", async ({ locals, assistant }) => { - const result = await collections.settings.updateOne(authCondition(locals), { - $addToSet: { assistants: assistant._id }, - $set: { activeModel: assistant._id.toString() }, - }); - - if (result.modifiedCount > 0) { - await collections.assistants.updateOne( - { _id: assistant._id }, - { $inc: { userCount: 1 } } - ); - } - - return { message: "Assistant subscribed" }; - }) - .delete("/follow", async ({ locals, assistant }) => { - const result = await collections.settings.updateOne(authCondition(locals), { - $pull: { assistants: assistant._id }, - }); - - if (result.modifiedCount > 0) { - await collections.assistants.updateOne( - { _id: assistant._id }, - { $inc: { userCount: -1 } } - ); - } - - return { message: "Assistant unsubscribed" }; - }); - }); -}); diff --git a/src/lib/server/api/routes/groups/conversations.ts b/src/lib/server/api/routes/groups/conversations.ts index 27c0aa8253ef8b64f8c93c2a55a1388f8e401181..e4f5f16f3111a5f96cee9a077ad0aa31b87f7158 100644 --- a/src/lib/server/api/routes/groups/conversations.ts +++ b/src/lib/server/api/routes/groups/conversations.ts @@ -3,509 +3,256 @@ import { authPlugin } from "$api/authPlugin"; import { collections } from "$lib/server/database"; import { ObjectId } from "mongodb"; import { authCondition } from "$lib/server/auth"; -import { models, validModelIdSchema } from "$lib/server/models"; +import { validModelIdSchema } from "$lib/server/models"; import { convertLegacyConversation } from "$lib/utils/tree/convertLegacyConversation"; import type { Conversation } from "$lib/types/Conversation"; import { CONV_NUM_PER_PAGE } from "$lib/constants/pagination"; -import pkg from "natural"; -const { PorterStemmer } = pkg; export const conversationGroup = new Elysia().use(authPlugin).group("/conversations", (app) => { - return app - .guard({ - as: "scoped", - beforeHandle: async ({ locals }) => { - if (!locals.user?._id && !locals.sessionId) { - return error(401, "Must have a valid session or user"); - } - }, - }) - .get( - "", - async ({ locals, query }) => { - const convs = await collections.conversations - .find(authCondition(locals)) - .project>({ - title: 1, - updatedAt: 1, - model: 1, - assistantId: 1, - }) - .sort({ updatedAt: -1 }) - .skip((query.p ?? 0) * CONV_NUM_PER_PAGE) - .limit(CONV_NUM_PER_PAGE) - .toArray(); - - const nConversations = await collections.conversations.countDocuments( - authCondition(locals) - ); - - const res = convs.map((conv) => ({ - _id: conv._id, - id: conv._id, // legacy param iOS - title: conv.title, - updatedAt: conv.updatedAt, - model: conv.model, - modelId: conv.model, // legacy param iOS - assistantId: conv.assistantId, - modelTools: models.find((m) => m.id == conv.model)?.tools ?? false, - })); - - return { conversations: res, nConversations }; - }, - { - query: t.Object({ - p: t.Optional(t.Number()), - }), - } - ) - .delete("", async ({ locals }) => { - const res = await collections.conversations.deleteMany({ - ...authCondition(locals), - }); - return res.deletedCount; - }) - .get( - "/search", - async ({ locals, query }) => { - const searchQuery = query.q; - const p = query.p ?? 0; + return ( + app + .guard({ + as: "scoped", + beforeHandle: async ({ locals }) => { + if (!locals.user?._id && !locals.sessionId) { + return error(401, "Must have a valid session or user"); + } + }, + }) + .get( + "", + async ({ locals, query }) => { + const convs = await collections.conversations + .find(authCondition(locals)) + .project>({ + title: 1, + updatedAt: 1, + model: 1, + }) + .sort({ updatedAt: -1 }) + .skip((query.p ?? 0) * CONV_NUM_PER_PAGE) + .limit(CONV_NUM_PER_PAGE) + .toArray(); - if (!searchQuery || searchQuery.length < 3) { - return []; - } + const nConversations = await collections.conversations.countDocuments( + authCondition(locals) + ); - if (!locals.user?._id && !locals.sessionId) { - throw new Error("Must have a valid session or user"); + const res = convs.map((conv) => ({ + _id: conv._id, + id: conv._id, // legacy param iOS + title: conv.title, + updatedAt: conv.updatedAt, + model: conv.model, + modelId: conv.model, // legacy param iOS + })); + + return { conversations: res, nConversations }; + }, + { + query: t.Object({ + p: t.Optional(t.Number()), + }), } + ) + .delete("", async ({ locals }) => { + const res = await collections.conversations.deleteMany({ + ...authCondition(locals), + }); + return res.deletedCount; + }) + // search endpoint removed + .group( + "/:id", + { + params: t.Object({ + id: t.String(), + }), + }, + (app) => { + return app + .derive(async ({ locals, params }) => { + let conversation; + let shared = false; + + // if the conver + if (params.id.length === 7) { + // shared link of length 7 + conversation = await collections.sharedConversations.findOne({ + _id: params.id, + }); + shared = true; - const convs = await collections.conversations - .find({ - sessionId: undefined, - ...authCondition(locals), - $text: { $search: searchQuery }, - }) - .sort({ - updatedAt: -1, // Sort by date updated in descending order - }) - .project< - Pick< - Conversation, - "_id" | "title" | "updatedAt" | "model" | "assistantId" | "messages" | "userId" - > - >({ - title: 1, - updatedAt: 1, - model: 1, - assistantId: 1, - messages: 1, - userId: 1, - }) - .skip(p * 5) - .limit(5) - .toArray() - .then((convs) => - convs.map((conv) => { - let matchedContent = ""; - let matchedText = ""; - - // Find the best match using stemming to handle MongoDB's text search behavior - let bestMatch = null; - let bestMatchLength = 0; - - // Simple function to find the best match in content - const findBestMatch = ( - content: string, - query: string - ): { start: number; end: number; text: string } | null => { - const contentLower = content.toLowerCase(); - const queryLower = query.toLowerCase(); - - // Try exact word boundary match first - const wordRegex = new RegExp( - `\\b${queryLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, - "gi" - ); - const wordMatch = wordRegex.exec(content); - if (wordMatch) { - return { - start: wordMatch.index, - end: wordMatch.index + wordMatch[0].length - 1, - text: wordMatch[0], - }; + if (!conversation) { + throw new Error("Conversation not found"); } - - // Try simple substring match - const index = contentLower.indexOf(queryLower); - if (index !== -1) { - return { - start: index, - end: index + queryLower.length - 1, - text: content.substring(index, index + queryLower.length), - }; + } else { + // todo: add validation on params.id + try { + new ObjectId(params.id); + } catch { + throw new Error("Invalid conversation ID format"); } + conversation = await collections.conversations.findOne({ + _id: new ObjectId(params.id), + ...authCondition(locals), + }); - return null; - }; - - // Create search variations - const searchVariations = [searchQuery.toLowerCase()]; - - // Add stemmed variations - try { - const stemmed = PorterStemmer.stem(searchQuery.toLowerCase()); - if (stemmed !== searchQuery.toLowerCase()) { - searchVariations.push(stemmed); - } + if (!conversation) { + const conversationExists = + (await collections.conversations.countDocuments({ + _id: new ObjectId(params.id), + })) !== 0; - // Find actual words in conversations that stem to the same root - for (const message of conv.messages) { - if (message.content) { - const words = message.content.toLowerCase().match(/\b\w+\b/g) || []; - words.forEach((word: string) => { - if ( - PorterStemmer.stem(word) === stemmed && - !searchVariations.includes(word) - ) { - searchVariations.push(word); - } - }); + if (conversationExists) { + throw new Error( + "You don't have access to this conversation. If someone gave you this link, ask them to use the 'share' feature instead." + ); } - } - } catch (e) { - console.warn("Stemming failed for:", searchQuery, e); - } - // Add simple variations - const query = searchQuery.toLowerCase(); - if (query.endsWith("s") && query.length > 3) { - searchVariations.push(query.slice(0, -1)); - } else if (!query.endsWith("s")) { - searchVariations.push(query + "s"); - } - - // Search through all messages for the best match - for (const message of conv.messages) { - if (!message.content) continue; - - // Try each variation in order of preference - for (const variation of searchVariations) { - const match = findBestMatch(message.content, variation); - if (match) { - const isExactQuery = variation === searchQuery.toLowerCase(); - const priority = isExactQuery ? 1000 : match.text.length; - - if (priority > bestMatchLength) { - bestMatch = { - content: message.content, - matchStart: match.start, - matchEnd: match.end, - matchedText: match.text, - }; - bestMatchLength = priority; - - // If we found exact query match, we're done - if (isExactQuery) break; - } - } + throw new Error("Conversation not found."); } - - // Stop if we found an exact match - if (bestMatchLength >= 1000) break; } - if (bestMatch) { - const { content, matchStart, matchEnd } = bestMatch; - matchedText = bestMatch.matchedText; - - // Create centered context around the match - const maxContextLength = 160; // Maximum length of actual content (no padding) - const matchLength = matchEnd - matchStart + 1; - - // Calculate context window - don't exceed maxContextLength even if content is longer - const availableForContext = - Math.min(maxContextLength, content.length) - matchLength; - const contextPerSide = Math.floor(availableForContext / 2); - - // Calculate snippet boundaries to center the match within maxContextLength - let snippetStart = Math.max(0, matchStart - contextPerSide); - let snippetEnd = Math.min( - content.length, - matchStart + matchLength + contextPerSide - ); - - // Ensure we don't exceed maxContextLength - if (snippetEnd - snippetStart > maxContextLength) { - if (matchStart - contextPerSide < 0) { - // Match is near start, extend end but limit to maxContextLength - snippetEnd = Math.min(content.length, snippetStart + maxContextLength); - } else { - // Match is not near start, limit to maxContextLength from match start - snippetEnd = Math.min(content.length, snippetStart + maxContextLength); - } - } - - // Adjust to word boundaries if possible (but don't move more than 15 chars) - const originalStart = snippetStart; - const originalEnd = snippetEnd; - - while ( - snippetStart > 0 && - content[snippetStart] !== " " && - content[snippetStart] !== "\n" && - originalStart - snippetStart < 15 - ) { - snippetStart--; - } - while ( - snippetEnd < content.length && - content[snippetEnd] !== " " && - content[snippetEnd] !== "\n" && - snippetEnd - originalEnd < 15 - ) { - snippetEnd++; - } - - // Extract the content - let extractedContent = content.substring(snippetStart, snippetEnd).trim(); - // Add ellipsis indicators only - if (snippetStart > 0) { - extractedContent = "..." + extractedContent; - } - if (snippetEnd < content.length) { - extractedContent = extractedContent + "..."; - } - - matchedContent = extractedContent; - } else { - // Fallback: use beginning of the first message if no match found - const firstMessage = conv.messages[0]; - if (firstMessage?.content) { - const content = firstMessage.content; - matchedContent = - content.length > 200 ? content.substring(0, 200) + "..." : content; - matchedText = searchQuery; // Fallback to search query - } - } + const convertedConv = { + ...conversation, + ...convertLegacyConversation(conversation), + shared, + }; + return { conversation: convertedConv }; + }) + .get("", async ({ conversation }) => { return { - _id: conv._id, - id: conv._id, - title: conv.title, - content: matchedContent, - matchedText, - updatedAt: conv.updatedAt, - model: conv.model, - assistantId: conv.assistantId, - modelTools: models.find((m) => m.id == conv.model)?.tools ?? false, + messages: conversation.messages, + title: conversation.title, + model: conversation.model, + preprompt: conversation.preprompt, + rootMessageId: conversation.rootMessageId, + id: conversation._id.toString(), + updatedAt: conversation.updatedAt, + modelId: conversation.model, + shared: conversation.shared, }; }) - ); - - return convs; - }, - { - query: t.Object({ - q: t.String(), - p: t.Optional(t.Number()), - }), - } - ) - .group( - "/:id", - { - params: t.Object({ - id: t.String(), - }), - }, - (app) => { - return app - .derive(async ({ locals, params }) => { - let conversation; - let shared = false; - - // if the conver - if (params.id.length === 7) { - // shared link of length 7 - conversation = await collections.sharedConversations.findOne({ - _id: params.id, - }); - shared = true; - - if (!conversation) { - throw new Error("Conversation not found"); - } - } else { - // todo: add validation on params.id - try { - new ObjectId(params.id); - } catch { - throw new Error("Invalid conversation ID format"); - } - conversation = await collections.conversations.findOne({ + .post("", () => { + // todo: post new message + throw new Error("Not implemented"); + }) + .delete("", async ({ locals, params }) => { + const res = await collections.conversations.deleteOne({ _id: new ObjectId(params.id), ...authCondition(locals), }); - if (!conversation) { - const conversationExists = - (await collections.conversations.countDocuments({ - _id: new ObjectId(params.id), - })) !== 0; - - if (conversationExists) { - throw new Error( - "You don't have access to this conversation. If someone gave you this link, ask them to use the 'share' feature instead." - ); - } - - throw new Error("Conversation not found."); + if (res.deletedCount === 0) { + throw new Error("Conversation not found"); } - } - - const convertedConv = { - ...conversation, - ...convertLegacyConversation(conversation), - shared, - }; - return { conversation: convertedConv }; - }) - .get("", async ({ conversation }) => { - return { - messages: conversation.messages, - title: conversation.title, - model: conversation.model, - preprompt: conversation.preprompt, - rootMessageId: conversation.rootMessageId, - assistant: conversation.assistantId - ? ((await collections.assistants.findOne({ - _id: new ObjectId(conversation.assistantId), - })) ?? undefined) - : undefined, - id: conversation._id.toString(), - updatedAt: conversation.updatedAt, - modelId: conversation.model, - assistantId: conversation.assistantId, - modelTools: models.find((m) => m.id == conversation.model)?.tools ?? false, - shared: conversation.shared, - }; - }) - .post("", () => { - // todo: post new message - throw new Error("Not implemented"); - }) - .delete("", async ({ locals, params }) => { - const res = await collections.conversations.deleteOne({ - _id: new ObjectId(params.id), - ...authCondition(locals), - }); - - if (res.deletedCount === 0) { - throw new Error("Conversation not found"); - } - - return { success: true }; - }) - .get("/output/:sha256", () => { - // todo: get output - throw new Error("Not implemented"); - }) - .post("/share", () => { - // todo: share conversation - throw new Error("Not implemented"); - }) - .post("/stop-generating", () => { - // todo: stop generating - throw new Error("Not implemented"); - }) - .patch( - "", - async ({ locals, params, body }) => { - if (body.model) { - if (!validModelIdSchema.safeParse(body.model).success) { - throw new Error("Invalid model ID"); + return { success: true }; + }) + .get("/output/:sha256", () => { + // todo: get output + throw new Error("Not implemented"); + }) + .post("/share", () => { + // todo: share conversation + throw new Error("Not implemented"); + }) + .post("/stop-generating", () => { + // todo: stop generating + throw new Error("Not implemented"); + }) + .patch( + "", + async ({ locals, params, body }) => { + if (body.model) { + if (!validModelIdSchema.safeParse(body.model).success) { + throw new Error("Invalid model ID"); + } } - } - // Only include defined values in the update - const updateValues = { - ...(body.title !== undefined && { title: body.title }), - ...(body.model !== undefined && { model: body.model }), - }; + // Only include defined values in the update (sanitize title) + const updateValues = { + ...(body.title !== undefined && { + title: body.title.replace(/<\/?think>/gi, "").trim(), + }), + ...(body.model !== undefined && { model: body.model }), + }; - const res = await collections.conversations.updateOne( - { - _id: new ObjectId(params.id), - ...authCondition(locals), - }, - { - $set: updateValues, + const res = await collections.conversations.updateOne( + { + _id: new ObjectId(params.id), + ...authCondition(locals), + }, + { + $set: updateValues, + } + ); + + if (res.modifiedCount === 0) { + throw new Error("Conversation not found"); } - ); - if (res.modifiedCount === 0) { - throw new Error("Conversation not found"); + return { success: true }; + }, + { + body: t.Object({ + title: t.Optional( + t.String({ + minLength: 1, + maxLength: 100, + }) + ), + model: t.Optional(t.String()), + }), } + ) + .delete( + "/message/:messageId", + async ({ locals, params, conversation }) => { + if (!conversation.messages.map((m) => m.id).includes(params.messageId)) { + throw new Error("Message not found"); + } - return { success: true }; - }, - { - body: t.Object({ - title: t.Optional( - t.String({ - minLength: 1, - maxLength: 100, - }) - ), - model: t.Optional(t.String()), - }), - } - ) - .delete( - "/message/:messageId", - async ({ locals, params, conversation }) => { - if (!conversation.messages.map((m) => m.id).includes(params.messageId)) { - throw new Error("Message not found"); - } + const filteredMessages = conversation.messages + .filter( + (message) => + // not the message AND the message is not in ancestors + !(message.id === params.messageId) && + message.ancestors && + !message.ancestors.includes(params.messageId) + ) + .map((message) => { + // remove the message from children if it's there + if (message.children && message.children.includes(params.messageId)) { + message.children = message.children.filter( + (child) => child !== params.messageId + ); + } + return message; + }); - const filteredMessages = conversation.messages - .filter( - (message) => - // not the message AND the message is not in ancestors - !(message.id === params.messageId) && - message.ancestors && - !message.ancestors.includes(params.messageId) - ) - .map((message) => { - // remove the message from children if it's there - if (message.children && message.children.includes(params.messageId)) { - message.children = message.children.filter( - (child) => child !== params.messageId - ); - } - return message; - }); + const res = await collections.conversations.updateOne( + { _id: new ObjectId(conversation._id), ...authCondition(locals) }, + { $set: { messages: filteredMessages } } + ); - const res = await collections.conversations.updateOne( - { _id: new ObjectId(conversation._id), ...authCondition(locals) }, - { $set: { messages: filteredMessages } } - ); + if (res.modifiedCount === 0) { + throw new Error("Deleting message failed"); + } - if (res.modifiedCount === 0) { - throw new Error("Deleting message failed"); + return { success: true }; + }, + { + params: t.Object({ + id: t.String(), + messageId: t.String(), + }), } - - return { success: true }; - }, - { - params: t.Object({ - id: t.String(), - messageId: t.String(), - }), - } - ); - } - ); + ); + } + ) + ); }); diff --git a/src/lib/server/api/routes/groups/debug.ts b/src/lib/server/api/routes/groups/debug.ts new file mode 100644 index 0000000000000000000000000000000000000000..7d2a4891e06543d7ffddb58e34c37a9391c95c55 --- /dev/null +++ b/src/lib/server/api/routes/groups/debug.ts @@ -0,0 +1,43 @@ +import { Elysia } from "elysia"; +import { config } from "$lib/server/config"; + +export const debugGroup = new Elysia().group("/debug", (app) => + app + .get("/config", async () => { + const { models } = await import("$lib/server/models"); + return { + OPENAI_BASE_URL: config.OPENAI_BASE_URL, + OPENAI_API_KEY_SET: Boolean(config.OPENAI_API_KEY || config.HF_TOKEN), + LEGACY_HF_TOKEN_SET: Boolean(config.HF_TOKEN && !config.OPENAI_API_KEY), + MODELS_COUNT: models.length, + NODE_VERSION: process.versions.node, + }; + }) + .get("/refresh", async () => { + const base = (config.OPENAI_BASE_URL || "https://router.huggingface.co/v1").replace( + /\/$/, + "" + ); + const res = await fetch(`${base}/models`); + const body = await res.text(); + let parsed: unknown; + try { + parsed = JSON.parse(body); + } catch (_err) { + parsed = undefined; + } + return { + status: res.status, + ok: res.ok, + base, + length: (() => { + if (parsed && typeof parsed === "object" && "data" in parsed) { + const data = (parsed as { data?: unknown }).data; + return Array.isArray(data) ? data.length : null; + } + return null; + })(), + sample: body.slice(0, 2000), + }; + }) +); diff --git a/src/lib/server/api/routes/groups/misc.ts b/src/lib/server/api/routes/groups/misc.ts index ee0f5cbf7e565312b8586fc690e3562532724cee..a82fdf45abc339980b0767f710ccbea0840fa739 100644 --- a/src/lib/server/api/routes/groups/misc.ts +++ b/src/lib/server/api/routes/groups/misc.ts @@ -11,10 +11,7 @@ import mimeTypes from "mime-types"; import { logger } from "$lib/server/logger"; export interface FeatureFlags { - searchEnabled: boolean; enableAssistants: boolean; - enableAssistantsRAG: boolean; - enableCommunityTools: boolean; loginEnabled: boolean; loginRequired: boolean; guestMode: boolean; @@ -59,19 +56,7 @@ export const misc = new Elysia() } return { - searchEnabled: !!( - config.SERPAPI_KEY || - config.SERPER_API_KEY || - config.SERPSTACK_API_KEY || - config.SEARCHAPI_KEY || - config.YDC_API_KEY || - config.USE_LOCAL_WEBSEARCH || - config.SEARXNG_QUERY_URL || - config.BING_SUBSCRIPTION_KEY - ), enableAssistants: config.ENABLE_ASSISTANTS === "true", - enableAssistantsRAG: config.ENABLE_ASSISTANTS_RAG === "true", - enableCommunityTools: config.COMMUNITY_TOOLS === "true", loginEnabled: requiresUser, // misnomer, this is actually whether the feature is available, not required loginRequired, guestMode: requiresUser && messagesBeforeLogin > 0, @@ -136,9 +121,9 @@ export const misc = new Elysia() const stats: { nConversations: number; nMessages: number; + nFiles: number; nAssistants: number; nAvatars: number; - nFiles: number; } = { nConversations: 0, nMessages: 0, @@ -195,13 +180,6 @@ export const misc = new Elysia() messages: conversation.messages.map((message) => { return { ...message, - webSearch: message.webSearch - ? { - prompt: message.webSearch?.prompt, - searchQuery: message.webSearch?.searchQuery, - results: message.webSearch?.results.map((result) => result.link), - } - : undefined, files: filenames, updates: undefined, }; @@ -258,8 +236,6 @@ export const misc = new Elysia() description: assistant.description, dynamicPrompt: assistant.dynamicPrompt, exampleInputs: assistant.exampleInputs, - rag: assistant.rag, - tools: assistant.tools, generateSettings: assistant.generateSettings, createdAt: assistant.createdAt.toISOString(), updatedAt: assistant.updatedAt.toISOString(), diff --git a/src/lib/server/api/routes/groups/models.ts b/src/lib/server/api/routes/groups/models.ts index e794ddc536fda06a1d1ae3b4247d442ffec64f11..4594c0e08b48ac5590e8e06f5b81aac142ccf63a 100644 --- a/src/lib/server/api/routes/groups/models.ts +++ b/src/lib/server/api/routes/groups/models.ts @@ -1,5 +1,5 @@ import { Elysia } from "elysia"; -import { models, oldModels, type BackendModel } from "$lib/server/models"; +import type { BackendModel } from "$lib/server/models"; import { authPlugin } from "../../authPlugin"; import { authCondition } from "$lib/server/auth"; import { collections } from "$lib/server/database"; @@ -9,21 +9,22 @@ export type GETModelsResponse = Array<{ name: string; websiteUrl?: string; modelUrl?: string; - tokenizer?: string | { tokenizerUrl: string; tokenizerConfigUrl: string }; datasetName?: string; datasetUrl?: string; displayName: string; description?: string; reasoning: boolean; logoUrl?: string; + providers?: Array<{ provider: string } & Record>; promptExamples?: { title: string; prompt: string }[]; parameters: BackendModel["parameters"]; preprompt?: string; multimodal: boolean; multimodalAcceptedMimetypes?: string[]; - tools: boolean; unlisted: boolean; hasInferenceAPI: boolean; + // Mark router entry for UI decoration — always present + isRouter: boolean; }>; export type GETOldModelsResponse = Array<{ @@ -35,33 +36,46 @@ export type GETOldModelsResponse = Array<{ export const modelGroup = new Elysia().group("/models", (app) => app - .get("/", () => { - return models - .filter((m) => m.unlisted == false) - .map((model) => ({ - id: model.id, - name: model.name, - websiteUrl: model.websiteUrl, - modelUrl: model.modelUrl, - tokenizer: model.tokenizer, - datasetName: model.datasetName, - datasetUrl: model.datasetUrl, - displayName: model.displayName, - description: model.description, - reasoning: !!model.reasoning, - logoUrl: model.logoUrl, - promptExamples: model.promptExamples, - parameters: model.parameters, - preprompt: model.preprompt, - multimodal: model.multimodal, - multimodalAcceptedMimetypes: model.multimodalAcceptedMimetypes, - tools: model.tools, - unlisted: model.unlisted, - hasInferenceAPI: model.hasInferenceAPI, - })) satisfies GETModelsResponse; + .get("/", async () => { + try { + const { models } = await import("$lib/server/models"); + return models + .filter((m) => m.unlisted == false) + .map((model) => ({ + id: model.id, + name: model.name, + websiteUrl: model.websiteUrl, + modelUrl: model.modelUrl, + datasetName: model.datasetName, + datasetUrl: model.datasetUrl, + displayName: model.displayName, + description: model.description, + reasoning: !!model.reasoning, + logoUrl: model.logoUrl, + providers: model.providers as unknown as Array< + { provider: string } & Record + >, + promptExamples: model.promptExamples, + parameters: model.parameters, + preprompt: model.preprompt, + multimodal: model.multimodal, + multimodalAcceptedMimetypes: model.multimodalAcceptedMimetypes, + unlisted: model.unlisted, + hasInferenceAPI: model.hasInferenceAPI, + isRouter: model.isRouter, + })) satisfies GETModelsResponse; + } catch (e) { + // Return empty list instead of crashing the whole page + return [] as GETModelsResponse; + } }) - .get("/old", () => { - return oldModels satisfies GETOldModelsResponse; + .get("/old", async () => { + try { + const { oldModels } = await import("$lib/server/models"); + return oldModels satisfies GETOldModelsResponse; + } catch (e) { + return [] as GETOldModelsResponse; + } }) .group("/:namespace/:model?", (app) => app @@ -70,11 +84,16 @@ export const modelGroup = new Elysia().group("/models", (app) => if (params.model) { modelId += "/" + params.model; } - const model = models.find((m) => m.id === modelId); - if (!model || model.unlisted) { - return error(404, "Model not found"); + try { + const { models } = await import("$lib/server/models"); + const model = models.find((m) => m.id === modelId); + if (!model || model.unlisted) { + return error(404, "Model not found"); + } + return { model }; + } catch (e) { + return error(500, "Models not available"); } - return { model }; }) .get("/", ({ model }) => { return model; diff --git a/src/lib/server/api/routes/groups/tools.ts b/src/lib/server/api/routes/groups/tools.ts deleted file mode 100644 index 9803bef8c62523f5bd3b87d01fc48fd2e4c26e1d..0000000000000000000000000000000000000000 --- a/src/lib/server/api/routes/groups/tools.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { Elysia, t } from "elysia"; -import { authPlugin } from "$api/authPlugin"; -import { ReviewStatus } from "$lib/types/Review"; -import { toolFromConfigs } from "$lib/server/tools"; -import { collections } from "$lib/server/database"; -import { ObjectId, type Filter } from "mongodb"; -import type { CommunityToolDB, ToolFront, ToolInputFile } from "$lib/types/Tool"; -import { MetricsServer } from "$lib/server/metrics"; -import { authCondition } from "$lib/server/auth"; -import { SortKey } from "$lib/types/Assistant"; -import type { User } from "$lib/types/User"; -import { generateQueryTokens, generateSearchTokens } from "$lib/utils/searchTokens"; -import { config } from "$lib/server/config"; - -const NUM_PER_PAGE = 16; - -export const toolGroup = new Elysia().use(authPlugin).group("/tools", (app) => { - return app - .get("/active", async ({ locals }) => { - const settings = await collections.settings.findOne(authCondition(locals)); - - if (!settings) { - return []; - } - - const toolUseDuration = (await MetricsServer.getMetrics().tool.toolUseDuration.get()).values; - - const activeCommunityToolIds = settings.tools ?? []; - - const communityTools = await collections.tools - .find({ _id: { $in: activeCommunityToolIds.map((el) => new ObjectId(el)) } }) - .toArray() - .then((tools) => - tools.map((tool) => ({ - ...tool, - isHidden: false, - isOnByDefault: true, - isLocked: true, - })) - ); - - const fullTools = [...communityTools, ...toolFromConfigs]; - - return fullTools - .filter((tool) => !tool.isHidden) - .map( - (tool) => - ({ - _id: tool._id.toString(), - type: tool.type, - displayName: tool.displayName, - name: tool.name, - description: tool.description, - mimeTypes: (tool.inputs ?? []) - .filter((input): input is ToolInputFile => input.type === "file") - .map((input) => (input as ToolInputFile).mimeTypes) - .flat(), - isOnByDefault: tool.isOnByDefault ?? true, - isLocked: tool.isLocked ?? true, - timeToUseMS: - toolUseDuration.find( - (el) => el.labels.tool === tool._id.toString() && el.labels.quantile === 0.9 - )?.value ?? 15_000, - color: tool.color, - icon: tool.icon, - }) satisfies ToolFront - ); - }) - .get( - "/search", - async ({ query, locals, error }) => { - if (config.COMMUNITY_TOOLS !== "true") { - error(403, "Community tools are not enabled"); - } - - const username = query.user; - const search = query.q?.trim() ?? null; - - const pageIndex = query.p ?? 0; - const sort = query.sort ?? SortKey.TRENDING; - const createdByCurrentUser = locals.user?.username && locals.user.username === username; - const activeOnly = query.active ?? false; - const showUnfeatured = query.showUnfeatured ?? false; - - let user: Pick | null = null; - if (username) { - user = await collections.users.findOne>( - { username }, - { projection: { _id: 1 } } - ); - if (!user) { - error(404, `User "${username}" doesn't exist`); - } - } - - const settings = await collections.settings.findOne(authCondition(locals)); - - if (!settings && activeOnly) { - error(404, "No user settings found"); - } - - const queryTokens = !!search && generateQueryTokens(search); - - const filter: Filter = { - ...(!createdByCurrentUser && - !activeOnly && - !(locals.isAdmin && showUnfeatured) && { review: ReviewStatus.APPROVED }), - ...(user && { createdById: user._id }), - ...(queryTokens && { searchTokens: { $all: queryTokens } }), - ...(activeOnly && { - _id: { - $in: (settings?.tools ?? []).map((key) => { - return new ObjectId(key); - }), - }, - }), - }; - - const communityTools = await collections.tools - .find(filter) - .skip(NUM_PER_PAGE * pageIndex) - .sort({ - ...(sort === SortKey.TRENDING && { last24HoursUseCount: -1 }), - useCount: -1, - }) - .limit(NUM_PER_PAGE) - .toArray(); - - const configTools = toolFromConfigs - .filter((tool) => !tool?.isHidden) - .filter((tool) => { - if (queryTokens) { - return generateSearchTokens(tool.displayName).some((token) => - queryTokens.some((queryToken) => queryToken.test(token)) - ); - } - return true; - }); - - const tools = [...(pageIndex == 0 && !username ? configTools : []), ...communityTools]; - - const numTotalItems = - (await collections.tools.countDocuments(filter)) + toolFromConfigs.length; - - return { - tools, - numTotalItems, - numItemsPerPage: NUM_PER_PAGE, - query: search, - sort, - showUnfeatured, - }; - }, - { - query: t.Object({ - user: t.Optional(t.String()), - q: t.Optional(t.String()), - sort: t.Optional(t.Enum(SortKey)), - p: t.Optional(t.Numeric()), - showUnfeatured: t.Optional(t.Boolean()), - active: t.Optional(t.Boolean()), - }), - } - ) - .get("/count", () => { - // return community tool count - return collections.tools.countDocuments({ type: "community", review: ReviewStatus.APPROVED }); - }) - .group("/:id", (app) => { - return app - .derive(async ({ params, error, locals }) => { - const tool = await collections.tools.findOne({ _id: new ObjectId(params.id) }); - - if (!tool) { - const tool = toolFromConfigs.find((el) => el._id.toString() === params.id); - if (!tool) { - throw error(404, "Tool not found"); - } else { - return { - tool: { - ...tool, - _id: tool._id.toString(), - call: undefined, - createdById: null, - createdByName: null, - createdByMe: false, - reported: false, - review: ReviewStatus.APPROVED, - }, - }; - } - } else { - const reported = await collections.reports.findOne({ - contentId: tool._id, - object: "tool", - }); - - return { - tool: { - ...tool, - _id: tool._id.toString(), - call: undefined, - createdById: tool.createdById.toString(), - createdByMe: - tool.createdById.toString() === (locals.user?._id ?? locals.sessionId).toString(), - reported: !!reported, - }, - }; - } - }) - .get("", ({ tool }) => { - return tool; - }) - .post("/", () => { - // todo: post new tool - throw new Error("Not implemented"); - }) - .group("/:toolId", (app) => { - return app - .get("/", () => { - // todo: get tool - throw new Error("Not implemented"); - }) - .patch("/", () => { - // todo: patch tool - throw new Error("Not implemented"); - }) - .delete("/", () => { - // todo: delete tool - throw new Error("Not implemented"); - }) - .post("/report", () => { - // todo: report tool - throw new Error("Not implemented"); - }) - .patch("/review", () => { - // todo: review tool - throw new Error("Not implemented"); - }); - }); - }); -}); diff --git a/src/lib/server/api/routes/groups/user.ts b/src/lib/server/api/routes/groups/user.ts index 20e8a4a0577f0b5fd071c5c738b969154a1cb24d..14614b754a9ce2cfa06fcce5688c508e468b2f57 100644 --- a/src/lib/server/api/routes/groups/user.ts +++ b/src/lib/server/api/routes/groups/user.ts @@ -5,8 +5,6 @@ import { collections } from "$lib/server/database"; import { authCondition } from "$lib/server/auth"; import { models, validateModel } from "$lib/server/models"; import { DEFAULT_SETTINGS, type SettingsEditable } from "$lib/types/Settings"; -import { toolFromConfigs } from "$lib/server/tools"; -import { ObjectId } from "mongodb"; import { z } from "zod"; export const userGroup = new Elysia() @@ -41,11 +39,7 @@ export const userGroup = new Elysia() .get("/settings", async ({ locals }) => { const settings = await collections.settings.findOne(authCondition(locals)); - if ( - settings && - !validateModel(models).safeParse(settings?.activeModel).success && - !settings.assistants?.map((el) => el.toString())?.includes(settings?.activeModel) - ) { + if (settings && !validateModel(models).safeParse(settings?.activeModel).success) { settings.activeModel = defaultModel.id; await collections.settings.updateOne(authCondition(locals), { $set: { activeModel: defaultModel.id }, @@ -65,67 +59,47 @@ export const userGroup = new Elysia() // todo: get user settings return { - ethicsModalAccepted: !!settings?.ethicsModalAcceptedAt, - ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null, + welcomeModalSeen: !!settings?.welcomeModalSeenAt, + welcomeModalSeenAt: settings?.welcomeModalSeenAt ?? null, activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel, - hideEmojiOnSidebar: settings?.hideEmojiOnSidebar ?? DEFAULT_SETTINGS.hideEmojiOnSidebar, disableStream: settings?.disableStream ?? DEFAULT_SETTINGS.disableStream, directPaste: settings?.directPaste ?? DEFAULT_SETTINGS.directPaste, + hidePromptExamples: settings?.hidePromptExamples ?? DEFAULT_SETTINGS.hidePromptExamples, shareConversationsWithModelAuthors: settings?.shareConversationsWithModelAuthors ?? DEFAULT_SETTINGS.shareConversationsWithModelAuthors, customPrompts: settings?.customPrompts ?? {}, - assistants: settings?.assistants?.map((assistantId) => assistantId.toString()) ?? [], - tools: - settings?.tools ?? - toolFromConfigs - .filter((el) => !el.isHidden && el.isOnByDefault) - .map((el) => el._id.toString()), + multimodalOverrides: settings?.multimodalOverrides ?? {}, }; }) .post("/settings", async ({ locals, request }) => { const body = await request.json(); - const { ethicsModalAccepted, ...settings } = z + const { welcomeModalSeen, ...settings } = z .object({ shareConversationsWithModelAuthors: z .boolean() .default(DEFAULT_SETTINGS.shareConversationsWithModelAuthors), - hideEmojiOnSidebar: z.boolean().default(DEFAULT_SETTINGS.hideEmojiOnSidebar), - ethicsModalAccepted: z.boolean().optional(), + welcomeModalSeen: z.boolean().optional(), activeModel: z.string().default(DEFAULT_SETTINGS.activeModel), customPrompts: z.record(z.string()).default({}), - tools: z.array(z.string()).optional(), + multimodalOverrides: z.record(z.boolean()).default({}), disableStream: z.boolean().default(false), directPaste: z.boolean().default(false), + hidePromptExamples: z.record(z.boolean()).default({}), }) .parse(body) satisfies SettingsEditable; - // make sure all tools exist - // either in db or in config - if (settings.tools) { - const newTools = [ - ...(await collections.tools - .find({ _id: { $in: settings.tools.map((toolId) => new ObjectId(toolId)) } }) - .project({ _id: 1 }) - .toArray() - .then((tools) => tools.map((tool) => tool._id.toString()))), - ...toolFromConfigs - .filter((el) => (settings?.tools ?? []).includes(el._id.toString())) - .map((el) => el._id.toString()), - ]; - - settings.tools = newTools; - } + // Tools removed: ignore tools updates await collections.settings.updateOne( authCondition(locals), { $set: { ...settings, - ...(ethicsModalAccepted && { ethicsModalAcceptedAt: new Date() }), + ...(welcomeModalSeen && { welcomeModalSeenAt: new Date() }), updatedAt: new Date(), }, $setOnInsert: { @@ -150,46 +124,5 @@ export const userGroup = new Elysia() }) .toArray(); return reports; - }) - .get("/assistant/active", async ({ locals }) => { - const settings = await collections.settings.findOne(authCondition(locals)); - - if (!settings) { - return null; - } - - if (settings.assistants?.map((el) => el.toString())?.includes(settings?.activeModel)) { - return await collections.assistants.findOne({ - _id: new ObjectId(settings.activeModel), - }); - } - - return null; - }) - .get("/assistants", async ({ locals }) => { - const settings = await collections.settings.findOne(authCondition(locals)); - - if (!settings) { - return []; - } - - const userAssistants = - settings?.assistants?.map((assistantId) => assistantId.toString()) ?? []; - - const assistants = await collections.assistants - .find({ - _id: { - $in: [...userAssistants.map((el) => new ObjectId(el))], - }, - }) - .toArray(); - - return assistants.map((el) => ({ - ...el, - _id: el._id.toString(), - createdById: undefined, - createdByMe: - el.createdById.toString() === (locals.user?._id ?? locals.sessionId).toString(), - })); }); }); diff --git a/src/lib/server/config.ts b/src/lib/server/config.ts index f65e19ecb45aad6c9bbfc74d811afd492740df2f..c093bb2f4f287acc85ea1f32d344db17ab39accf 100644 --- a/src/lib/server/config.ts +++ b/src/lib/server/config.ts @@ -151,7 +151,9 @@ export const ready = (async () => { } })(); -type ConfigProxy = ConfigManager & { [K in ConfigKey]: string }; +type ExtraConfigKeys = "HF_TOKEN" | "OLD_MODELS" | "ENABLE_ASSISTANTS"; + +type ConfigProxy = ConfigManager & { [K in ConfigKey | ExtraConfigKeys]: string }; export const config: ConfigProxy = new Proxy(configManager, { get(target, prop, receiver) { diff --git a/src/lib/server/database.ts b/src/lib/server/database.ts index 68a1e9ad6c483ac7450f65990ecde7d9b0f2475a..a1bd56ec73ac96f49e4f4d3866adf8a42ddd43fc 100644 --- a/src/lib/server/database.ts +++ b/src/lib/server/database.ts @@ -12,7 +12,6 @@ import type { ConversationStats } from "$lib/types/ConversationStats"; import type { MigrationResult } from "$lib/types/MigrationResult"; import type { Semaphore } from "$lib/types/Semaphore"; import type { AssistantStats } from "$lib/types/AssistantStats"; -import type { CommunityToolDB } from "$lib/types/Tool"; import { MongoMemoryServer } from "mongodb-memory-server"; import { logger } from "$lib/server/logger"; import { building } from "$app/environment"; @@ -130,7 +129,7 @@ export class Database { const migrationResults = db.collection("migrationResults"); const semaphores = db.collection("semaphores"); const tokenCaches = db.collection("tokens"); - const tools = db.collection("tools"); + const tools = db.collection("tools"); const configCollection = db.collection("config"); return { @@ -173,7 +172,6 @@ export class Database { messageEvents, semaphores, tokenCaches, - tools, config, } = this.getCollections(); @@ -271,9 +269,7 @@ export class Database { .createIndex({ createdAt: 1 }, { expireAfterSeconds: 5 * 60 }) .catch((e) => logger.error(e)); tokenCaches.createIndex({ tokenHash: 1 }).catch((e) => logger.error(e)); - tools.createIndex({ createdById: 1, userCount: -1 }).catch((e) => logger.error(e)); - tools.createIndex({ userCount: 1 }).catch((e) => logger.error(e)); - tools.createIndex({ last24HoursCount: 1 }).catch((e) => logger.error(e)); + // Tools removed: skipping tools indexes conversations .createIndex({ diff --git a/src/lib/server/embeddingEndpoints/embeddingEndpoints.ts b/src/lib/server/embeddingEndpoints/embeddingEndpoints.ts deleted file mode 100644 index 053e4316605e098cf3957bceff324a6284c76481..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingEndpoints/embeddingEndpoints.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { z } from "zod"; -import { - embeddingEndpointTei, - embeddingEndpointTeiParametersSchema, -} from "./tei/embeddingEndpoints"; -import { - embeddingEndpointTransformersJS, - embeddingEndpointTransformersJSParametersSchema, -} from "./transformersjs/embeddingEndpoints"; -import { - embeddingEndpointOpenAI, - embeddingEndpointOpenAIParametersSchema, -} from "./openai/embeddingEndpoints"; -import { embeddingEndpointHfApi, embeddingEndpointHfApiSchema } from "./hfApi/embeddingHfApi"; - -// parameters passed when generating text -interface EmbeddingEndpointParameters { - inputs: string[]; -} - -export type Embedding = number[]; - -// type signature for the endpoint -export type EmbeddingEndpoint = (params: EmbeddingEndpointParameters) => Promise; - -export const embeddingEndpointSchema = z.discriminatedUnion("type", [ - embeddingEndpointTeiParametersSchema, - embeddingEndpointTransformersJSParametersSchema, - embeddingEndpointOpenAIParametersSchema, - embeddingEndpointHfApiSchema, -]); - -type EmbeddingEndpointTypeOptions = z.infer["type"]; - -// generator function that takes in type discrimantor value for defining the endpoint and return the endpoint -export type EmbeddingEndpointGenerator = ( - inputs: Extract, { type: T }> -) => EmbeddingEndpoint | Promise; - -// list of all endpoint generators -export const embeddingEndpoints: { - [Key in EmbeddingEndpointTypeOptions]: EmbeddingEndpointGenerator; -} = { - tei: embeddingEndpointTei, - transformersjs: embeddingEndpointTransformersJS, - openai: embeddingEndpointOpenAI, - hfapi: embeddingEndpointHfApi, -}; - -export default embeddingEndpoints; diff --git a/src/lib/server/embeddingEndpoints/hfApi/embeddingHfApi.ts b/src/lib/server/embeddingEndpoints/hfApi/embeddingHfApi.ts deleted file mode 100644 index d60e37c9f83ffa41e07b64f3036b64e6fab40f6d..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingEndpoints/hfApi/embeddingHfApi.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { z } from "zod"; -import type { EmbeddingEndpoint, Embedding } from "../embeddingEndpoints"; -import { chunk } from "$lib/utils/chunk"; -import { config } from "$lib/server/config"; -import { logger } from "$lib/server/logger"; - -export const embeddingEndpointHfApiSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("hfapi"), - authorization: z - .string() - .optional() - .transform((v) => (!v && config.HF_TOKEN ? "Bearer " + config.HF_TOKEN : v)), // if the header is not set but HF_TOKEN is, use it as the authorization header -}); - -export async function embeddingEndpointHfApi( - input: z.input -): Promise { - const { model, authorization } = embeddingEndpointHfApiSchema.parse(input); - const url = `${config.HF_API_ROOT}/${model.id}`; - - return async ({ inputs }) => { - const batchesInputs = chunk(inputs, 128); - - const batchesResults = await Promise.all( - batchesInputs.map(async (batchInputs) => { - const response = await fetch(`${url}`, { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - ...(authorization ? { Authorization: authorization } : {}), - }, - body: JSON.stringify({ - inputs: { - source_sentence: batchInputs[0], - sentences: batchInputs.slice(1), - }, - }), - }); - - if (!response.ok) { - logger.error(await response.text()); - logger.error(response, "Failed to get embeddings from Hugging Face API"); - return []; - } - - const embeddings: Embedding[] = await response.json(); - return embeddings; - }) - ); - - const flatAllEmbeddings = batchesResults.flat(); - - return flatAllEmbeddings; - }; -} diff --git a/src/lib/server/embeddingEndpoints/openai/embeddingEndpoints.ts b/src/lib/server/embeddingEndpoints/openai/embeddingEndpoints.ts deleted file mode 100644 index d3c1edf161f10a6c5565091991a61d1c7f12e223..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingEndpoints/openai/embeddingEndpoints.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { z } from "zod"; -import type { EmbeddingEndpoint, Embedding } from "../embeddingEndpoints"; -import { chunk } from "$lib/utils/chunk"; -import { config } from "$lib/server/config"; - -export const embeddingEndpointOpenAIParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("openai"), - url: z.string().url().default("https://api.openai.com/v1/embeddings"), - apiKey: z.string().default(config.OPENAI_API_KEY), - defaultHeaders: z.record(z.string()).default({}), -}); - -export async function embeddingEndpointOpenAI( - input: z.input -): Promise { - const { url, model, apiKey, defaultHeaders } = - embeddingEndpointOpenAIParametersSchema.parse(input); - - const maxBatchSize = model.maxBatchSize || 100; - - return async ({ inputs }) => { - const requestURL = new URL(url); - - const batchesInputs = chunk(inputs, maxBatchSize); - - const batchesResults = await Promise.all( - batchesInputs.map(async (batchInputs) => { - const response = await fetch(requestURL, { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}), - ...defaultHeaders, - }, - body: JSON.stringify({ input: batchInputs, model: model.name }), - }); - - const embeddings: Embedding[] = []; - const responseObject = await response.json(); - for (const embeddingObject of responseObject.data) { - embeddings.push(embeddingObject.embedding); - } - return embeddings; - }) - ); - - const flatAllEmbeddings = batchesResults.flat(); - - return flatAllEmbeddings; - }; -} diff --git a/src/lib/server/embeddingEndpoints/tei/embeddingEndpoints.ts b/src/lib/server/embeddingEndpoints/tei/embeddingEndpoints.ts deleted file mode 100644 index fa096aee58c95d0c29f9104f695afc6b440f109c..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingEndpoints/tei/embeddingEndpoints.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { z } from "zod"; -import type { EmbeddingEndpoint, Embedding } from "../embeddingEndpoints"; -import { chunk } from "$lib/utils/chunk"; -import { config } from "$lib/server/config"; -import { logger } from "$lib/server/logger"; - -export const embeddingEndpointTeiParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("tei"), - url: z.string().url(), - authorization: z - .string() - .optional() - .transform((v) => (!v && config.HF_TOKEN ? "Bearer " + config.HF_TOKEN : v)), // if the header is not set but HF_TOKEN is, use it as the authorization header -}); - -const getModelInfoByUrl = async (url: string, authorization?: string) => { - const { origin } = new URL(url); - - const response = await fetch(`${origin}/info`, { - headers: { - Accept: "application/json", - "Content-Type": "application/json", - ...(authorization ? { Authorization: authorization } : {}), - }, - }); - - try { - const json = await response.json(); - return { max_client_batch_size: 32, max_batch_tokens: 16384, ...json }; - } catch { - logger.debug("Could not get info from TEI embedding endpoint. Using defaults."); - return { max_client_batch_size: 32, max_batch_tokens: 16384 }; - } -}; - -export async function embeddingEndpointTei( - input: z.input -): Promise { - const { url, model, authorization } = embeddingEndpointTeiParametersSchema.parse(input); - - const { max_client_batch_size, max_batch_tokens } = await getModelInfoByUrl(url); - const maxBatchSize = Math.min( - max_client_batch_size, - Math.floor(max_batch_tokens / model.chunkCharLength) - ); - - return async ({ inputs }) => { - const { origin } = new URL(url); - - const batchesInputs = chunk(inputs, maxBatchSize); - - const batchesResults = await Promise.all( - batchesInputs.map(async (batchInputs) => { - const response = await fetch(`${origin}/embed`, { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - ...(authorization ? { Authorization: authorization } : {}), - }, - body: JSON.stringify({ inputs: batchInputs, normalize: true, truncate: true }), - }); - - const embeddings: Embedding[] = await response.json(); - return embeddings; - }) - ); - - const flatAllEmbeddings = batchesResults.flat(); - - return flatAllEmbeddings; - }; -} diff --git a/src/lib/server/embeddingEndpoints/transformersjs/embeddingEndpoints.ts b/src/lib/server/embeddingEndpoints/transformersjs/embeddingEndpoints.ts deleted file mode 100644 index 802937e39164192e54b74dca9caa4c779fa32411..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingEndpoints/transformersjs/embeddingEndpoints.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { z } from "zod"; -import type { EmbeddingEndpoint } from "../embeddingEndpoints"; -import type { Tensor, FeatureExtractionPipeline } from "@huggingface/transformers"; -import { pipeline } from "@huggingface/transformers"; - -export const embeddingEndpointTransformersJSParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("transformersjs"), -}); - -// Use the Singleton pattern to enable lazy construction of the pipeline. -class TransformersJSModelsSingleton { - static instances: Array<[string, Promise]> = []; - - static async getInstance(modelName: string): Promise { - const modelPipelineInstance = this.instances.find(([name]) => name === modelName); - - if (modelPipelineInstance) { - const [, modelPipeline] = modelPipelineInstance; - // dispose of the previous pipeline to clear memory - await (await modelPipeline).dispose(); - this.instances = this.instances.filter(([name]) => name !== modelName); - } - const newModelPipeline = pipeline("feature-extraction", modelName); - this.instances.push([modelName, newModelPipeline]); - - return newModelPipeline; - } -} - -export async function calculateEmbedding(modelName: string, inputs: string[]) { - const extractor = await TransformersJSModelsSingleton.getInstance(modelName); - const output: Tensor = await extractor(inputs, { pooling: "mean", normalize: true }); - - return output.tolist(); -} - -export function embeddingEndpointTransformersJS( - input: z.input -): EmbeddingEndpoint { - const { model } = embeddingEndpointTransformersJSParametersSchema.parse(input); - - return async ({ inputs }) => { - return calculateEmbedding(model.name, inputs); - }; -} diff --git a/src/lib/server/embeddingModels.ts b/src/lib/server/embeddingModels.ts deleted file mode 100644 index 9bbe8cf9c0613a18257c4e40e77410fb8877288e..0000000000000000000000000000000000000000 --- a/src/lib/server/embeddingModels.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { config } from "$lib/server/config"; - -import { z } from "zod"; -import { sum } from "$lib/utils/sum"; -import { - embeddingEndpoints, - embeddingEndpointSchema, - type EmbeddingEndpoint, -} from "$lib/server/embeddingEndpoints/embeddingEndpoints"; -import { embeddingEndpointTransformersJS } from "$lib/server/embeddingEndpoints/transformersjs/embeddingEndpoints"; - -import JSON5 from "json5"; - -const modelConfig = z.object({ - /** Used as an identifier in DB */ - id: z.string().optional(), - /** Used to link to the model page, and for inference */ - name: z.string().min(1), - displayName: z.string().min(1).optional(), - description: z.string().min(1).optional(), - websiteUrl: z.string().url().optional(), - modelUrl: z.string().url().optional(), - endpoints: z.array(embeddingEndpointSchema).nonempty(), - chunkCharLength: z.number().positive(), - maxBatchSize: z.number().positive().optional(), - preQuery: z.string().default(""), - prePassage: z.string().default(""), -}); - -// Default embedding model for backward compatibility -const rawEmbeddingModelJSON = - config.TEXT_EMBEDDING_MODELS || - `[ - { - "name": "Xenova/gte-small", - "chunkCharLength": 512, - "endpoints": [ - { "type": "transformersjs" } - ] - } -]`; - -const embeddingModelsRaw = z.array(modelConfig).parse(JSON5.parse(rawEmbeddingModelJSON)); - -const processEmbeddingModel = async (m: z.infer) => ({ - ...m, - id: m.id || m.name, -}); - -const addEndpoint = (m: Awaited>) => ({ - ...m, - getEndpoint: async (): Promise => { - if (!m.endpoints) { - return embeddingEndpointTransformersJS({ - type: "transformersjs", - weight: 1, - model: m, - }); - } - - const totalWeight = sum(m.endpoints.map((e) => e.weight)); - - let random = Math.random() * totalWeight; - - for (const endpoint of m.endpoints) { - if (random < endpoint.weight) { - const args = { ...endpoint, model: m }; - - switch (args.type) { - case "tei": - return embeddingEndpoints.tei(args); - case "transformersjs": - return embeddingEndpoints.transformersjs(args); - case "openai": - return embeddingEndpoints.openai(args); - case "hfapi": - return embeddingEndpoints.hfapi(args); - default: - throw new Error(`Unknown endpoint type: ${args}`); - } - } - - random -= endpoint.weight; - } - - throw new Error(`Failed to select embedding endpoint`); - }, -}); - -export const embeddingModels = await Promise.all( - embeddingModelsRaw.map((e) => processEmbeddingModel(e).then(addEndpoint)) -); - -export const defaultEmbeddingModel = embeddingModels[0]; - -const validateEmbeddingModel = (_models: EmbeddingBackendModel[], key: "id" | "name") => { - return z.enum([_models[0][key], ..._models.slice(1).map((m) => m[key])]); -}; - -export const validateEmbeddingModelById = (_models: EmbeddingBackendModel[]) => { - return validateEmbeddingModel(_models, "id"); -}; - -export const validateEmbeddingModelByName = (_models: EmbeddingBackendModel[]) => { - return validateEmbeddingModel(_models, "name"); -}; - -export type EmbeddingBackendModel = typeof defaultEmbeddingModel; diff --git a/src/lib/server/endpoints/anthropic/endpointAnthropic.ts b/src/lib/server/endpoints/anthropic/endpointAnthropic.ts deleted file mode 100644 index a542e932d94be28f62a63402a7abb5fa054c4c19..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/anthropic/endpointAnthropic.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; -import { config } from "$lib/server/config"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import { createImageProcessorOptionsValidator } from "../images"; -import { endpointMessagesToAnthropicMessages, addToolResults } from "./utils"; -import { createDocumentProcessorOptionsValidator } from "../document"; -import type { - Tool, - ToolCall, - ToolInput, - ToolInputFile, - ToolInputFixed, - ToolInputOptional, -} from "$lib/types/Tool"; -import type Anthropic from "@anthropic-ai/sdk"; -import type { MessageParam } from "@anthropic-ai/sdk/resources/messages.mjs"; -import directlyAnswer from "$lib/server/tools/directlyAnswer"; - -export const endpointAnthropicParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("anthropic"), - baseURL: z.string().url().default("https://api.anthropic.com"), - apiKey: z.string().default(config.ANTHROPIC_API_KEY ?? "sk-"), - defaultHeaders: z.record(z.string()).optional(), - defaultQuery: z.record(z.string()).optional(), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: ["image/png", "image/jpeg", "image/webp"], - preferredMimeType: "image/webp", - // The 4 / 3 compensates for the 33% increase in size when converting to base64 - maxSizeInMB: (5 / 4) * 3, - maxWidth: 4096, - maxHeight: 4096, - }), - document: createDocumentProcessorOptionsValidator({ - supportedMimeTypes: ["application/pdf"], - maxSizeInMB: 32, - }), - }) - .default({}), -}); - -export async function endpointAnthropic( - input: z.input -): Promise { - const { baseURL, apiKey, model, defaultHeaders, defaultQuery, multimodal } = - endpointAnthropicParametersSchema.parse(input); - let Anthropic; - try { - Anthropic = (await import("@anthropic-ai/sdk")).default; - } catch (e) { - throw new Error("Failed to import @anthropic-ai/sdk", { cause: e }); - } - - const anthropic = new Anthropic({ - apiKey, - baseURL, - defaultHeaders, - defaultQuery, - }); - - return async ({ - messages, - preprompt, - generateSettings, - conversationId, - tools = [], - toolResults = [], - }) => { - let system = preprompt; - if (messages?.[0]?.from === "system") { - system = messages[0].content; - } - - let tokenId = 0; - if (tools.length === 0 && toolResults.length > 0) { - const toolNames = new Set(toolResults.map((tool) => tool.call.name)); - tools = Array.from(toolNames).map((name) => ({ - name, - description: "", - inputs: [], - })) as unknown as Tool[]; - } - - const parameters = { ...model.parameters, ...generateSettings }; - - return (async function* () { - const stream = anthropic.messages.stream({ - model: model.id ?? model.name, - tools: createAnthropicTools(tools), - tool_choice: - tools.length > 0 ? { type: "auto", disable_parallel_tool_use: false } : undefined, - messages: addToolResults( - await endpointMessagesToAnthropicMessages(messages, multimodal, conversationId), - toolResults - ) as MessageParam[], - max_tokens: parameters?.max_new_tokens, - temperature: parameters?.temperature, - top_p: parameters?.top_p, - top_k: parameters?.top_k, - stop_sequences: parameters?.stop, - system, - }); - while (true) { - const result = await Promise.race([stream.emitted("text"), stream.emitted("end")]); - - if (result === undefined) { - if ("tool_use" === stream.receivedMessages[0].stop_reason) { - // this should really create a new "Assistant" message with the tool id in it. - const toolCalls: ToolCall[] = stream.receivedMessages[0].content - .filter( - (block): block is Anthropic.Messages.ContentBlock & { type: "tool_use" } => - block.type === "tool_use" - ) - .map((block) => ({ - name: block.name, - parameters: block.input as Record, - id: block.id, - })); - - yield { - token: { id: tokenId, text: "", logprob: 0, special: false, toolCalls }, - generated_text: null, - details: null, - }; - } else { - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: await stream.finalText(), - details: null, - } satisfies TextGenerationStreamOutput; - } - - return; - } - // Text delta - yield { - token: { - id: tokenId++, - text: result as unknown as string, - special: false, - logprob: 0, - }, - generated_text: null, - details: null, - } satisfies TextGenerationStreamOutput; - } - })(); - }; -} - -function createAnthropicTools(tools: Tool[]): Anthropic.Messages.Tool[] { - return tools - .filter((tool) => tool.name !== directlyAnswer.name) - .map((tool) => { - const properties = tool.inputs.reduce( - (acc, input) => { - acc[input.name] = convertToolInputToJSONSchema(input); - return acc; - }, - {} as Record - ); - - const required = tool.inputs - .filter((input) => input.paramType === "required") - .map((input) => input.name); - - return { - name: tool.name, - description: tool.description, - input_schema: { - type: "object", - properties, - required: required.length > 0 ? required : undefined, - }, - }; - }); -} - -function convertToolInputToJSONSchema(input: ToolInput): Record { - const baseSchema: Record = {}; - if ("description" in input) { - baseSchema["description"] = input.description || ""; - } - switch (input.paramType) { - case "optional": - baseSchema["default"] = (input as ToolInputOptional).default; - break; - case "fixed": - baseSchema["const"] = (input as ToolInputFixed).value; - break; - } - - if (input.type === "file") { - baseSchema["type"] = "string"; - baseSchema["format"] = "binary"; - baseSchema["mimeTypes"] = (input as ToolInputFile).mimeTypes; - } else { - switch (input.type) { - case "str": - baseSchema["type"] = "string"; - break; - case "int": - baseSchema["type"] = "integer"; - break; - case "float": - baseSchema["type"] = "number"; - break; - case "bool": - baseSchema["type"] = "boolean"; - break; - } - } - - return baseSchema; -} diff --git a/src/lib/server/endpoints/anthropic/endpointAnthropicVertex.ts b/src/lib/server/endpoints/anthropic/endpointAnthropicVertex.ts deleted file mode 100644 index 06ceae7463cc861e163983b9f8551b9f9495f688..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/anthropic/endpointAnthropicVertex.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import { createImageProcessorOptionsValidator } from "../images"; -import { endpointMessagesToAnthropicMessages } from "./utils"; -import type { MessageParam } from "@anthropic-ai/sdk/resources/messages.mjs"; - -export const endpointAnthropicVertexParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("anthropic-vertex"), - region: z.string().default("us-central1"), - projectId: z.string(), - defaultHeaders: z.record(z.string()).optional(), - defaultQuery: z.record(z.string()).optional(), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: ["image/png", "image/jpeg", "image/webp"], - preferredMimeType: "image/webp", - // The 4 / 3 compensates for the 33% increase in size when converting to base64 - maxSizeInMB: (5 / 4) * 3, - maxWidth: 4096, - maxHeight: 4096, - }), - }) - .default({}), -}); - -export async function endpointAnthropicVertex( - input: z.input -): Promise { - const { region, projectId, model, defaultHeaders, defaultQuery, multimodal } = - endpointAnthropicVertexParametersSchema.parse(input); - let AnthropicVertex; - try { - AnthropicVertex = (await import("@anthropic-ai/vertex-sdk")).AnthropicVertex; - } catch (e) { - throw new Error("Failed to import @anthropic-ai/vertex-sdk", { cause: e }); - } - - const anthropic = new AnthropicVertex({ - baseURL: `https://${region}-aiplatform.googleapis.com/v1`, - region, - projectId, - defaultHeaders, - defaultQuery, - }); - - return async ({ messages, preprompt }) => { - let system = preprompt; - if (messages?.[0]?.from === "system") { - system = messages[0].content; - } - - let tokenId = 0; - return (async function* () { - const stream = anthropic.messages.stream({ - model: model.id ?? model.name, - messages: (await endpointMessagesToAnthropicMessages( - messages, - multimodal - )) as MessageParam[], - max_tokens: model.parameters?.max_new_tokens, - temperature: model.parameters?.temperature, - top_p: model.parameters?.top_p, - top_k: model.parameters?.top_k, - stop_sequences: model.parameters?.stop, - system, - }); - while (true) { - const result = await Promise.race([stream.emitted("text"), stream.emitted("end")]); - - // Stream end - if (result === undefined) { - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: await stream.finalText(), - details: null, - } satisfies TextGenerationStreamOutput; - return; - } - - // Text delta - yield { - token: { - id: tokenId++, - text: result as unknown as string, - special: false, - logprob: 0, - }, - generated_text: null, - details: null, - } satisfies TextGenerationStreamOutput; - } - })(); - }; -} diff --git a/src/lib/server/endpoints/anthropic/utils.ts b/src/lib/server/endpoints/anthropic/utils.ts deleted file mode 100644 index e490a81ba57971dcad3d753a52d9b1b2c8f79d54..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/anthropic/utils.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { makeImageProcessor, type ImageProcessorOptions } from "../images"; -import { makeDocumentProcessor, type FileProcessorOptions } from "../document"; -import type { EndpointMessage } from "../endpoints"; -import type { MessageFile } from "$lib/types/Message"; -import type { - BetaImageBlockParam, - BetaMessageParam, - BetaBase64PDFBlock, -} from "@anthropic-ai/sdk/resources/beta/messages/messages.mjs"; -import type { ToolResult } from "$lib/types/Tool"; -import { downloadFile } from "$lib/server/files/downloadFile"; -import type { ObjectId } from "mongodb"; - -export async function fileToImageBlock( - file: MessageFile, - opts: ImageProcessorOptions<"image/png" | "image/jpeg" | "image/webp"> -): Promise { - const processor = makeImageProcessor(opts); - - const { image, mime } = await processor(file); - - return { - type: "image", - source: { - type: "base64", - media_type: mime, - data: image.toString("base64"), - }, - }; -} - -export async function fileToDocumentBlock( - file: MessageFile, - opts: FileProcessorOptions<"application/pdf"> -): Promise { - const processor = makeDocumentProcessor(opts); - const { file: document, mime } = await processor(file); - - return { - type: "document", - source: { - type: "base64", - media_type: mime, - data: document.toString("base64"), - }, - }; -} - -type NonSystemMessage = EndpointMessage & { from: "user" | "assistant" }; -export async function endpointMessagesToAnthropicMessages( - messages: EndpointMessage[], - multimodal: { - image: ImageProcessorOptions<"image/png" | "image/jpeg" | "image/webp">; - document?: FileProcessorOptions<"application/pdf">; - }, - conversationId?: ObjectId | undefined -): Promise { - return await Promise.all( - messages - .filter((message): message is NonSystemMessage => message.from !== "system") - .map>(async (message) => { - return { - role: message.from, - content: [ - ...(message.from === "user" - ? await Promise.all( - (message.files ?? []).map(async (file) => { - if (file.type === "hash" && conversationId) { - file = await downloadFile(file.value, conversationId); - } - - if (file.mime.startsWith("image/")) { - return fileToImageBlock(file, multimodal.image); - } else if (file.mime === "application/pdf" && multimodal.document) { - return fileToDocumentBlock(file, multimodal.document); - } else { - throw new Error(`Unsupported file type: ${file.mime}`); - } - }) - ) - : []), - { type: "text", text: message.content }, - ], - }; - }) - ); -} - -export function addToolResults( - messages: BetaMessageParam[], - toolResults: ToolResult[] -): BetaMessageParam[] { - const id = crypto.randomUUID(); - if (toolResults.length === 0) { - return messages; - } - return [ - ...messages, - { - role: "assistant", - content: toolResults.map((result, index) => ({ - type: "tool_use", - id: `tool_${index}_${id}`, - name: result.call.name, - input: result.call.parameters, - })), - }, - { - role: "user", - content: toolResults.map((result, index) => ({ - type: "tool_result", - tool_use_id: `tool_${index}_${id}`, - is_error: result.status === "error", - content: JSON.stringify( - result.status === "error" ? result.message : "outputs" in result ? result.outputs : "" - ), - })), - }, - ]; -} diff --git a/src/lib/server/endpoints/aws/endpointAws.ts b/src/lib/server/endpoints/aws/endpointAws.ts deleted file mode 100644 index 02ecf4d7388590008db99aedf109d7f20bb92133..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/aws/endpointAws.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { buildPrompt } from "$lib/buildPrompt"; -import { textGenerationStream } from "@huggingface/inference"; -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; - -export const endpointAwsParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("aws"), - url: z.string().url(), - accessKey: z - .string({ - description: - "An AWS Access Key ID. If not provided, the default AWS identity resolution will be used", - }) - .min(1) - .optional(), - secretKey: z - .string({ - description: - "An AWS Access Key Secret. If not provided, the default AWS identity resolution will be used", - }) - .min(1) - .optional(), - sessionToken: z.string().optional(), - service: z.union([z.literal("sagemaker"), z.literal("lambda")]).default("sagemaker"), - region: z.string().optional(), -}); - -export async function endpointAws( - input: z.input -): Promise { - let createSignedFetcher; - try { - createSignedFetcher = (await import("aws-sigv4-fetch")).createSignedFetcher; - } catch (e) { - throw new Error("Failed to import aws-sigv4-fetch"); - } - - const { url, accessKey, secretKey, sessionToken, model, region, service } = - endpointAwsParametersSchema.parse(input); - - const signedFetch = createSignedFetcher({ - service, - region, - credentials: - accessKey && secretKey - ? { accessKeyId: accessKey, secretAccessKey: secretKey, sessionToken } - : undefined, - }); - - return async ({ messages, preprompt, continueMessage, generateSettings }) => { - const prompt = await buildPrompt({ - messages, - continueMessage, - preprompt, - model, - }); - - return textGenerationStream( - { - parameters: { ...model.parameters, ...generateSettings, return_full_text: false }, - model: url, - inputs: prompt, - }, - { - fetch: signedFetch, - } - ); - }; -} - -export default endpointAws; diff --git a/src/lib/server/endpoints/aws/endpointBedrock.ts b/src/lib/server/endpoints/aws/endpointBedrock.ts deleted file mode 100644 index e6d848abf45bfb6d57e49b9cc284e0da91360ff9..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/aws/endpointBedrock.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images"; -import type { EndpointMessage } from "../endpoints"; -import type { MessageFile } from "$lib/types/Message"; - -export const endpointBedrockParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - type: z.literal("bedrock"), - region: z.string().default("us-east-1"), - model: z.any(), - anthropicVersion: z.string().default("bedrock-2023-05-31"), - isNova: z.boolean().default(false), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: [ - "image/png", - "image/jpeg", - "image/webp", - "image/avif", - "image/tiff", - "image/gif", - ], - preferredMimeType: "image/webp", - maxSizeInMB: Infinity, - maxWidth: 4096, - maxHeight: 4096, - }), - }) - .default({}), -}); - -export async function endpointBedrock( - input: z.input -): Promise { - const { region, model, anthropicVersion, multimodal, isNova } = - endpointBedrockParametersSchema.parse(input); - - let BedrockRuntimeClient, InvokeModelWithResponseStreamCommand; - try { - ({ BedrockRuntimeClient, InvokeModelWithResponseStreamCommand } = await import( - "@aws-sdk/client-bedrock-runtime" - )); - } catch (error) { - throw new Error("Failed to import @aws-sdk/client-bedrock-runtime. Make sure it's installed."); - } - - const client = new BedrockRuntimeClient({ - region, - }); - const imageProcessor = makeImageProcessor(multimodal.image); - - return async ({ messages, preprompt, generateSettings }) => { - let system = preprompt; - // Use the first message as the system prompt if it's of type "system" - if (messages?.[0]?.from === "system") { - system = messages[0].content; - messages = messages.slice(1); // Remove the first system message from the array - } - - const formattedMessages = await prepareMessages(messages, isNova, imageProcessor); - - let tokenId = 0; - const parameters = { ...model.parameters, ...generateSettings }; - return (async function* () { - const baseCommandParams = { - contentType: "application/json", - accept: "application/json", - modelId: model.id, - }; - - const maxTokens = parameters.max_new_tokens || 4096; - - let bodyContent; - if (isNova) { - bodyContent = { - messages: formattedMessages, - inferenceConfig: { - maxTokens, - topP: 0.1, - temperature: 1.0, - }, - system: [{ text: system }], - }; - } else { - bodyContent = { - anthropic_version: anthropicVersion, - max_tokens: maxTokens, - messages: formattedMessages, - system, - }; - } - - const command = new InvokeModelWithResponseStreamCommand({ - ...baseCommandParams, - body: Buffer.from(JSON.stringify(bodyContent), "utf-8"), - trace: "DISABLED", - }); - - const response = await client.send(command); - - let text = ""; - - for await (const item of response.body ?? []) { - const chunk = JSON.parse(new TextDecoder().decode(item.chunk?.bytes)); - if ("contentBlockDelta" in chunk || chunk.type === "content_block_delta") { - const chunkText = chunk.contentBlockDelta?.delta?.text || chunk.delta?.text || ""; - text += chunkText; - yield { - token: { - id: tokenId++, - text: chunkText, - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - } satisfies TextGenerationStreamOutput; - } else if ("messageStop" in chunk || chunk.type === "message_stop") { - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: text, - details: null, - } satisfies TextGenerationStreamOutput; - } - } - })(); - }; -} - -// Prepare the messages excluding system prompts -async function prepareMessages( - messages: EndpointMessage[], - isNova: boolean, - imageProcessor: ReturnType -) { - const formattedMessages = []; - - for (const message of messages) { - const content = []; - - if (message.files?.length) { - content.push(...(await prepareFiles(imageProcessor, isNova, message.files))); - } - if (isNova) { - content.push({ text: message.content }); - } else { - content.push({ type: "text", text: message.content }); - } - - const lastMessage = formattedMessages[formattedMessages.length - 1]; - if (lastMessage && lastMessage.role === message.from) { - // If the last message has the same role, merge the content - lastMessage.content.push(...content); - } else { - formattedMessages.push({ role: message.from, content }); - } - } - return formattedMessages; -} - -// Process files and convert them to base64 encoded strings -async function prepareFiles( - imageProcessor: ReturnType, - isNova: boolean, - files: MessageFile[] -) { - const processedFiles = await Promise.all(files.map(imageProcessor)); - - if (isNova) { - return processedFiles.map((file) => ({ - image: { - format: file.mime.substring("image/".length), - source: { bytes: file.image.toString("base64") }, - }, - })); - } else { - return processedFiles.map((file) => ({ - type: "image", - source: { type: "base64", media_type: file.mime, data: file.image.toString("base64") }, - })); - } -} diff --git a/src/lib/server/endpoints/cloudflare/endpointCloudflare.ts b/src/lib/server/endpoints/cloudflare/endpointCloudflare.ts deleted file mode 100644 index 933c78ffab54691f93ab87d93481922735a3a450..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/cloudflare/endpointCloudflare.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import { config } from "$lib/server/config"; -import { logger } from "$lib/server/logger"; - -export const endpointCloudflareParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("cloudflare"), - accountId: z.string().default(config.CLOUDFLARE_ACCOUNT_ID), - apiToken: z.string().default(config.CLOUDFLARE_API_TOKEN), -}); - -export async function endpointCloudflare( - input: z.input -): Promise { - const { accountId, apiToken, model } = endpointCloudflareParametersSchema.parse(input); - - if (!model.id.startsWith("@")) { - model.id = "@hf/" + model.id; - } - - const apiURL = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/run/${model.id}`; - - return async ({ messages, preprompt, generateSettings }) => { - let messagesFormatted = messages.map((message) => ({ - role: message.from, - content: message.content, - })); - - if (messagesFormatted?.[0]?.role !== "system") { - messagesFormatted = [{ role: "system", content: preprompt ?? "" }, ...messagesFormatted]; - } - - const parameters = { ...model.parameters, ...generateSettings }; - - const payload = JSON.stringify({ - messages: messagesFormatted, - stream: true, - max_tokens: parameters?.max_new_tokens, - temperature: parameters?.temperature, - top_p: parameters?.top_p, - top_k: parameters?.top_k, - repetition_penalty: parameters?.repetition_penalty, - }); - - const res = await fetch(apiURL, { - method: "POST", - headers: { - Authorization: `Bearer ${apiToken}`, - "Content-Type": "application/json", - }, - body: payload, - }); - - if (!res.ok) { - throw new Error(`Failed to generate text: ${await res.text()}`); - } - - const encoder = new TextDecoderStream(); - const reader = res.body?.pipeThrough(encoder).getReader(); - - return (async function* () { - let stop = false; - let generatedText = ""; - let tokenId = 0; - let accumulatedData = ""; // Buffer to accumulate data chunks - - while (!stop) { - const out = await reader?.read(); - - // If it's done, we cancel - if (out?.done) { - reader?.cancel(); - return; - } - - if (!out?.value) { - return; - } - - // Accumulate the data chunk - accumulatedData += out.value; - - // Process each complete JSON object in the accumulated data - while (accumulatedData.includes("\n")) { - // Assuming each JSON object ends with a newline - const endIndex = accumulatedData.indexOf("\n"); - let jsonString = accumulatedData.substring(0, endIndex).trim(); - - // Remove the processed part from the buffer - accumulatedData = accumulatedData.substring(endIndex + 1); - - if (jsonString.startsWith("data: ")) { - jsonString = jsonString.slice(6); - let data = null; - - if (jsonString === "[DONE]") { - stop = true; - - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: generatedText, - details: null, - } satisfies TextGenerationStreamOutput; - reader?.cancel(); - - continue; - } - - try { - data = JSON.parse(jsonString); - } catch (e) { - logger.error(e, "Failed to parse JSON"); - logger.error(jsonString, "Problematic JSON string:"); - continue; // Skip this iteration and try the next chunk - } - - // Handle the parsed data - if (data.response) { - generatedText += data.response ?? ""; - const output: TextGenerationStreamOutput = { - token: { - id: tokenId++, - text: data.response ?? "", - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - }; - yield output; - } - } - } - } - })(); - }; -} - -export default endpointCloudflare; diff --git a/src/lib/server/endpoints/cohere/endpointCohere.ts b/src/lib/server/endpoints/cohere/endpointCohere.ts deleted file mode 100644 index 92fcdc7ce5bc061e5e65c0f0bb258149fbbe260e..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/cohere/endpointCohere.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { z } from "zod"; -import { config } from "$lib/server/config"; -import type { Endpoint } from "../endpoints"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import type { Cohere, CohereClient } from "cohere-ai"; -import { buildPrompt } from "$lib/buildPrompt"; -import { ToolResultStatus, type ToolCall } from "$lib/types/Tool"; -import { pipeline, Writable, type Readable } from "node:stream"; -import { toolHasName } from "$lib/utils/tools"; - -export const endpointCohereParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("cohere"), - apiKey: z.string().default(config.COHERE_API_TOKEN), - clientName: z.string().optional(), - raw: z.boolean().default(false), - forceSingleStep: z.boolean().default(true), -}); - -export async function endpointCohere( - input: z.input -): Promise { - const { apiKey, clientName, model, raw, forceSingleStep } = - endpointCohereParametersSchema.parse(input); - - let cohere: CohereClient; - - try { - cohere = new (await import("cohere-ai")).CohereClient({ - token: apiKey, - clientName, - }); - } catch (e) { - throw new Error("Failed to import cohere-ai", { cause: e }); - } - - return async ({ messages, preprompt, generateSettings, continueMessage, tools, toolResults }) => { - let system = preprompt; - if (messages?.[0]?.from === "system") { - system = messages[0].content; - } - - // Tools must use [A-z_] for their names and directly_answer is banned - // It's safe to convert the tool names because we treat - and _ the same - tools = tools - ?.filter((tool) => !toolHasName("directly_answer", tool)) - .map((tool) => ({ ...tool, name: tool.name.replaceAll("-", "_") })); - - const parameters = { ...model.parameters, ...generateSettings }; - - return (async function* () { - let stream; - let tokenId = 0; - - if (raw) { - const prompt = await buildPrompt({ - messages, - model, - preprompt: system, - continueMessage, - tools, - toolResults, - }); - - stream = await cohere.chatStream({ - forceSingleStep, - message: prompt, - rawPrompting: true, - model: model.id ?? model.name, - p: parameters?.top_p, - k: parameters?.top_k, - maxTokens: parameters?.max_new_tokens, - temperature: parameters?.temperature, - stopSequences: parameters?.stop, - frequencyPenalty: parameters?.frequency_penalty, - }); - } else { - const formattedMessages = messages - .filter((message) => message.from !== "system") - .map((message) => ({ - role: message.from === "user" ? "USER" : "CHATBOT", - message: message.content, - })) satisfies Cohere.Message[]; - - stream = await cohere - .chatStream({ - forceSingleStep, - model: model.id ?? model.name, - chatHistory: formattedMessages.slice(0, -1), - message: formattedMessages[formattedMessages.length - 1].message, - preamble: system, - p: parameters?.top_p, - k: parameters?.top_k, - maxTokens: parameters?.max_new_tokens, - temperature: parameters?.temperature, - stopSequences: parameters?.stop, - frequencyPenalty: parameters?.frequency_penalty, - tools, - toolResults: - toolResults?.length && toolResults?.length > 0 - ? toolResults?.map((toolResult) => { - if (toolResult.status === ToolResultStatus.Error) { - return { call: toolResult.call, outputs: [{ error: toolResult.message }] }; - } - return { call: toolResult.call, outputs: toolResult.outputs }; - }) - : undefined, - }) - .catch(async (err) => { - if (!err.body) throw err; - - // Decode the error message and throw - const message = await convertStreamToBuffer(err.body).catch(() => { - throw err; - }); - throw Error(message, { cause: err }); - }); - } - - for await (const output of stream) { - if (output.eventType === "text-generation") { - yield { - token: { - id: tokenId++, - text: output.text, - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - } satisfies TextGenerationStreamOutput; - } else if (output.eventType === "tool-calls-generation") { - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - toolCalls: output.toolCalls as ToolCall[], - }, - generated_text: null, - details: null, - }; - } else if (output.eventType === "stream-end") { - if (["ERROR", "ERROR_TOXIC", "ERROR_LIMIT"].includes(output.finishReason)) { - throw new Error(output.finishReason); - } - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: output.response.text, - details: null, - }; - } - } - })(); - }; -} - -async function convertStreamToBuffer(webReadableStream: Readable) { - return new Promise((resolve, reject) => { - const chunks: Buffer[] = []; - - pipeline( - webReadableStream, - new Writable({ - write(chunk, _, callback) { - chunks.push(chunk); - callback(); - }, - }), - (err) => { - if (err) { - reject(err); - } else { - resolve(Buffer.concat(chunks).toString("utf-8")); - } - } - ); - }); -} diff --git a/src/lib/server/endpoints/document.ts b/src/lib/server/endpoints/document.ts index 70df7c09279b4db96433e6be594f4f22ca2ab5d9..7d16d162e346306da66137f24d2a08ac4295e876 100644 --- a/src/lib/server/endpoints/document.ts +++ b/src/lib/server/endpoints/document.ts @@ -6,10 +6,7 @@ export interface FileProcessorOptions { maxSizeInMB: number; } -export type ImageProcessor = (file: MessageFile) => Promise<{ - file: Buffer; - mime: TMimeType; -}>; +// Removed unused ImageProcessor type alias export const createDocumentProcessorOptionsValidator = ( defaults: FileProcessorOptions @@ -29,10 +26,7 @@ export const createDocumentProcessorOptionsValidator = = (file: MessageFile) => { - file: Buffer; - mime: TMimeType; -}; +// Removed unused DocumentProcessor type alias export type AsyncDocumentProcessor = ( file: MessageFile diff --git a/src/lib/server/endpoints/endpoints.ts b/src/lib/server/endpoints/endpoints.ts index 0cc6039fe2b3a00097ca9b47f2a62ff4d68a5c38..e3188f56ad31bf5be29c78404b6e03245f815ee0 100644 --- a/src/lib/server/endpoints/endpoints.ts +++ b/src/lib/server/endpoints/endpoints.ts @@ -1,40 +1,10 @@ import type { Conversation } from "$lib/types/Conversation"; import type { Message } from "$lib/types/Message"; import type { TextGenerationStreamOutput, TextGenerationStreamToken } from "@huggingface/inference"; -import { endpointTgi, endpointTgiParametersSchema } from "./tgi/endpointTgi"; import { z } from "zod"; -import endpointAws, { endpointAwsParametersSchema } from "./aws/endpointAws"; import { endpointOAIParametersSchema, endpointOai } from "./openai/endpointOai"; -import endpointLlamacpp, { endpointLlamacppParametersSchema } from "./llamacpp/endpointLlamacpp"; -import endpointOllama, { endpointOllamaParametersSchema } from "./ollama/endpointOllama"; -import endpointVertex, { endpointVertexParametersSchema } from "./google/endpointVertex"; -import endpointGenAI, { endpointGenAIParametersSchema } from "./google/endpointGenAI"; -import { endpointBedrock, endpointBedrockParametersSchema } from "./aws/endpointBedrock"; - -import { - endpointAnthropic, - endpointAnthropicParametersSchema, -} from "./anthropic/endpointAnthropic"; -import { - endpointAnthropicVertex, - endpointAnthropicVertexParametersSchema, -} from "./anthropic/endpointAnthropicVertex"; import type { Model } from "$lib/types/Model"; -import endpointCloudflare, { - endpointCloudflareParametersSchema, -} from "./cloudflare/endpointCloudflare"; -import { endpointCohere, endpointCohereParametersSchema } from "./cohere/endpointCohere"; -import endpointLangserve, { - endpointLangserveParametersSchema, -} from "./langserve/endpointLangserve"; - -import type { Tool, ToolCall, ToolResult } from "$lib/types/Tool"; import type { ObjectId } from "mongodb"; -import { endpointLocal, endpointLocalParametersSchema } from "./local/endpointLocal"; -import { - endpointInferenceClient, - endpointInferenceClientParametersSchema, -} from "./inference-client/endpointInferenceClient"; export type EndpointMessage = Omit; @@ -44,61 +14,23 @@ export interface EndpointParameters { preprompt?: Conversation["preprompt"]; continueMessage?: boolean; // used to signal that the last message will be extended generateSettings?: Partial; - tools?: Tool[]; - toolResults?: ToolResult[]; isMultimodal?: boolean; conversationId?: ObjectId; } -interface CommonEndpoint { - weight: number; -} -export type TextGenerationStreamOutputWithToolsAndWebSources = TextGenerationStreamOutput & { - token: TextGenerationStreamToken & { toolCalls?: ToolCall[] }; - webSources?: { uri: string; title: string }[]; +export type TextGenerationStreamOutputSimplified = TextGenerationStreamOutput & { + token: TextGenerationStreamToken; + routerMetadata?: { route?: string; model?: string }; }; // type signature for the endpoint export type Endpoint = ( params: EndpointParameters -) => Promise>; - -// generator function that takes in parameters for defining the endpoint and return the endpoint -export type EndpointGenerator = (parameters: T) => Endpoint; +) => Promise>; // list of all endpoint generators export const endpoints = { - tgi: endpointTgi, - anthropic: endpointAnthropic, - anthropicvertex: endpointAnthropicVertex, - bedrock: endpointBedrock, - aws: endpointAws, openai: endpointOai, - llamacpp: endpointLlamacpp, - ollama: endpointOllama, - vertex: endpointVertex, - genai: endpointGenAI, - cloudflare: endpointCloudflare, - cohere: endpointCohere, - langserve: endpointLangserve, - local: endpointLocal, - inferenceClient: endpointInferenceClient, }; -export const endpointSchema = z.discriminatedUnion("type", [ - endpointAnthropicParametersSchema, - endpointAnthropicVertexParametersSchema, - endpointAwsParametersSchema, - endpointBedrockParametersSchema, - endpointOAIParametersSchema, - endpointTgiParametersSchema, - endpointLlamacppParametersSchema, - endpointOllamaParametersSchema, - endpointVertexParametersSchema, - endpointGenAIParametersSchema, - endpointCloudflareParametersSchema, - endpointCohereParametersSchema, - endpointLangserveParametersSchema, - endpointLocalParametersSchema, - endpointInferenceClientParametersSchema, -]); +export const endpointSchema = z.discriminatedUnion("type", [endpointOAIParametersSchema]); export default endpoints; diff --git a/src/lib/server/endpoints/google/endpointGenAI.ts b/src/lib/server/endpoints/google/endpointGenAI.ts deleted file mode 100644 index 032fc5969b9508eedf50b86bda49017a16f887aa..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/google/endpointGenAI.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { GoogleGenerativeAI, HarmBlockThreshold, HarmCategory } from "@google/generative-ai"; -import type { Content, Part, SafetySetting, TextPart } from "@google/generative-ai"; -import { z } from "zod"; -import type { Message, MessageFile } from "$lib/types/Message"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import type { Endpoint } from "../endpoints"; -import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images"; -import type { ImageProcessorOptions } from "../images"; -import { config } from "$lib/server/config"; - -export const endpointGenAIParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("genai"), - apiKey: z.string().default(config.GOOGLE_GENAI_API_KEY), - safetyThreshold: z - .enum([ - HarmBlockThreshold.HARM_BLOCK_THRESHOLD_UNSPECIFIED, - HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, - HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, - HarmBlockThreshold.BLOCK_NONE, - HarmBlockThreshold.BLOCK_ONLY_HIGH, - ]) - .optional(), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: ["image/png", "image/jpeg", "image/webp"], - preferredMimeType: "image/webp", - // The 4 / 3 compensates for the 33% increase in size when converting to base64 - maxSizeInMB: (5 / 4) * 3, - maxWidth: 4096, - maxHeight: 4096, - }), - }) - .default({}), -}); - -export function endpointGenAI(input: z.input): Endpoint { - const { model, apiKey, safetyThreshold, multimodal } = endpointGenAIParametersSchema.parse(input); - - const genAI = new GoogleGenerativeAI(apiKey); - - const safetySettings = safetyThreshold - ? Object.keys(HarmCategory) - .filter((cat) => cat !== HarmCategory.HARM_CATEGORY_UNSPECIFIED) - .reduce((acc, val) => { - acc.push({ - category: val as HarmCategory, - threshold: safetyThreshold, - }); - return acc; - }, [] as SafetySetting[]) - : undefined; - - return async ({ messages, preprompt, generateSettings }) => { - const parameters = { ...model.parameters, ...generateSettings }; - - const generativeModel = genAI.getGenerativeModel({ - model: model.id ?? model.name, - safetySettings, - generationConfig: { - maxOutputTokens: parameters?.max_new_tokens ?? 4096, - stopSequences: parameters?.stop, - temperature: parameters?.temperature ?? 1, - }, - }); - - let systemMessage = preprompt; - if (messages[0].from === "system") { - systemMessage = messages[0].content; - messages.shift(); - } - - const genAIMessages = await Promise.all( - messages.map(async ({ from, content, files }: Omit): Promise => { - return { - role: from === "user" ? "user" : "model", - parts: [ - ...(await Promise.all( - (files ?? []).map((file) => fileToImageBlock(file, multimodal.image)) - )), - { text: content }, - ], - }; - }) - ); - - const result = await generativeModel.generateContentStream({ - contents: genAIMessages, - systemInstruction: - systemMessage && systemMessage.trim() !== "" - ? { - role: "system", - parts: [{ text: systemMessage }], - } - : undefined, - }); - - let tokenId = 0; - return (async function* () { - let generatedText = ""; - - for await (const data of result.stream) { - if (!data?.candidates?.length) break; // Handle case where no candidates are present - - const candidate = data.candidates[0]; - if (!candidate.content?.parts?.length) continue; // Skip if no parts are present - - const firstPart = candidate.content.parts.find((part) => "text" in part) as - | TextPart - | undefined; - if (!firstPart) continue; // Skip if no text part is found - - const content = firstPart.text; - generatedText += content; - - const output: TextGenerationStreamOutput = { - token: { - id: tokenId++, - text: content, - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - }; - yield output; - } - - const output: TextGenerationStreamOutput = { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: generatedText, - details: null, - }; - yield output; - })(); - }; -} - -async function fileToImageBlock( - file: MessageFile, - opts: ImageProcessorOptions<"image/png" | "image/jpeg" | "image/webp"> -): Promise { - const processor = makeImageProcessor(opts); - const { image, mime } = await processor(file); - - return { - inlineData: { - mimeType: mime, - data: image.toString("base64"), - }, - }; -} - -export default endpointGenAI; diff --git a/src/lib/server/endpoints/google/endpointVertex.ts b/src/lib/server/endpoints/google/endpointVertex.ts deleted file mode 100644 index 882e61654b2c0b67b55d9251fdcfd22dee8ae7fb..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/google/endpointVertex.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { - VertexAI, - HarmCategory, - HarmBlockThreshold, - type Content, - type TextPart, -} from "@google-cloud/vertexai"; -import type { Endpoint, TextGenerationStreamOutputWithToolsAndWebSources } from "../endpoints"; -import { z } from "zod"; -import type { Message } from "$lib/types/Message"; -import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images"; -import { createDocumentProcessorOptionsValidator, makeDocumentProcessor } from "../document"; - -export const endpointVertexParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), // allow optional and validate against emptiness - type: z.literal("vertex"), - location: z.string().default("europe-west1"), - extraBody: z.object({ model_version: z.string() }).optional(), - project: z.string(), - apiEndpoint: z.string().optional(), - safetyThreshold: z - .enum([ - HarmBlockThreshold.HARM_BLOCK_THRESHOLD_UNSPECIFIED, - HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, - HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, - HarmBlockThreshold.BLOCK_NONE, - HarmBlockThreshold.BLOCK_ONLY_HIGH, - ]) - .optional(), - tools: z.array(z.any()).optional(), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: [ - "image/png", - "image/jpeg", - "image/webp", - "image/avif", - "image/tiff", - "image/gif", - ], - preferredMimeType: "image/webp", - maxSizeInMB: 20, - maxWidth: 4096, - maxHeight: 4096, - }), - document: createDocumentProcessorOptionsValidator({ - supportedMimeTypes: ["application/pdf", "text/plain"], - maxSizeInMB: 20, - }), - }) - .default({}), -}); - -export function endpointVertex(input: z.input): Endpoint { - const { project, location, model, apiEndpoint, safetyThreshold, tools, multimodal, extraBody } = - endpointVertexParametersSchema.parse(input); - - const vertex_ai = new VertexAI({ - project, - location, - apiEndpoint, - }); - - return async ({ messages, preprompt, generateSettings }) => { - const parameters = { ...model.parameters, ...generateSettings }; - - const hasFiles = messages.some((message) => message.files && message.files.length > 0); - - const generativeModel = vertex_ai.getGenerativeModel({ - model: extraBody?.model_version ?? model.id ?? model.name, - safetySettings: safetyThreshold - ? [ - { - category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, - threshold: safetyThreshold, - }, - { - category: HarmCategory.HARM_CATEGORY_HARASSMENT, - threshold: safetyThreshold, - }, - { - category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, - threshold: safetyThreshold, - }, - { - category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, - threshold: safetyThreshold, - }, - { - category: HarmCategory.HARM_CATEGORY_UNSPECIFIED, - threshold: safetyThreshold, - }, - ] - : undefined, - generationConfig: { - maxOutputTokens: parameters?.max_new_tokens ?? 4096, - stopSequences: parameters?.stop, - temperature: parameters?.temperature ?? 1, - }, - // tools and multimodal are mutually exclusive - tools: !hasFiles ? tools : undefined, - }); - - // Preprompt is the same as the first system message. - let systemMessage = preprompt; - if (messages[0].from === "system") { - systemMessage = messages[0].content; - messages.shift(); - } - - const vertexMessages = await Promise.all( - messages.map(async ({ from, content, files }: Omit): Promise => { - const imageProcessor = makeImageProcessor(multimodal.image); - const documentProcessor = makeDocumentProcessor(multimodal.document); - - const processedFilesWithNull = - files && files.length > 0 - ? await Promise.all( - files.map(async (file) => { - if (file.mime.includes("image")) { - const { image, mime } = await imageProcessor(file); - - return { file: image, mime }; - } else if (file.mime === "application/pdf" || file.mime === "text/plain") { - return documentProcessor(file); - } - - return null; - }) - ) - : []; - - const processedFiles = processedFilesWithNull.filter((file) => file !== null); - - return { - role: from === "user" ? "user" : "model", - parts: [ - ...processedFiles.map((processedFile) => ({ - inlineData: { - data: processedFile.file.toString("base64"), - mimeType: processedFile.mime, - }, - })), - { - text: content, - }, - ], - }; - }) - ); - - const result = await generativeModel.generateContentStream({ - contents: vertexMessages, - systemInstruction: systemMessage - ? { - role: "system", - parts: [ - { - text: systemMessage, - }, - ], - } - : undefined, - }); - - let tokenId = 0; - return (async function* () { - let generatedText = ""; - - const webSources = []; - - for await (const data of result.stream) { - if (!data?.candidates?.length) break; // Handle case where no candidates are present - - const candidate = data.candidates[0]; - if (!candidate.content?.parts?.length) continue; // Skip if no parts are present - - const firstPart = candidate.content.parts.find((part) => "text" in part) as - | TextPart - | undefined; - if (!firstPart) continue; // Skip if no text part is found - - const isLastChunk = !!candidate.finishReason; - - const candidateWebSources = candidate.groundingMetadata?.groundingChunks - ?.map((chunk) => { - const uri = chunk.web?.uri ?? chunk.retrievedContext?.uri; - const title = chunk.web?.title ?? chunk.retrievedContext?.title; - - if (!uri || !title) { - return null; - } - - return { - uri, - title, - }; - }) - .filter((source) => source !== null); - - if (candidateWebSources) { - webSources.push(...candidateWebSources); - } - - const content = firstPart.text; - generatedText += content; - const output: TextGenerationStreamOutputWithToolsAndWebSources = { - token: { - id: tokenId++, - text: content, - logprob: 0, - special: isLastChunk, - }, - generated_text: isLastChunk ? generatedText : null, - details: null, - webSources, - }; - yield output; - - if (isLastChunk) break; - } - })(); - }; -} -export default endpointVertex; diff --git a/src/lib/server/endpoints/inference-client/endpointInferenceClient.ts b/src/lib/server/endpoints/inference-client/endpointInferenceClient.ts deleted file mode 100644 index 5f48abac8a20ed89586408f746dc869b3883e8ce..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/inference-client/endpointInferenceClient.ts +++ /dev/null @@ -1,342 +0,0 @@ -import { z } from "zod"; -import type { Endpoint, TextGenerationStreamOutputWithToolsAndWebSources } from "../endpoints"; -import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images"; -import { INFERENCE_PROVIDERS, InferenceClient } from "@huggingface/inference"; -import { config } from "$lib/server/config"; -import type { Tool, ToolCall } from "$lib/types/Tool"; -import type { ChatCompletionStreamOutput } from "@huggingface/tasks"; -import type { FunctionDefinition } from "openai/resources/index.mjs"; -import type { ChatCompletionTool, FunctionParameters } from "openai/resources/index.mjs"; -import { logger } from "$lib/server/logger"; -import type { MessageFile } from "$lib/types/Message"; -import { v4 as uuidv4 } from "uuid"; -import type { Conversation } from "$lib/types/Conversation"; -import { downloadFile } from "$lib/server/files/downloadFile"; -import { jsonrepair } from "jsonrepair"; -type DeltaToolCall = NonNullable< - ChatCompletionStreamOutput["choices"][number]["delta"]["tool_calls"] ->[number]; - -function createChatCompletionToolsArray(tools: Tool[] | undefined): ChatCompletionTool[] { - const toolChoices = [] as ChatCompletionTool[]; - if (tools === undefined) { - return toolChoices; - } - - for (const t of tools) { - const requiredProperties = [] as string[]; - - const properties = {} as Record; - for (const idx in t.inputs) { - const parameterDefinition = t.inputs[idx]; - - const parameter = {} as Record; - switch (parameterDefinition.type) { - case "str": - parameter.type = "string"; - break; - case "float": - case "int": - parameter.type = "number"; - break; - case "bool": - parameter.type = "boolean"; - break; - case "file": - throw new Error("File type's currently not supported"); - default: - throw new Error(`Unknown tool IO type: ${t}`); - } - - if ("description" in parameterDefinition) { - parameter.description = parameterDefinition.description; - } - - if (parameterDefinition.paramType == "required") { - requiredProperties.push(t.inputs[idx].name); - } - - properties[t.inputs[idx].name] = parameter; - } - - const functionParameters: FunctionParameters = { - type: "object", - ...(requiredProperties.length > 0 ? { required: requiredProperties } : {}), - properties, - }; - - const functionDefinition: FunctionDefinition = { - name: t.name, - description: t.description, - parameters: functionParameters, - }; - - const toolDefinition: ChatCompletionTool = { - type: "function", - function: functionDefinition, - }; - - toolChoices.push(toolDefinition); - } - - return toolChoices; -} - -export const endpointInferenceClientParametersSchema = z.object({ - type: z.literal("inference-client"), - weight: z.number().int().positive().default(1), - model: z.any(), - provider: z.enum(INFERENCE_PROVIDERS).optional(), - modelName: z.string().optional(), - baseURL: z.string().optional(), - multimodal: z - .object({ - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: [ - "image/png", - "image/jpeg", - "image/webp", - "image/avif", - "image/tiff", - "image/gif", - ], - preferredMimeType: "image/webp", - maxSizeInMB: Infinity, - maxWidth: 4096, - maxHeight: 4096, - }), - }) - .default({}), - customHeaders: z.record(z.string(), z.string()).default({}), -}); - -export async function endpointInferenceClient( - input: z.input -): Promise { - const { model, provider, modelName, baseURL, multimodal, customHeaders } = - endpointInferenceClientParametersSchema.parse(input); - - if (!!provider && !!baseURL) { - throw new Error("provider and baseURL cannot both be provided"); - } - const client = baseURL - ? new InferenceClient(config.HF_TOKEN, { endpointUrl: baseURL }) - : new InferenceClient(config.HF_TOKEN); - - const imageProcessor = multimodal.image ? makeImageProcessor(multimodal.image) : undefined; - - async function prepareFiles(files: MessageFile[], conversationId?: Conversation["_id"]) { - if (!imageProcessor) { - return []; - } - const processedFiles = await Promise.all( - files - .filter((file) => file.mime.startsWith("image/")) - .map(async (file) => { - if (file.type === "hash" && conversationId) { - file = await downloadFile(file.value, conversationId); - } - return imageProcessor(file); - }) - ); - return processedFiles.map((file) => ({ - type: "image_url" as const, - image_url: { - url: `data:${file.mime};base64,${file.image.toString("base64")}`, - }, - })); - } - - return async ({ messages, generateSettings, tools, toolResults, preprompt, conversationId }) => { - /* eslint-disable @typescript-eslint/no-explicit-any */ - let messagesArray = (await Promise.all( - messages.map(async (message) => { - return { - role: message.from, - content: [ - ...(await prepareFiles(message.files ?? [], conversationId)), - { type: "text" as const, text: message.content }, - ], - }; - }) - )) as any[]; - - if ( - !model.systemRoleSupported && - messagesArray.length > 0 && - messagesArray[0]?.role === "system" - ) { - messagesArray[0].role = "user"; - } else if (messagesArray[0].role !== "system") { - messagesArray.unshift({ - role: "system", - content: preprompt ?? "", - }); - } - - if (toolResults && toolResults.length > 0) { - messagesArray = [ - ...messagesArray, - { - role: "assistant", - content: [ - { - type: "text" as const, - text: "", - }, - ], - tool_calls: toolResults.map((toolResult) => ({ - type: "function", - function: { - name: toolResult.call.name, - arguments: JSON.stringify(toolResult.call.parameters), - }, - id: toolResult?.call?.toolId || uuidv4(), - })), - }, - ...toolResults.map((toolResult) => ({ - role: model.systemRoleSupported ? "tool" : "user", - content: [ - { - type: "text" as const, - text: JSON.stringify(toolResult), - }, - ], - tool_call_id: toolResult?.call?.toolId || uuidv4(), - })), - ]; - } - - messagesArray = messagesArray.reduce((acc: typeof messagesArray, current) => { - if (acc.length === 0 || current.role !== acc[acc.length - 1].role) { - acc.push(current); - } else { - const prevMessage = acc[acc.length - 1]; - - prevMessage.content = [ - ...prevMessage.content.filter((item: any) => item.type !== "text"), - ...current.content.filter((item: any) => item.type !== "text"), - { - type: "text" as const, - text: [ - ...prevMessage.content.filter((item: any) => item.type === "text"), - ...current.content.filter((item: any) => item.type === "text"), - ] - .map((item: any) => item.text) - .join("\n") - .replace(/^\n/, ""), - }, - ]; - - prevMessage.files = [...(prevMessage?.files ?? []), ...(current?.files ?? [])]; - - prevMessage.tool_calls = [ - ...(prevMessage?.tool_calls ?? []), - ...(current?.tool_calls ?? []), - ]; - } - return acc; - }, []); - const toolCallChoices = createChatCompletionToolsArray(tools); - const stream = client.chatCompletionStream( - { - ...model.parameters, - ...generateSettings, - model: modelName ?? model.id ?? model.name, - provider: baseURL ? undefined : provider || ("hf-inference" as const), - messages: messagesArray, - ...(toolCallChoices.length > 0 ? { tools: toolCallChoices, tool_choice: "auto" } : {}), - toolResults, - }, - { - fetch: async (url, options) => { - return fetch(url, { - ...options, - headers: { - ...options?.headers, - "X-Use-Cache": "false", - "ChatUI-Conversation-ID": conversationId?.toString() ?? "", - ...customHeaders, - }, - }); - }, - } - ); - - let tokenId = 0; - let generated_text = ""; - const finalToolCalls: DeltaToolCall[] = []; - - async function* convertStream(): AsyncGenerator< - TextGenerationStreamOutputWithToolsAndWebSources, - void, - void - > { - for await (const chunk of stream) { - const token = chunk.choices?.[0]?.delta?.content || ""; - - generated_text += token; - - const toolCalls = chunk.choices?.[0]?.delta?.tool_calls ?? []; - - for (const toolCall of toolCalls) { - const index = toolCall.index ?? 0; - - if (!finalToolCalls[index]) { - finalToolCalls[index] = toolCall; - } else { - if (finalToolCalls[index].function.arguments === undefined) { - finalToolCalls[index].function.arguments = ""; - } - if (toolCall.function.arguments) { - finalToolCalls[index].function.arguments += toolCall.function.arguments; - } - } - } - - yield { - token: { - id: tokenId++, - text: token, - logprob: 0, - special: false, - }, - details: null, - generated_text: null, - }; - } - - let mappedToolCalls: ToolCall[] | undefined; - try { - if (finalToolCalls.length === 0) { - mappedToolCalls = undefined; - } else { - // Ensure finalToolCalls is an array - const toolCallsArray = Array.isArray(finalToolCalls) ? finalToolCalls : [finalToolCalls]; - - mappedToolCalls = toolCallsArray.map((tc) => ({ - id: tc.id, - name: tc.function.name ?? "", - parameters: JSON.parse(jsonrepair(tc.function.arguments || "{}")), - })); - } - } catch (e) { - logger.error(e, "error mapping tool calls"); - } - - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - toolCalls: mappedToolCalls, - }, - generated_text, - details: null, - }; - } - - return convertStream(); - }; -} diff --git a/src/lib/server/endpoints/langserve/endpointLangserve.ts b/src/lib/server/endpoints/langserve/endpointLangserve.ts deleted file mode 100644 index a6152cf64b7420fc3b74f64eea9ce257e37928bf..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/langserve/endpointLangserve.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { buildPrompt } from "$lib/buildPrompt"; -import { z } from "zod"; -import type { Endpoint } from "../endpoints"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import { logger } from "$lib/server/logger"; - -export const endpointLangserveParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("langserve"), - url: z.string().url(), -}); - -export function endpointLangserve( - input: z.input -): Endpoint { - const { url, model } = endpointLangserveParametersSchema.parse(input); - - return async ({ messages, preprompt, continueMessage }) => { - const prompt = await buildPrompt({ - messages, - continueMessage, - preprompt, - model, - }); - - const r = await fetch(`${url}/stream`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - input: { text: prompt }, - }), - }); - - if (!r.ok) { - throw new Error(`Failed to generate text: ${await r.text()}`); - } - - const encoder = new TextDecoderStream(); - const reader = r.body?.pipeThrough(encoder).getReader(); - - return (async function* () { - let stop = false; - let generatedText = ""; - let tokenId = 0; - let accumulatedData = ""; // Buffer to accumulate data chunks - - while (!stop) { - // Read the stream and log the outputs to console - const out = (await reader?.read()) ?? { done: false, value: undefined }; - - // If it's done, we cancel - if (out.done) { - reader?.cancel(); - return; - } - - if (!out.value) { - return; - } - - // Accumulate the data chunk - accumulatedData += out.value; - // Keep read data to check event type - const eventData = out.value; - - // Process each complete JSON object in the accumulated data - while (accumulatedData.includes("\n")) { - // Assuming each JSON object ends with a newline - const endIndex = accumulatedData.indexOf("\n"); - let jsonString = accumulatedData.substring(0, endIndex).trim(); - // Remove the processed part from the buffer - - accumulatedData = accumulatedData.substring(endIndex + 1); - - // Stopping with end event - if (eventData.startsWith("event: end")) { - stop = true; - yield { - token: { - id: tokenId++, - text: "", - logprob: 0, - special: true, - }, - generated_text: generatedText, - details: null, - } satisfies TextGenerationStreamOutput; - reader?.cancel(); - continue; - } - - if (eventData.startsWith("event: data") && jsonString.startsWith("data: ")) { - jsonString = jsonString.slice(6); - let data = null; - - // Handle the parsed data - try { - data = JSON.parse(jsonString); - } catch (e) { - logger.error(e, "Failed to parse JSON"); - logger.error(jsonString, "Problematic JSON string:"); - continue; // Skip this iteration and try the next chunk - } - // Assuming content within data is a plain string - if (data) { - generatedText += data; - const output: TextGenerationStreamOutput = { - token: { - id: tokenId++, - text: data, - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - }; - yield output; - } - } - } - } - })(); - }; -} - -export default endpointLangserve; diff --git a/src/lib/server/endpoints/llamacpp/endpointLlamacpp.ts b/src/lib/server/endpoints/llamacpp/endpointLlamacpp.ts deleted file mode 100644 index 671c1a50e8e38ab00d7ae8ae583d63ffb5e2ce58..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/llamacpp/endpointLlamacpp.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { config } from "$lib/server/config"; -import { buildPrompt } from "$lib/buildPrompt"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import type { Endpoint } from "../endpoints"; -import { z } from "zod"; -import { logger } from "$lib/server/logger"; - -export const endpointLlamacppParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("llamacpp"), - url: z.string().url().default("http://127.0.0.1:8080"), // legacy, feel free to remove in breaking change update - baseURL: z.string().url().optional(), - accessToken: z.string().default(config.HF_TOKEN ?? config.HF_ACCESS_TOKEN), -}); - -export function endpointLlamacpp( - input: z.input -): Endpoint { - const { baseURL, url, model } = endpointLlamacppParametersSchema.parse(input); - return async ({ messages, preprompt, continueMessage, generateSettings }) => { - const prompt = await buildPrompt({ - messages, - continueMessage, - preprompt, - model, - }); - - const parameters = { ...model.parameters, ...generateSettings }; - - const r = await fetch(`${baseURL ?? url}/completion`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - prompt, - stream: true, - temperature: parameters.temperature, - top_p: parameters.top_p, - top_k: parameters.top_k, - stop: parameters.stop, - repeat_penalty: parameters.repetition_penalty, - n_predict: parameters.max_new_tokens, - cache_prompt: true, - }), - }); - - if (!r.ok) { - throw new Error(`Failed to generate text: ${await r.text()}`); - } - - const encoder = new TextDecoderStream(); - const reader = r.body?.pipeThrough(encoder).getReader(); - - return (async function* () { - let stop = false; - let generatedText = ""; - let tokenId = 0; - let accumulatedData = ""; // Buffer to accumulate data chunks - - while (!stop) { - // Read the stream and log the outputs to console - const out = (await reader?.read()) ?? { done: false, value: undefined }; - - // If it's done, we cancel - if (out.done) { - reader?.cancel(); - return; - } - - if (!out.value) { - return; - } - - // Accumulate the data chunk - accumulatedData += out.value; - - // Process each complete JSON object in the accumulated data - while (accumulatedData.includes("\n")) { - // Assuming each JSON object ends with a newline - const endIndex = accumulatedData.indexOf("\n"); - let jsonString = accumulatedData.substring(0, endIndex).trim(); - - // Remove the processed part from the buffer - accumulatedData = accumulatedData.substring(endIndex + 1); - - if (jsonString.startsWith("data: ")) { - jsonString = jsonString.slice(6); - let data = null; - - try { - data = JSON.parse(jsonString); - } catch (e) { - logger.error(e, "Failed to parse JSON"); - logger.error(jsonString, "Problematic JSON string:"); - continue; // Skip this iteration and try the next chunk - } - - // Handle the parsed data - if (data.content || data.stop) { - generatedText += data.content; - const output: TextGenerationStreamOutput = { - token: { - id: tokenId++, - text: data.content ?? "", - logprob: 0, - special: false, - }, - generated_text: data.stop ? generatedText : null, - details: null, - }; - if (data.stop) { - stop = true; - output.token.special = true; - reader?.cancel(); - } - yield output; - } - } - } - } - })(); - }; -} - -export default endpointLlamacpp; diff --git a/src/lib/server/endpoints/local/endpointLocal.ts b/src/lib/server/endpoints/local/endpointLocal.ts deleted file mode 100644 index 83f3f50b08c2e4193a51f3aae413ae0a611d70f5..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/local/endpointLocal.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { config } from "$lib/server/config"; -import type { - Endpoint, - EndpointMessage, - TextGenerationStreamOutputWithToolsAndWebSources, -} from "../endpoints"; -import { z } from "zod"; -import { - createImageProcessorOptionsValidator, - makeImageProcessor, - type ImageProcessor, -} from "../images"; -import { findRepoRoot } from "$lib/server/findRepoRoot"; -import { fileURLToPath } from "url"; -import { dirname, join } from "path"; -import { logger } from "$lib/server/logger"; -import type { LlamaContextSequence } from "node-llama-cpp"; -export const endpointLocalParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - modelPath: z.string().optional(), - type: z.literal("local"), - multimodal: z - .object({ - // Assumes IDEFICS - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: ["image/jpeg", "image/webp"], - preferredMimeType: "image/webp", - maxSizeInMB: 5, - maxWidth: 378, - maxHeight: 980, - }), - }) - .default({}), -}); - -export async function endpointLocal( - input: z.input -): Promise { - // Parse and validate input - const { - modelPath: modelPathInput, - multimodal, - model, - } = endpointLocalParametersSchema.parse(input); - - // Setup model path and folder - const path = modelPathInput ?? `hf:${model.id ?? model.name}`; - const modelFolder = - config.MODELS_STORAGE_PATH || - join(findRepoRoot(dirname(fileURLToPath(import.meta.url))), "models"); - - // Initialize Llama model - - const { getLlama, LlamaChatSession, resolveModelFile } = await import("node-llama-cpp"); - - const modelPath = await resolveModelFile(path, modelFolder); - - const llama = await getLlama({ - logger: (level, message) => { - switch (level) { - case "fatal": - logger.fatal(message); - break; - case "error": - logger.error(message); - break; - case "warn": - logger.warn(message); - break; - case "info": - logger.info(message); - break; - case "log": - logger.info(message); // Map 'log' to 'info' since pino doesn't have a 'log' level - break; - case "debug": - logger.debug(message); - break; - default: - break; - } - }, - }); - - if (!llama) { - throw new Error("Failed to initialize llama.cpp build."); - } - const modelLoaded = await llama.loadModel({ - modelPath, - }); - // Create context and image processor - const context = await modelLoaded.createContext({ sequences: 1 }); - const imageProcessor = makeImageProcessor(multimodal.image); - - return async function ({ - messages, - preprompt, - continueMessage, - generateSettings, - // tools, - // toolResults, - isMultimodal, - }) { - // Process messages and build prompt - const processedMessages = await Promise.all( - messages.map((msg) => prepareMessage(Boolean(isMultimodal), msg, imageProcessor)) - ); - - let sequence: LlamaContextSequence; - try { - sequence = context.getSequence(); - } catch (error) { - logger.error(error, `Error getting sequence`); - throw error; - } - - const chatSession = new LlamaChatSession({ - contextSequence: sequence, - systemPrompt: preprompt, - }); - - chatSession.setChatHistory( - messages.slice(0, -1).map((message) => { - switch (message.from) { - case "user": - return { - type: "user", - text: message.content, - }; - case "assistant": - return { - type: "model", - response: [message.content], - }; - case "system": - return { - type: "system", - text: message.content, - }; - } - }) - ); - - async function* generateTokens(): AsyncGenerator { - let tokenId = 0; - let fullText = ""; - // A simple queue for tokens that have been produced - const queue: TextGenerationStreamOutputWithToolsAndWebSources[] = []; - let waitingResolve: - | ((value: TextGenerationStreamOutputWithToolsAndWebSources | null) => void) - | null = null; - let generationCompleted = false; - - // Helper function to push tokens to the queue - function pushOutput(output: TextGenerationStreamOutputWithToolsAndWebSources) { - if (waitingResolve) { - waitingResolve(output); - waitingResolve = null; - } else { - queue.push(output); - } - } - - const options = { - maxTokens: generateSettings?.max_new_tokens, - temperature: generateSettings?.temperature ?? 0.2, - topP: generateSettings?.top_p ?? 0.9, - topK: generateSettings?.top_k ?? 40, - onTextChunk: (text: string) => { - fullText += text; - const output: TextGenerationStreamOutputWithToolsAndWebSources = { - token: { - id: tokenId++, - text, - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - }; - // Instead of returning the token, push it into our queue. - pushOutput(output); - }, - }; - - let generationPromise; - if (!continueMessage) - // Start the token generation process - generationPromise = chatSession.prompt( - processedMessages[processedMessages.length - 1].content, - options - ); - else { - generationPromise = chatSession.completePrompt( - processedMessages[processedMessages.length - 1].content, - options - ); - } - - try { - // Yield tokens as they become available - while (!generationCompleted || queue.length > 0) { - if (queue.length === 0) { - const output = - await new Promise( - (resolve) => (waitingResolve = resolve) - ); - - // When output is null, it indicates generation completion. - if (output === null || !output.token.text) break; - if (model.parameters.stop_sequences?.includes(output.token.text)) { - break; - } - yield output; - } else { - const output = queue.shift(); - if (output) yield output; - } - } - - // Wait for the generation process to complete (and catch errors if any) - await generationPromise.finally(() => { - generationCompleted = true; - // Resolve any pending waiters so the loop can end. - if (waitingResolve) { - waitingResolve(null); - waitingResolve = null; - } - }); - - // Yield a final token that contains the full generated text. - yield { - token: { - id: tokenId, - text: "", - logprob: 0, - special: true, - }, - generated_text: fullText, - details: null, - }; - } catch (error) { - logger.error(error, `Generation error`); - // Ensure we clean up the LlamaManager in case of errors - throw error; - } - } - - return generateTokens(); - }; -} - -async function prepareMessage( - isMultimodal: boolean, - message: EndpointMessage, - imageProcessor: ImageProcessor -): Promise { - if (!isMultimodal) return message; - const files = await Promise.all(message.files?.map(imageProcessor) ?? []); - const markdowns = files.map( - (file) => `![](data:${file.mime};base64,${file.image.toString("base64")})` - ); - const content = message.content + "\n" + markdowns.join("\n "); - - return { ...message, content }; -} diff --git a/src/lib/server/endpoints/ollama/endpointOllama.ts b/src/lib/server/endpoints/ollama/endpointOllama.ts deleted file mode 100644 index 8c64f93a141f147a9e877e7bf094b067f12609b7..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/ollama/endpointOllama.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { buildPrompt } from "$lib/buildPrompt"; -import type { TextGenerationStreamOutput } from "@huggingface/inference"; -import type { Endpoint } from "../endpoints"; -import { z } from "zod"; - -export const endpointOllamaParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("ollama"), - url: z.string().url().default("http://127.0.0.1:11434"), - ollamaName: z.string().min(1).optional(), -}); - -export function endpointOllama(input: z.input): Endpoint { - const { url, model, ollamaName } = endpointOllamaParametersSchema.parse(input); - - return async ({ messages, preprompt, continueMessage, generateSettings }) => { - const prompt = await buildPrompt({ - messages, - continueMessage, - preprompt, - model, - }); - - const parameters = { ...model.parameters, ...generateSettings }; - - const requestInfo = await fetch(`${url}/api/tags`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - const tags = await requestInfo.json(); - - if (!tags.models.some((m: { name: string }) => m.name === ollamaName)) { - // if its not in the tags, pull but dont wait for the answer - fetch(`${url}/api/pull`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - name: ollamaName ?? model.name, - stream: false, - }), - }); - - throw new Error("Currently pulling model from Ollama, please try again later."); - } - - const r = await fetch(`${url}/api/generate`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - prompt, - model: ollamaName ?? model.name, - raw: true, - options: { - top_p: parameters.top_p, - top_k: parameters.top_k, - temperature: parameters.temperature, - repeat_penalty: parameters.repetition_penalty, - stop: parameters.stop, - num_predict: parameters.max_new_tokens, - }, - }), - }); - - if (!r.ok) { - throw new Error(`Failed to generate text: ${await r.text()}`); - } - - const encoder = new TextDecoderStream(); - const reader = r.body?.pipeThrough(encoder).getReader(); - - return (async function* () { - let generatedText = ""; - let tokenId = 0; - let stop = false; - while (!stop) { - // read the stream and log the outputs to console - const out = (await reader?.read()) ?? { done: false, value: undefined }; - // we read, if it's done we cancel - if (out.done) { - reader?.cancel(); - return; - } - - if (!out.value) { - return; - } - - let data = null; - try { - data = JSON.parse(out.value); - } catch (e) { - return; - } - if (!data.done) { - generatedText += data.response; - - yield { - token: { - id: tokenId++, - text: data.response ?? "", - logprob: 0, - special: false, - }, - generated_text: null, - details: null, - } satisfies TextGenerationStreamOutput; - } else { - stop = true; - yield { - token: { - id: tokenId++, - text: data.response ?? "", - logprob: 0, - special: true, - }, - generated_text: generatedText, - details: null, - } satisfies TextGenerationStreamOutput; - } - } - })(); - }; -} - -export default endpointOllama; diff --git a/src/lib/server/endpoints/openai/endpointOai.ts b/src/lib/server/endpoints/openai/endpointOai.ts index 2fa7ec2e88f1ca593c38f4fd83414710dd74bc63..7443fb764a059afe0cef48f1867b8acd38a9b0a9 100644 --- a/src/lib/server/endpoints/openai/endpointOai.ts +++ b/src/lib/server/endpoints/openai/endpointOai.ts @@ -8,88 +8,22 @@ import type { CompletionCreateParamsStreaming } from "openai/resources/completio import type { ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming, - ChatCompletionTool, } from "openai/resources/chat/completions"; -import type { FunctionDefinition, FunctionParameters } from "openai/resources/shared"; import { buildPrompt } from "$lib/buildPrompt"; import { config } from "$lib/server/config"; import type { Endpoint } from "../endpoints"; import type OpenAI from "openai"; import { createImageProcessorOptionsValidator, makeImageProcessor } from "../images"; import type { MessageFile } from "$lib/types/Message"; -import { type Tool } from "$lib/types/Tool"; import type { EndpointMessage } from "../endpoints"; -import { v4 as uuidv4 } from "uuid"; -function createChatCompletionToolsArray(tools: Tool[] | undefined): ChatCompletionTool[] { - const toolChoices = [] as ChatCompletionTool[]; - if (tools === undefined) { - return toolChoices; - } - - for (const t of tools) { - const requiredProperties = [] as string[]; - - const properties = {} as Record; - for (const idx in t.inputs) { - const parameterDefinition = t.inputs[idx]; - - const parameter = {} as Record; - switch (parameterDefinition.type) { - case "str": - parameter.type = "string"; - break; - case "float": - case "int": - parameter.type = "number"; - break; - case "bool": - parameter.type = "boolean"; - break; - case "file": - throw new Error("File type's currently not supported"); - default: - throw new Error(`Unknown tool IO type: ${t}`); - } - - if ("description" in parameterDefinition) { - parameter.description = parameterDefinition.description; - } - - if (parameterDefinition.paramType == "required") { - requiredProperties.push(t.inputs[idx].name); - } - - properties[t.inputs[idx].name] = parameter; - } - - const functionParameters: FunctionParameters = { - type: "object", - ...(requiredProperties.length > 0 ? { required: requiredProperties } : {}), - properties, - }; - - const functionDefinition: FunctionDefinition = { - name: t.name, - description: t.description, - parameters: functionParameters, - }; - - const toolDefinition: ChatCompletionTool = { - type: "function", - function: functionDefinition, - }; - - toolChoices.push(toolDefinition); - } - - return toolChoices; -} +// uuid import removed (no tool call ids) export const endpointOAIParametersSchema = z.object({ weight: z.number().int().positive().default(1), model: z.any(), type: z.literal("openai"), baseURL: z.string().url().default("https://api.openai.com/v1"), + // Canonical auth token is OPENAI_API_KEY; keep HF_TOKEN as legacy alias apiKey: z.string().default(config.OPENAI_API_KEY || config.HF_TOKEN || "sk-"), completion: z .union([z.literal("completions"), z.literal("chat_completions")]) @@ -101,17 +35,14 @@ export const endpointOAIParametersSchema = z.object({ .object({ image: createImageProcessorOptionsValidator({ supportedMimeTypes: [ + // Restrict to the most widely-supported formats "image/png", "image/jpeg", - "image/webp", - "image/avif", - "image/tiff", - "image/gif", ], - preferredMimeType: "image/webp", - maxSizeInMB: Infinity, - maxWidth: 4096, - maxHeight: 4096, + preferredMimeType: "image/jpeg", + maxSizeInMB: 3, + maxWidth: 2048, + maxHeight: 2048, }), }) .default({}), @@ -143,21 +74,38 @@ export async function endpointOai( throw new Error("Failed to import OpenAI", { cause: e }); } + // Store router metadata if captured + let routerMetadata: { route?: string; model?: string } = {}; + + // Custom fetch wrapper to capture response headers for router metadata + const customFetch = async (url: RequestInfo, init?: RequestInit): Promise => { + const response = await fetch(url, init); + + // Capture router headers if present (fallback for non-streaming) + const routeHeader = response.headers.get("X-Router-Route"); + const modelHeader = response.headers.get("X-Router-Model"); + + if (routeHeader && modelHeader) { + routerMetadata = { + route: routeHeader, + model: modelHeader, + }; + } + + return response; + }; + const openai = new OpenAI({ apiKey: apiKey || "sk-", baseURL, defaultHeaders, defaultQuery, + fetch: customFetch, }); const imageProcessor = makeImageProcessor(multimodal.image); if (completion === "completions") { - if (model.tools) { - throw new Error( - "Tools are not supported for 'completions' mode, switch to 'chat_completions' instead" - ); - } return async ({ messages, preprompt, continueMessage, generateSettings, conversationId }) => { const prompt = await buildPrompt({ messages, @@ -190,17 +138,10 @@ export async function endpointOai( return openAICompletionToTextGenerationStream(openAICompletion); }; } else if (completion === "chat_completions") { - return async ({ - messages, - preprompt, - generateSettings, - tools, - toolResults, - conversationId, - }) => { + return async ({ messages, preprompt, generateSettings, conversationId, isMultimodal }) => { // Format messages for the chat API, handling multimodal content if supported let messagesOpenAI: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = - await prepareMessages(messages, imageProcessor, !model.tools && model.multimodal); + await prepareMessages(messages, imageProcessor, isMultimodal ?? model.multimodal); // Check if a system message already exists as the first message const hasSystemMessage = messagesOpenAI.length > 0 && messagesOpenAI[0]?.role === "system"; @@ -219,60 +160,8 @@ export async function endpointOai( messagesOpenAI = [{ role: "system", content: preprompt ?? "" }, ...messagesOpenAI]; } - // Handle models that don't support system role by converting to user message - // This maintains compatibility with older or non-standard models - if ( - !model.systemRoleSupported && - messagesOpenAI.length > 0 && - messagesOpenAI[0]?.role === "system" - ) { - messagesOpenAI[0] = { - ...messagesOpenAI[0], - role: "user", - }; - } - - // Format tool results for the API to provide context for follow-up tool calls - // This creates the full conversation flow needed for multi-step tool interactions - if (toolResults && toolResults.length > 0) { - const toolCallRequests: OpenAI.Chat.Completions.ChatCompletionAssistantMessageParam = { - role: "assistant", - content: null, - tool_calls: [], - }; - - const responses: Array = []; - - for (const result of toolResults) { - const id = result?.call?.toolId || uuidv4(); - - const toolCallResult: OpenAI.Chat.Completions.ChatCompletionMessageToolCall = { - type: "function", - function: { - name: result.call.name, - arguments: JSON.stringify(result.call.parameters), - }, - id, - }; - - toolCallRequests.tool_calls?.push(toolCallResult); - const toolCallResponse: OpenAI.Chat.Completions.ChatCompletionToolMessageParam = { - role: "tool", - content: "", - tool_call_id: id, - }; - if ("outputs" in result) { - toolCallResponse.content = JSON.stringify(result.outputs); - } - responses.push(toolCallResponse); - } - messagesOpenAI.push(toolCallRequests); - messagesOpenAI.push(...responses); - } - // Combine model defaults with request-specific parameters const parameters = { ...model.parameters, ...generateSettings }; - const toolCallChoices = createChatCompletionToolsArray(tools); const body = { model: model.id ?? model.name, messages: messagesOpenAI, @@ -286,8 +175,6 @@ export async function endpointOai( top_p: parameters?.top_p, frequency_penalty: parameters?.repetition_penalty, presence_penalty: parameters?.presence_penalty, - // Only include tool configuration if tools are provided - ...(toolCallChoices.length > 0 ? { tools: toolCallChoices, tool_choice: "auto" } : {}), }; // Handle both streaming and non-streaming responses with appropriate processors @@ -302,7 +189,7 @@ export async function endpointOai( }, } ); - return openAIChatToTextGenerationStream(openChatAICompletion); + return openAIChatToTextGenerationStream(openChatAICompletion, () => routerMetadata); } else { const openChatAICompletion = await openai.chat.completions.create( body as ChatCompletionCreateParamsNonStreaming, @@ -314,7 +201,7 @@ export async function endpointOai( }, } ); - return openAIChatToTextGenerationSingle(openChatAICompletion); + return openAIChatToTextGenerationSingle(openChatAICompletion, () => routerMetadata); } }; } else { @@ -330,18 +217,13 @@ async function prepareMessages( return Promise.all( messages.map(async (message) => { if (message.from === "user" && isMultimodal) { - return { - role: message.from, - content: [ - ...(await prepareFiles(imageProcessor, message.files ?? [])), - { type: "text", text: message.content }, - ], - }; + const parts = [ + { type: "text" as const, text: message.content }, + ...(await prepareFiles(imageProcessor, message.files ?? [])), + ]; + return { role: message.from, content: parts }; } - return { - role: message.from, - content: message.content, - }; + return { role: message.from, content: message.content }; }) ); } @@ -357,6 +239,9 @@ async function prepareFiles( type: "image_url" as const, image_url: { url: `data:${file.mime};base64,${file.image.toString("base64")}`, + // Improves compatibility with some OpenAI-compatible servers + // that expect an explicit detail setting. + detail: "auto", }, })); } diff --git a/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts b/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts index b69b92009f2e94e0e878d0aa80ea394d85f2fa06..a4bc885312a299f514d7923acf8313ee6fd5255e 100644 --- a/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts +++ b/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts @@ -1,59 +1,57 @@ import type { TextGenerationStreamOutput } from "@huggingface/inference"; import type OpenAI from "openai"; import type { Stream } from "openai/streaming"; -import type { ToolCall } from "$lib/types/Tool"; - -type ToolCallWithParameters = { - toolCall: ToolCall; - parameterJsonString: string; -}; - -function prepareToolCalls(toolCallsWithParameters: ToolCallWithParameters[], tokenId: number) { - const toolCalls: ToolCall[] = []; - - for (const toolCallWithParameters of toolCallsWithParameters) { - // HACK: sometimes gpt4 via azure returns the JSON with literal newlines in it - // like {\n "foo": "bar" } - const s = toolCallWithParameters.parameterJsonString.replace("\n", ""); - const params = JSON.parse(s); - - const toolCall = toolCallWithParameters.toolCall; - for (const name in params) { - toolCall.parameters[name] = params[name]; - } - - toolCalls.push(toolCall); - } - - const output = { - token: { - id: tokenId, - text: "", - logprob: 0, - special: false, - toolCalls, - }, - generated_text: null, - details: null, - }; - - return output; -} /** * Transform a stream of OpenAI.Chat.ChatCompletion into a stream of TextGenerationStreamOutput */ export async function* openAIChatToTextGenerationStream( - completionStream: Stream + completionStream: Stream, + getRouterMetadata?: () => { route?: string; model?: string } ) { let generatedText = ""; let tokenId = 0; - const toolCalls: ToolCallWithParameters[] = []; - let toolBuffer = ""; // XXX: hack because tools seem broken on tgi openai endpoints? + let toolBuffer = ""; // legacy hack kept harmless + let metadataYielded = false; + let thinkOpen = false; for await (const completion of completionStream) { + // Check if this chunk contains router metadata (first chunk from llm-router) + if (!metadataYielded && (completion as any)["x-router-metadata"]) { + const metadata = (completion as any)["x-router-metadata"]; + yield { + token: { + id: tokenId++, + text: "", + logprob: 0, + special: true, + }, + generated_text: null, + details: null, + routerMetadata: { + route: metadata.route, + model: metadata.model, + }, + } as TextGenerationStreamOutput & { routerMetadata: { route: string; model: string } }; + metadataYielded = true; + // Skip processing this chunk as content since it's just metadata + if ( + !completion.choices || + completion.choices.length === 0 || + !completion.choices[0].delta?.content + ) { + continue; + } + } const { choices } = completion; - const content = choices[0]?.delta?.content ?? ""; + const delta: any = choices?.[0]?.delta ?? {}; + const content: string = (delta?.content as string) ?? ""; + const reasoning: string = + typeof delta?.reasoning === "string" + ? (delta.reasoning as string) + : typeof delta?.reasoning_content === "string" + ? (delta.reasoning_content as string) + : ""; const last = choices[0]?.finish_reason === "stop" || choices[0]?.finish_reason === "length"; // if the last token is a stop and the tool buffer is not empty, yield it as a generated_text @@ -90,13 +88,39 @@ export async function* openAIChatToTextGenerationStream( } } - if (content) { - generatedText = generatedText + content; + let combined = ""; + if (reasoning && reasoning.length > 0) { + if (!thinkOpen) { + combined += "" + reasoning; + thinkOpen = true; + } else { + combined += reasoning; + } + } + + if (content && content.length > 0) { + const trimmed = content.trim(); + // If provider sends a lone closing tag with no prior , drop it. + if (!thinkOpen && trimmed === "") { + // ignore stray closing tag + } else if (thinkOpen && trimmed === "") { + // close once without duplicating the tag + combined += ""; + thinkOpen = false; + } else if (thinkOpen) { + combined += "" + content; + thinkOpen = false; + } else { + combined += content; + } } + + // Accumulate the combined token into the full text + generatedText += combined; const output: TextGenerationStreamOutput = { token: { id: tokenId++, - text: content ?? "", + text: combined, logprob: 0, special: last, }, @@ -105,30 +129,24 @@ export async function* openAIChatToTextGenerationStream( }; yield output; - const tools = completion.choices[0]?.delta?.tool_calls || []; - for (const tool of tools) { - if (tool.id) { - if (!tool.function?.name) { - throw new Error("Tool call without function name"); - } - const toolCallWithParameters: ToolCallWithParameters = { - toolCall: { - name: tool.function.name, - parameters: {}, - toolId: tool.id, - }, - parameterJsonString: "", - }; - toolCalls.push(toolCallWithParameters); - } - - if (toolCalls.length > 0 && tool.function?.arguments) { - toolCalls[toolCalls.length - 1].parameterJsonString += tool.function.arguments; - } - } + // Tools removed: ignore tool_calls deltas + } - if (choices[0]?.finish_reason === "tool_calls") { - yield prepareToolCalls(toolCalls, tokenId++); + // If metadata wasn't yielded from chunks (e.g., from headers), yield it at the end + if (!metadataYielded && getRouterMetadata) { + const routerMetadata = getRouterMetadata(); + if (routerMetadata && routerMetadata.route && routerMetadata.model) { + yield { + token: { + id: tokenId++, + text: "", + logprob: 0, + special: true, + }, + generated_text: null, + details: null, + routerMetadata, + } as TextGenerationStreamOutput & { routerMetadata: { route?: string; model?: string } }; } } } @@ -137,9 +155,21 @@ export async function* openAIChatToTextGenerationStream( * Transform a non-streaming OpenAI chat completion into a stream of TextGenerationStreamOutput */ export async function* openAIChatToTextGenerationSingle( - completion: OpenAI.Chat.Completions.ChatCompletion + completion: OpenAI.Chat.Completions.ChatCompletion, + getRouterMetadata?: () => { route?: string; model?: string } ) { - const content = completion.choices[0]?.message?.content || ""; + const message: any = completion.choices?.[0]?.message ?? {}; + let content: string = message?.content || ""; + // Provider-dependent reasoning shapes (non-streaming) + const r: string = + typeof message?.reasoning === "string" + ? (message.reasoning as string) + : typeof message?.reasoning_content === "string" + ? (message.reasoning_content as string) + : ""; + if (r && r.length > 0) { + content = `${r}` + content; + } const tokenId = 0; // Yield the content as a single token @@ -152,5 +182,11 @@ export async function* openAIChatToTextGenerationSingle( }, generated_text: content, details: null, - } as TextGenerationStreamOutput; + ...(getRouterMetadata + ? (() => { + const metadata = getRouterMetadata(); + return metadata && metadata.route && metadata.model ? { routerMetadata: metadata } : {}; + })() + : {}), + } as TextGenerationStreamOutput & { routerMetadata?: { route?: string; model?: string } }; } diff --git a/src/lib/server/endpoints/preprocessMessages.ts b/src/lib/server/endpoints/preprocessMessages.ts index d4e272c460ea6297d3cf14ae4833c03b0417e808..5d403e4bf8d5b49b4d863c616c838f15fb370848 100644 --- a/src/lib/server/endpoints/preprocessMessages.ts +++ b/src/lib/server/endpoints/preprocessMessages.ts @@ -1,52 +1,17 @@ import type { Message } from "$lib/types/Message"; -import { format } from "date-fns"; import type { EndpointMessage } from "./endpoints"; import { downloadFile } from "../files/downloadFile"; import type { ObjectId } from "mongodb"; export async function preprocessMessages( messages: Message[], - webSearch: Message["webSearch"], convId: ObjectId ): Promise { return Promise.resolve(messages) - .then((msgs) => addWebSearchContext(msgs, webSearch)) .then((msgs) => downloadFiles(msgs, convId)) .then((msgs) => injectClipboardFiles(msgs)); } -function addWebSearchContext(messages: Message[], webSearch: Message["webSearch"]) { - const webSearchContext = webSearch?.contextSources - .map(({ context }, idx) => `Source [${idx + 1}]\n${context.trim()}`) - .join("\n\n----------\n\n"); - - // No web search context available, skip - if (!webSearch || !webSearchContext?.trim()) return messages; - // No messages available, skip - if (messages.length === 0) return messages; - - const lastQuestion = messages.findLast((el) => el.from === "user")?.content ?? ""; - const previousQuestions = messages - .filter((el) => el.from === "user") - .slice(0, -1) - .map((el) => el.content); - const currentDate = format(new Date(), "MMMM d, yyyy"); - - const finalMessage = { - ...messages[messages.length - 1], - content: `I searched the web using the query: ${webSearch.searchQuery}. The query was generated by a tool and might not be relevant to the question. -Today is ${currentDate} and here are the results. -When answering the question, you must reference the sources you used inline by wrapping the index in brackets like this: [1]. If multiple sources are used, you must reference each one of them without commas like this: [1][2][3]. -===================== -${webSearchContext} -===================== -${previousQuestions.length > 0 ? `Previous questions: \n- ${previousQuestions.join("\n- ")}` : ""} -Answer the question: ${lastQuestion}`, - }; - - return [...messages.slice(0, -1), finalMessage]; -} - async function downloadFiles(messages: Message[], convId: ObjectId): Promise { return Promise.all( messages.map>((message) => diff --git a/src/lib/server/endpoints/tgi/endpointTgi.ts b/src/lib/server/endpoints/tgi/endpointTgi.ts deleted file mode 100644 index c2f50efb5c6b7afe5f4daed42b008035efd63f71..0000000000000000000000000000000000000000 --- a/src/lib/server/endpoints/tgi/endpointTgi.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { config } from "$lib/server/config"; -import { buildPrompt } from "$lib/buildPrompt"; -import { textGenerationStream } from "@huggingface/inference"; -import type { Endpoint, EndpointMessage } from "../endpoints"; -import { z } from "zod"; -import { - createImageProcessorOptionsValidator, - makeImageProcessor, - type ImageProcessor, -} from "../images"; - -export const endpointTgiParametersSchema = z.object({ - weight: z.number().int().positive().default(1), - model: z.any(), - type: z.literal("tgi"), - url: z.string().url(), - accessToken: z.string().default(config.HF_TOKEN ?? config.HF_ACCESS_TOKEN), - authorization: z.string().optional(), - multimodal: z - .object({ - // Assumes IDEFICS - image: createImageProcessorOptionsValidator({ - supportedMimeTypes: ["image/jpeg", "image/webp"], - preferredMimeType: "image/webp", - maxSizeInMB: 5, - maxWidth: 378, - maxHeight: 980, - }), - }) - .default({}), -}); - -export function endpointTgi(input: z.input): Endpoint { - const { url, accessToken, model, authorization, multimodal } = - endpointTgiParametersSchema.parse(input); - const imageProcessor = makeImageProcessor(multimodal.image); - - return async ({ - messages, - preprompt, - continueMessage, - generateSettings, - tools, - toolResults, - isMultimodal, - conversationId, - }) => { - const messagesWithResizedFiles = await Promise.all( - messages.map((message) => prepareMessage(Boolean(isMultimodal), message, imageProcessor)) - ); - - const prompt = await buildPrompt({ - messages: messagesWithResizedFiles, - preprompt, - model, - continueMessage, - tools, - toolResults, - }); - - return textGenerationStream( - { - parameters: { ...model.parameters, ...generateSettings, return_full_text: false }, - model: url, - inputs: prompt, - accessToken, - }, - { - fetch: async (endpointUrl, info) => { - if (info && authorization && !accessToken) { - // Set authorization header if it is defined and HF_TOKEN is empty - info.headers = { - ...info.headers, - Authorization: authorization, - "ChatUI-Conversation-ID": conversationId?.toString() ?? "", - "X-Use-Cache": "false", - }; - } - return fetch(endpointUrl, info); - }, - } - ); - }; -} - -async function prepareMessage( - isMultimodal: boolean, - message: EndpointMessage, - imageProcessor: ImageProcessor -): Promise { - if (!isMultimodal) return message; - const files = await Promise.all(message.files?.map(imageProcessor) ?? []); - const markdowns = files.map( - (file) => `![](data:${file.mime};base64,${file.image.toString("base64")})` - ); - const content = message.content + "\n" + markdowns.join("\n "); - - return { ...message, content }; -} diff --git a/src/lib/server/generateFromDefaultEndpoint.ts b/src/lib/server/generateFromDefaultEndpoint.ts index 32d1fa3924ab958dbe26f10c1af6114a85c936c7..b8da7ddb738440db2040be28dd1c21542e592c00 100644 --- a/src/lib/server/generateFromDefaultEndpoint.ts +++ b/src/lib/server/generateFromDefaultEndpoint.ts @@ -1,4 +1,4 @@ -import { taskModel } from "$lib/server/models"; +import { taskModel, models } from "$lib/server/models"; import { MessageUpdateType, type MessageUpdate } from "$lib/types/MessageUpdate"; import type { EndpointMessage } from "./endpoints/endpoints"; @@ -6,20 +6,25 @@ export async function* generateFromDefaultEndpoint({ messages, preprompt, generateSettings, + modelId, }: { messages: EndpointMessage[]; preprompt?: string; generateSettings?: Record; + /** Optional: use this model instead of the default task model */ + modelId?: string; }): AsyncGenerator { try { - const endpoint = await taskModel.getEndpoint(); + // Choose endpoint based on provided modelId, else fall back to taskModel + const model = modelId ? (models.find((m) => m.id === modelId) ?? taskModel) : taskModel; + const endpoint = await model.getEndpoint(); const tokenStream = await endpoint({ messages, preprompt, generateSettings }); for await (const output of tokenStream) { // if not generated_text is here it means the generation is not done if (output.generated_text) { let generated_text = output.generated_text; - for (const stop of [...(taskModel.parameters?.stop ?? []), "<|endoftext|>"]) { + for (const stop of [...(model.parameters?.stop ?? []), "<|endoftext|>"]) { if (generated_text.endsWith(stop)) { generated_text = generated_text.slice(0, -stop.length).trimEnd(); } diff --git a/src/lib/server/metrics.ts b/src/lib/server/metrics.ts deleted file mode 100644 index d198830edf77ec1c64ce69c1b9b8476bfe7cd0a0..0000000000000000000000000000000000000000 --- a/src/lib/server/metrics.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { collectDefaultMetrics, Registry, Counter, Summary } from "prom-client"; -import express from "express"; -import { logger } from "$lib/server/logger"; -import { config } from "$lib/server/config"; -import type { Model } from "$lib/types/Model"; -import { onExit } from "./exitHandler"; -import { promisify } from "util"; - -interface Metrics { - model: { - conversationsTotal: Counter; - messagesTotal: Counter; - tokenCountTotal: Counter; - timePerOutputToken: Summary; - timeToFirstToken: Summary; - latency: Summary; - votesPositive: Counter; - votesNegative: Counter; - }; - - webSearch: { - requestCount: Counter; - pageFetchCount: Counter; - pageFetchCountError: Counter; - pageFetchDuration: Summary; - embeddingDuration: Summary; - }; - - tool: { - toolUseCount: Counter; - toolUseCountError: Counter; - toolUseDuration: Summary; - timeToChooseTools: Summary; - }; -} - -export class MetricsServer { - private static instance: MetricsServer; - private metrics: Metrics; - - private constructor() { - const app = express(); - - const port = Number(config.METRICS_PORT || "5565"); - if (isNaN(port) || port < 0 || port > 65535) { - logger.warn(`Invalid value for METRICS_PORT: ${config.METRICS_PORT}`); - } - - if (config.METRICS_ENABLED !== "false" && config.METRICS_ENABLED !== "true") { - logger.warn(`Invalid value for METRICS_ENABLED: ${config.METRICS_ENABLED}`); - } - if (config.METRICS_ENABLED === "true") { - const server = app.listen(port, () => { - logger.info(`Metrics server listening on port ${port}`); - }); - const closeServer = promisify(server.close); - onExit(async () => { - logger.info("Disconnecting metrics server ..."); - await closeServer(); - logger.info("Server stopped ..."); - }); - } - - const register = new Registry(); - collectDefaultMetrics({ register }); - - this.metrics = { - model: { - conversationsTotal: new Counter({ - name: "model_conversations_total", - help: "Total number of conversations", - labelNames: ["model"], - registers: [register], - }), - messagesTotal: new Counter({ - name: "model_messages_total", - help: "Total number of messages", - labelNames: ["model"], - registers: [register], - }), - tokenCountTotal: new Counter({ - name: "model_token_count_total", - help: "Total number of tokens", - labelNames: ["model"], - registers: [register], - }), - timePerOutputToken: new Summary({ - name: "model_time_per_output_token_ms", - help: "Time per output token in ms", - labelNames: ["model"], - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - timeToFirstToken: new Summary({ - name: "model_time_to_first_token_ms", - help: "Time to first token", - labelNames: ["model"], - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - latency: new Summary({ - name: "model_latency_ms", - help: "Total latency until end of answer", - labelNames: ["model"], - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - votesPositive: new Counter({ - name: "model_votes_positive", - help: "Total number of positive votes on messages generated by the model", - labelNames: ["model"], - registers: [register], - }), - votesNegative: new Counter({ - name: "model_votes_negative", - help: "Total number of negative votes on messages generated by the model", - labelNames: ["model"], - registers: [register], - }), - }, - webSearch: { - requestCount: new Counter({ - name: "web_search_request_count", - help: "Total number of web search requests", - registers: [register], - }), - pageFetchCount: new Counter({ - name: "web_search_page_fetch_count", - help: "Total number of web search page fetches", - registers: [register], - }), - pageFetchCountError: new Counter({ - name: "web_search_page_fetch_count_error", - help: "Total number of web search page fetch errors", - registers: [register], - }), - pageFetchDuration: new Summary({ - name: "web_search_page_fetch_duration_ms", - help: "Web search page fetch duration", - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - embeddingDuration: new Summary({ - name: "web_search_embedding_duration_ms", - help: "Web search embedding duration", - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - }, - tool: { - toolUseCount: new Counter({ - name: "tool_use_count", - help: "Total number of tool uses", - labelNames: ["tool"], - registers: [register], - }), - toolUseCountError: new Counter({ - name: "tool_use_count_error", - help: "Total number of tool use errors", - labelNames: ["tool"], - registers: [register], - }), - toolUseDuration: new Summary({ - name: "tool_use_duration_ms", - help: "Tool use duration", - labelNames: ["tool"], - registers: [register], - maxAgeSeconds: 30 * 60, // longer duration since we use this to give feedback to the user - ageBuckets: 5, - }), - timeToChooseTools: new Summary({ - name: "time_to_choose_tools_ms", - help: "Time to choose tools", - labelNames: ["model"], - registers: [register], - maxAgeSeconds: 5 * 60, - ageBuckets: 5, - }), - }, - }; - - app.get("/metrics", (req, res) => { - register.metrics().then((metrics) => { - res.set("Content-Type", "text/plain"); - res.send(metrics); - }); - }); - } - - public static getInstance(): MetricsServer { - if (!MetricsServer.instance) { - MetricsServer.instance = new MetricsServer(); - } - - return MetricsServer.instance; - } - - public static getMetrics(): Metrics { - return MetricsServer.getInstance().metrics; - } -} diff --git a/src/lib/server/models.ts b/src/lib/server/models.ts index dca275cbd5c17c76dc01e40b18efb8da00b9030d..ccfc72ff4c06b7c738c5d03299ce969a48e5f9b0 100644 --- a/src/lib/server/models.ts +++ b/src/lib/server/models.ts @@ -1,31 +1,20 @@ import { config } from "$lib/server/config"; import type { ChatTemplateInput } from "$lib/types/Template"; -import { compileTemplate } from "$lib/utils/template"; import { z } from "zod"; import endpoints, { endpointSchema, type Endpoint } from "./endpoints/endpoints"; -import { endpointTgi } from "./endpoints/tgi/endpointTgi"; -import { sum } from "$lib/utils/sum"; -import { embeddingModels, validateEmbeddingModelByName } from "./embeddingModels"; - -import type { PreTrainedTokenizer } from "@huggingface/transformers"; import JSON5 from "json5"; -import { getTokenizer } from "$lib/utils/getTokenizer"; import { logger } from "$lib/server/logger"; -import { type ToolInput } from "$lib/types/Tool"; -import { fetchJSON } from "$lib/utils/fetchJSON"; -import { join, dirname } from "path"; -import { fileURLToPath } from "url"; -import { findRepoRoot } from "./findRepoRoot"; -import { Template } from "@huggingface/jinja"; -import { readdirSync } from "fs"; - -export const MODELS_FOLDER = - config.MODELS_STORAGE_PATH || - join(findRepoRoot(dirname(fileURLToPath(import.meta.url))), "models"); +import { makeRouterEndpoint } from "$lib/server/router/endpoint"; type Optional = Pick, K> & Omit; +const sanitizeJSONEnv = (val: string, fallback: string) => { + const raw = (val ?? "").trim(); + const unquoted = raw.startsWith("`") && raw.endsWith("`") ? raw.slice(1, -1) : raw; + return unquoted || fallback; +}; + const reasoningSchema = z.union([ z.object({ type: z.literal("regex"), // everything is reasoning, extract the answer from the regex @@ -51,20 +40,12 @@ const modelConfig = z.object({ logoUrl: z.string().url().optional(), websiteUrl: z.string().url().optional(), modelUrl: z.string().url().optional(), - tokenizer: z - .union([ - z.string(), - z.object({ - tokenizerUrl: z.string().url(), - tokenizerConfigUrl: z.string().url(), - }), - ]) - .optional(), + tokenizer: z.never().optional(), datasetName: z.string().min(1).optional(), datasetUrl: z.string().url().optional(), preprompt: z.string().default(""), prepromptUrl: z.string().url().optional(), - chatPromptTemplate: z.string().optional(), + chatPromptTemplate: z.never().optional(), promptExamples: z .array( z.object({ @@ -74,6 +55,7 @@ const modelConfig = z.object({ ) .optional(), endpoints: z.array(endpointSchema).optional(), + providers: z.array(z.object({ supports_tools: z.boolean().optional() }).passthrough()).optional(), parameters: z .object({ temperature: z.number().min(0).max(2).optional(), @@ -89,286 +71,261 @@ const modelConfig = z.object({ .optional(), multimodal: z.boolean().default(false), multimodalAcceptedMimetypes: z.array(z.string()).optional(), - tools: z.boolean().default(false), unlisted: z.boolean().default(false), - embeddingModel: validateEmbeddingModelByName(embeddingModels).optional(), + embeddingModel: z.never().optional(), /** Used to enable/disable system prompt usage */ systemRoleSupported: z.boolean().default(true), reasoning: reasoningSchema.optional(), }); -const ggufModelsConfig = await Promise.all( - readdirSync(MODELS_FOLDER) - .filter((f) => f.endsWith(".gguf")) - .map(async (f) => { - return { - name: f.replace(".gguf", ""), - endpoints: [ - { - type: "local" as const, - modelPath: f, - }, - ], - }; - }) -); +type ModelConfig = z.infer; -const turnStringIntoLocalModel = z.preprocess((obj: unknown) => { - if (typeof obj !== "string") return obj; +const overrideEntrySchema = modelConfig + .partial() + .extend({ + id: z.string().optional(), + name: z.string().optional(), + }) + .refine((value) => Boolean((value.id ?? value.name)?.trim()), { + message: "Model override entry must provide an id or name", + }); - const name = obj.startsWith("hf:") ? obj.split(":")[1] : obj; - const displayName = obj.startsWith("hf:") - ? obj.split(":")[1].split("/").slice(0, 2).join("/") - : obj.endsWith(".gguf") - ? obj.replace(".gguf", "") - : obj; +type ModelOverride = z.infer; - const modelPath = obj.includes("/") && !obj.startsWith("hf:") ? `hf:${obj}` : obj; +// ggufModelsConfig unused in this build - return { - name, - displayName, - endpoints: [ - { - type: "local", - modelPath, - }, - ], - } satisfies z.input; -}, modelConfig); +// Source models exclusively from an OpenAI-compatible endpoint. +let modelsRaw: ModelConfig[] = []; -let modelsRaw = z.array(turnStringIntoLocalModel).parse(JSON5.parse(config.MODELS ?? "[]")); +// Require explicit base URL; no implicit default here +const openaiBaseUrl = config.OPENAI_BASE_URL + ? config.OPENAI_BASE_URL.replace(/\/$/, "") + : undefined; +const isHFRouter = openaiBaseUrl === "https://router.huggingface.co/v1"; -if (config.LOAD_GGUF_MODELS === "true" || modelsRaw.length === 0) { - const parsedGgufModels = z.array(modelConfig).parse(ggufModelsConfig); - modelsRaw = [...modelsRaw, ...parsedGgufModels]; -} - -async function getChatPromptRender( - m: z.infer -): Promise>> { - if (m.endpoints?.some((e) => e.type === "local")) { - const endpoint = m.endpoints?.find((e) => e.type === "local"); - const path = endpoint?.modelPath ?? `hf:${m.id ?? m.name}`; - - const { resolveModelFile, readGgufFileInfo } = await import("node-llama-cpp"); +if (openaiBaseUrl) { + try { + const baseURL = openaiBaseUrl; + logger.info({ baseURL }, "[models] Using OpenAI-compatible base URL"); + + // Canonical auth token is OPENAI_API_KEY; keep HF_TOKEN as legacy alias + const authToken = config.OPENAI_API_KEY || config.HF_TOKEN || ""; + + // Try unauthenticated request first (many model lists are public, e.g. HF router) + let response = await fetch(`${baseURL}/models`); + logger.info({ status: response.status }, "[models] First fetch status"); + if (response.status === 401 || response.status === 403) { + // Retry with Authorization header if available + response = await fetch(`${baseURL}/models`, { + headers: authToken ? { Authorization: `Bearer ${authToken}` } : undefined, + }); + logger.info({ status: response.status }, "[models] Retried fetch status"); + } + if (!response.ok) { + throw new Error( + `Failed to fetch ${baseURL}/models: ${response.status} ${response.statusText}` + ); + } + const json = await response.json(); + logger.info({ keys: Object.keys(json || {}) }, "[models] Response keys"); + + const listSchema = z + .object({ + data: z.array( + z.object({ + id: z.string(), + description: z.string().optional(), + providers: z + .array(z.object({ supports_tools: z.boolean().optional() }).passthrough()) + .optional(), + architecture: z + .object({ + input_modalities: z.array(z.string()).optional(), + }) + .passthrough() + .optional(), + }) + ), + }) + .passthrough(); - const modelPath = await resolveModelFile(path, MODELS_FOLDER); + const parsed = listSchema.parse(json); + logger.info({ count: parsed.data.length }, "[models] Parsed models count"); - const info = await readGgufFileInfo(modelPath, { - readTensorInfo: false, - }); + modelsRaw = parsed.data.map((m) => { + let logoUrl: string | undefined = undefined; + if (isHFRouter && m.id.includes("/")) { + const org = m.id.split("/")[0]; + logoUrl = `https://huggingface.co/api/organizations/${encodeURIComponent(org)}/avatar?redirect=true`; + } - if (info.metadata.tokenizer.chat_template) { - // compile with jinja - const jinjaTemplate = new Template(info.metadata.tokenizer.chat_template); - return (inputs: ChatTemplateInput) => { - return jinjaTemplate.render({ ...m, ...inputs }); - }; - } + const inputModalities = (m.architecture?.input_modalities ?? []).map((modality) => + modality.toLowerCase() + ); + const supportsImageInput = + inputModalities.includes("image") || inputModalities.includes("vision"); + return { + id: m.id, + name: m.id, + displayName: m.id, + description: m.description, + logoUrl, + providers: m.providers, + multimodal: supportsImageInput, + multimodalAcceptedMimetypes: supportsImageInput ? ["image/*"] : undefined, + endpoints: [ + { + type: "openai" as const, + baseURL, + // apiKey will be taken from OPENAI_API_KEY or HF_TOKEN automatically + }, + ], + } as ModelConfig; + }) as ModelConfig[]; + } catch (e) { + logger.error(e, "Failed to load models from OpenAI base URL"); + throw e; } +} else { + logger.error( + "OPENAI_BASE_URL is required. Set it to an OpenAI-compatible base (e.g., https://router.huggingface.co/v1)." + ); + throw new Error("OPENAI_BASE_URL not set"); +} - if (m.chatPromptTemplate) { - return compileTemplate(m.chatPromptTemplate, m); - } - let tokenizer: PreTrainedTokenizer; +let modelOverrides: ModelOverride[] = []; +const overridesEnv = (Reflect.get(config, "MODELS") as string | undefined) ?? ""; +if (overridesEnv.trim()) { try { - tokenizer = await getTokenizer(m.tokenizer ?? m.id ?? m.name); - } catch (e) { - // if fetching the tokenizer fails but it wasnt manually set, use the default template - if (!m.tokenizer) { - logger.warn( - `No tokenizer found for model ${m.name}, using default template. Consider setting tokenizer manually or making sure the model is available on the hub.`, - m - ); - return compileTemplate( - "{{#if @root.preprompt}}<|im_start|>system\n{{@root.preprompt}}<|im_end|>\n{{/if}}{{#each messages}}{{#ifUser}}<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n{{/ifUser}}{{#ifAssistant}}{{content}}<|im_end|>\n{{/ifAssistant}}{{/each}}", - m - ); - } - - logger.error( - e, - `Failed to load tokenizer ${ - m.tokenizer ?? m.id ?? m.name - } make sure the model is available on the hub and you have access to any gated models.` - ); - process.exit(); + modelOverrides = z + .array(overrideEntrySchema) + .parse(JSON5.parse(sanitizeJSONEnv(overridesEnv, "[]"))); + } catch (error) { + logger.error(error, "[models] Failed to parse MODELS overrides"); } +} - const renderTemplate = ({ messages, preprompt, tools, continueMessage }: ChatTemplateInput) => { - let formattedMessages: { - role: string; - content: string; - tool_calls?: { id: string; tool_call_id: string; output: string }[]; - }[] = messages.map((message) => ({ - content: message.content, - role: message.from, - })); - - if (!m.systemRoleSupported) { - const firstSystemMessage = formattedMessages.find((msg) => msg.role === "system"); - formattedMessages = formattedMessages.filter((msg) => msg.role !== "system"); - - if ( - firstSystemMessage && - formattedMessages.length > 0 && - formattedMessages[0].role === "user" - ) { - formattedMessages[0].content = - firstSystemMessage.content + "\n" + formattedMessages[0].content; - } +if (modelOverrides.length) { + const overrideMap = new Map(); + for (const override of modelOverrides) { + for (const key of [override.id, override.name]) { + const trimmed = key?.trim(); + if (trimmed) overrideMap.set(trimmed, override); } + } - if (preprompt && formattedMessages[0].role !== "system") { - formattedMessages = [ - { - role: m.systemRoleSupported ? "system" : "user", - content: preprompt, - }, - ...formattedMessages, - ]; - } + modelsRaw = modelsRaw.map((model) => { + const override = overrideMap.get(model.id ?? "") ?? overrideMap.get(model.name ?? ""); + if (!override) return model; - const mappedTools = - tools?.map((tool) => { - const inputs: Record< - string, - { - type: ToolInput["type"]; - description: string; - required: boolean; - } - > = {}; - - for (const value of tool.inputs) { - if (value.paramType !== "fixed") { - inputs[value.name] = { - type: value.type, - description: value.description ?? "", - required: value.paramType === "required", - }; - } - } - - return { - name: tool.name, - description: tool.description, - parameter_definitions: inputs, - }; - }) ?? []; - - const output = tokenizer.apply_chat_template(formattedMessages, { - tokenize: false, - add_generation_prompt: !continueMessage, - tools: mappedTools.length ? mappedTools : undefined, - }); - - if (typeof output !== "string") { - throw new Error("Failed to apply chat template, the output is not a string"); - } + const { id, name, ...rest } = override; + + return { + ...model, + ...rest, + }; + }); +} - return output; +function getChatPromptRender(_m: ModelConfig): (inputs: ChatTemplateInput) => string { + // Minimal template to support legacy "completions" flow if ever used. + // We avoid any tokenizer/Jinja usage in this build. + return ({ messages, preprompt }) => { + const parts: string[] = []; + if (preprompt) parts.push(`[SYSTEM]\n${preprompt}`); + for (const msg of messages) { + const role = msg.from === "assistant" ? "ASSISTANT" : msg.from.toUpperCase(); + parts.push(`[${role}]\n${msg.content}`); + } + parts.push(`[ASSISTANT]`); + return parts.join("\n\n"); }; - return renderTemplate; } -const processModel = async (m: z.infer) => ({ +const processModel = async (m: ModelConfig) => ({ ...m, chatPromptRender: await getChatPromptRender(m), id: m.id || m.name, displayName: m.displayName || m.name, preprompt: m.prepromptUrl ? await fetch(m.prepromptUrl).then((r) => r.text()) : m.preprompt, parameters: { ...m.parameters, stop_sequences: m.parameters?.stop }, + unlisted: m.unlisted ?? false, }); const addEndpoint = (m: Awaited>) => ({ ...m, getEndpoint: async (): Promise => { - if (!m.endpoints) { - return endpointTgi({ - type: "tgi", - url: `${config.HF_API_ROOT}/${m.name}`, - accessToken: config.HF_TOKEN ?? config.HF_ACCESS_TOKEN, - weight: 1, - model: m, - }); + if (!m.endpoints || m.endpoints.length === 0) { + throw new Error("No endpoints configured. This build requires OpenAI-compatible endpoints."); } - const totalWeight = sum(m.endpoints.map((e) => e.weight)); - - let random = Math.random() * totalWeight; - - for (const endpoint of m.endpoints) { - if (random < endpoint.weight) { - const args = { ...endpoint, model: m }; - - switch (args.type) { - case "tgi": - return endpoints.tgi(args); - case "local": - return endpoints.local(args); - case "inference-client": - return endpoints.inferenceClient(args); - case "anthropic": - return endpoints.anthropic(args); - case "anthropic-vertex": - return endpoints.anthropicvertex(args); - case "bedrock": - return endpoints.bedrock(args); - case "aws": - return await endpoints.aws(args); - case "openai": - return await endpoints.openai(args); - case "llamacpp": - return endpoints.llamacpp(args); - case "ollama": - return endpoints.ollama(args); - case "vertex": - return await endpoints.vertex(args); - case "genai": - return await endpoints.genai(args); - case "cloudflare": - return await endpoints.cloudflare(args); - case "cohere": - return await endpoints.cohere(args); - case "langserve": - return await endpoints.langserve(args); - default: - // for legacy reason - return endpoints.tgi(args); - } - } - random -= endpoint.weight; + // Only support OpenAI-compatible endpoints in this build + const endpoint = m.endpoints[0]; + if (endpoint.type !== "openai") { + throw new Error("Only 'openai' endpoint type is supported in this build"); } - - throw new Error(`Failed to select endpoint`); + return await endpoints.openai({ ...endpoint, model: m }); }, }); -const inferenceApiIds = config.isHuggingChat - ? await fetchJSON<{ id: string }[]>( - "https://huggingface.co/api/models?pipeline_tag=text-generation&inference=warm&filter=conversational" - ) - .then((arr) => arr?.map((r) => r.id) || []) - .catch(() => { - logger.error("Failed to fetch inference API ids"); - return []; - }) - : []; +const inferenceApiIds: string[] = []; -export const models = await Promise.all( +const builtModels = await Promise.all( modelsRaw.map((e) => processModel(e) .then(addEndpoint) .then(async (m) => ({ ...m, hasInferenceAPI: inferenceApiIds.includes(m.id ?? m.name), + // router decoration added later + isRouter: false as boolean, })) ) ); -export type ProcessedModel = (typeof models)[number]; +// Inject a synthetic router alias ("Omni") if Arch router is configured +const archBase = (config.LLM_ROUTER_ARCH_BASE_URL || "").trim(); +const routerLabel = (config.PUBLIC_LLM_ROUTER_DISPLAY_NAME || "Omni").trim() || "Omni"; +const routerLogo = (config.PUBLIC_LLM_ROUTER_LOGO_URL || "").trim(); +const routerAliasId = (config.PUBLIC_LLM_ROUTER_ALIAS_ID || "omni").trim() || "omni"; + +let decorated = builtModels as any[]; + +if (archBase) { + // Build a minimal model config for the alias + const aliasRaw: ModelConfig = { + id: routerAliasId, + name: routerAliasId, + displayName: routerLabel, + logoUrl: routerLogo || undefined, + preprompt: "", + endpoints: [ + { + type: "openai" as const, + baseURL: openaiBaseUrl!, + }, + ], + // Keep the alias visible + unlisted: false, + } as any; + + const aliasBase = await processModel(aliasRaw); + // Create a self-referential ProcessedModel for the router endpoint + let aliasModel: any = {}; + aliasModel = { + ...aliasBase, + isRouter: true, + // getEndpoint uses the router wrapper regardless of the endpoints array + getEndpoint: async (): Promise => makeRouterEndpoint(aliasModel), + }; + + // Put alias first + decorated = [aliasModel, ...decorated]; +} + +export const models = decorated as typeof builtModels; + +export type ProcessedModel = (typeof models)[number] & { isRouter?: boolean }; // super ugly but not sure how to make typescript happier export const validModelIdSchema = z.enum(models.map((m) => m.id) as [string, ...string[]]); @@ -386,7 +343,7 @@ export const oldModels = config.OLD_MODELS transferTo: validModelIdSchema.optional(), }) ) - .parse(JSON5.parse(config.OLD_MODELS)) + .parse(JSON5.parse(sanitizeJSONEnv(config.OLD_MODELS, "[]"))) .map((m) => ({ ...m, id: m.id || m.name, displayName: m.displayName || m.name })) : []; @@ -399,13 +356,12 @@ export const validateModel = (_models: BackendModel[]) => { export const taskModel = addEndpoint( config.TASK_MODEL - ? ((models.find((m) => m.name === config.TASK_MODEL) || - (await processModel(modelConfig.parse(JSON5.parse(config.TASK_MODEL))))) ?? + ? (models.find((m) => m.name === config.TASK_MODEL || m.id === config.TASK_MODEL) ?? defaultModel) : defaultModel ); export type BackendModel = Optional< typeof defaultModel, - "preprompt" | "parameters" | "multimodal" | "unlisted" | "tools" | "hasInferenceAPI" + "preprompt" | "parameters" | "multimodal" | "unlisted" | "hasInferenceAPI" >; diff --git a/src/lib/server/router/arch.ts b/src/lib/server/router/arch.ts new file mode 100644 index 0000000000000000000000000000000000000000..8506f5978270e944387c0af65f818017c4d64393 --- /dev/null +++ b/src/lib/server/router/arch.ts @@ -0,0 +1,122 @@ +import { config } from "$lib/server/config"; +import { logger } from "$lib/server/logger"; +import type { EndpointMessage } from "../endpoints/endpoints"; +import type { Route, RouteConfig } from "./types"; +import { getRoutes } from "./policy"; + +const DEFAULT_LAST_TURNS = 16; +const PROMPT_TEMPLATE = ` +You are a helpful assistant designed to find the best suited route. +You are provided with route description within XML tags: + + + +{routes} + + + + + +{conversation} + + + +Your task is to decide which route is best suit with user intent on the conversation in XML tags. + +Follow those instructions: +1. Use prior turns to choose the best route for the current message if needed. +2. If no route match the full conversation respond with other route {"route": "other"}. +3. Analyze the route descriptions and find the best match route for user latest intent. +4. Respond only with the route name that best matches the user's request, using the exact name in the block. +Based on your analysis, provide your response in the following JSON format if you decide to match any route: +{"route": "route_name"} +`.trim(); + +function lastNTurns(arr: T[], n = DEFAULT_LAST_TURNS) { + if (!Array.isArray(arr)) return [] as T[]; + return arr.slice(-n); +} + +function toRouterPrompt(messages: EndpointMessage[], routes: Route[]) { + const simpleRoutes: RouteConfig[] = routes.map((r) => ({ + name: r.name, + description: r.description, + })); + const convo = messages + .map((m) => ({ role: m.from, content: m.content })) + .filter((m) => typeof m.content === "string" && m.content.trim() !== ""); + return PROMPT_TEMPLATE.replace("{routes}", JSON.stringify(simpleRoutes)).replace( + "{conversation}", + JSON.stringify(lastNTurns(convo)) + ); +} + +function parseRouteName(text: string): string | undefined { + if (!text) return; + try { + const obj = JSON.parse(text); + if (typeof obj?.route === "string" && obj.route.trim()) return obj.route.trim(); + } catch {} + const m = text.match(/["']route["']\s*:\s*["']([^"']+)["']/); + if (m?.[1]) return m[1].trim(); + try { + const obj = JSON.parse(text.replace(/'/g, '"')); + if (typeof obj?.route === "string" && obj.route.trim()) return obj.route.trim(); + } catch {} + return; +} + +export async function archSelectRoute( + messages: EndpointMessage[], + traceId?: string +): Promise<{ routeName: string }> { + const routes = await getRoutes(); + const prompt = toRouterPrompt(messages, routes); + + const baseURL = (config.LLM_ROUTER_ARCH_BASE_URL || "").replace(/\/$/, ""); + const archModel = config.LLM_ROUTER_ARCH_MODEL || "router/omni"; + + if (!baseURL) { + logger.warn("LLM_ROUTER_ARCH_BASE_URL not set; routing will fail over to fallback."); + return { routeName: "arch_router_failure" }; + } + + const headers: HeadersInit = { + Authorization: `Bearer ${config.OPENAI_API_KEY || config.HF_TOKEN}`, + "Content-Type": "application/json", + }; + const body = { + model: archModel, + messages: [{ role: "user", content: prompt }], + temperature: 0, + max_tokens: 16, + stream: false, + }; + + const ctrl = new AbortController(); + const timeoutMs = Number(config.LLM_ROUTER_ARCH_TIMEOUT_MS || 10000); + const to = setTimeout(() => ctrl.abort(), timeoutMs); + + try { + const resp = await fetch(`${baseURL}/chat/completions`, { + method: "POST", + headers, + body: JSON.stringify(body), + signal: ctrl.signal, + }); + clearTimeout(to); + if (!resp.ok) throw new Error(`arch-router ${resp.status}`); + const data: any = await resp.json(); + const text = (data?.choices?.[0]?.message?.content ?? "").toString().trim(); + const raw = parseRouteName(text); + + const other = config.LLM_ROUTER_OTHER_ROUTE || "casual_conversation"; + const chosen = raw === "other" ? other : raw || "casual_conversation"; + const exists = routes.some((r) => r.name === chosen); + return { routeName: exists ? chosen : "casual_conversation" }; + } catch (e: any) { + clearTimeout(to); + logger.warn({ err: String(e), traceId }, "arch router selection failed"); + return { routeName: "arch_router_failure" }; + } +} diff --git a/src/lib/server/router/endpoint.ts b/src/lib/server/router/endpoint.ts new file mode 100644 index 0000000000000000000000000000000000000000..0a30da97ae0e44a78426a4e8d690d7cc6bd3b201 --- /dev/null +++ b/src/lib/server/router/endpoint.ts @@ -0,0 +1,103 @@ +import type { Endpoint, EndpointParameters, EndpointMessage } from "../endpoints/endpoints"; +import endpoints from "../endpoints/endpoints"; +import type { ProcessedModel } from "../models"; +import { config } from "$lib/server/config"; +import { logger } from "$lib/server/logger"; +import { archSelectRoute } from "./arch"; +import { getRoutes, resolveRouteModels } from "./policy"; + +const REASONING_BLOCK_REGEX = /[\s\S]*?(?:<\/think>|$)/g; + +function stripReasoningBlocks(text: string): string { + const stripped = text.replace(REASONING_BLOCK_REGEX, ""); + return stripped === text ? text : stripped.trim(); +} + +function stripReasoningFromMessage(message: EndpointMessage): EndpointMessage { + const { reasoning: _reasoning, ...rest } = message; + const content = + typeof message.content === "string" ? stripReasoningBlocks(message.content) : message.content; + return { + ...rest, + content, + }; +} + +/** + * Create an Endpoint that performs route selection via Arch and then forwards + * to the selected model (with fallbacks) using the OpenAI-compatible endpoint. + */ +export async function makeRouterEndpoint(routerModel: ProcessedModel): Promise { + return async function routerEndpoint(params: EndpointParameters) { + const routes = await getRoutes(); + const sanitizedMessages = params.messages.map(stripReasoningFromMessage); + const { routeName } = await archSelectRoute(sanitizedMessages); + + const fallbackModel = config.LLM_ROUTER_FALLBACK_MODEL || routerModel.id; + const { candidates } = resolveRouteModels(routeName, routes, fallbackModel); + + // Helper to create an OpenAI endpoint for a specific candidate model id + async function createCandidateEndpoint(candidateModelId: string): Promise { + // Try to use the real candidate model config if present in chat-ui's model list + let modelForCall: ProcessedModel | undefined; + try { + const mod = await import("../models"); + const all = (mod as any).models as ProcessedModel[]; + modelForCall = all?.find((m) => m.id === candidateModelId || m.name === candidateModelId); + } catch (e) { + logger.warn({ err: String(e) }, "[router] failed to load models for candidate lookup"); + } + + if (!modelForCall) { + // Fallback: clone router model with candidate id + modelForCall = { + ...routerModel, + id: candidateModelId, + name: candidateModelId, + displayName: candidateModelId, + } as ProcessedModel; + } + + return endpoints.openai({ + type: "openai", + baseURL: (config.OPENAI_BASE_URL || "https://router.huggingface.co/v1").replace(/\/$/, ""), + apiKey: config.OPENAI_API_KEY || config.HF_TOKEN || "sk-", + model: modelForCall, + // Ensure streaming path is used + streamingSupported: true, + }); + } + + // Yield router metadata for immediate UI display, using the actual candidate + async function* metadataThenStream(gen: AsyncGenerator, actualModel: string) { + yield { + token: { id: 0, text: "", special: true, logprob: 0 }, + generated_text: null, + details: null, + routerMetadata: { route: routeName, model: actualModel }, + } as any; + for await (const ev of gen) yield ev; + } + + let lastErr: any = undefined; + for (const candidate of candidates) { + try { + logger.info({ route: routeName, model: candidate }, "[router] trying candidate"); + const ep = await createCandidateEndpoint(candidate); + const gen = await ep({ ...params }); + // Yield metadata with the actual candidate used + return metadataThenStream(gen, candidate); + } catch (e) { + lastErr = e; + logger.warn( + { route: routeName, model: candidate, err: String(e) }, + "[router] candidate failed" + ); + continue; + } + } + + // Exhausted all candidates — throw to signal upstream failure + throw new Error(`Routing failed for route=${routeName}: ${String(lastErr)}`); + }; +} diff --git a/src/lib/server/router/policy.ts b/src/lib/server/router/policy.ts new file mode 100644 index 0000000000000000000000000000000000000000..9d625a28cf98cdcbc27d30881c277c740b36b71a --- /dev/null +++ b/src/lib/server/router/policy.ts @@ -0,0 +1,49 @@ +import { readFile } from "node:fs/promises"; +import { config } from "$lib/server/config"; +import type { Route } from "./types"; + +let ROUTES: Route[] = []; +let loaded = false; + +export async function loadPolicy(): Promise { + const path = config.LLM_ROUTER_ROUTES_PATH; + const text = await readFile(path, "utf8"); + const arr = JSON.parse(text) as Route[]; + if (!Array.isArray(arr)) { + throw new Error("Routes config must be a flat array of routes"); + } + const seen = new Set(); + for (const r of arr) { + if (!r?.name || !r?.description || !r?.primary_model) { + throw new Error(`Invalid route entry: ${JSON.stringify(r)}`); + } + if (seen.has(r.name)) { + throw new Error(`Duplicate route name: ${r.name}`); + } + seen.add(r.name); + } + ROUTES = arr; + loaded = true; + return ROUTES; +} + +export async function getRoutes(): Promise { + if (!loaded) await loadPolicy(); + return ROUTES; +} + +export function resolveRouteModels( + routeName: string, + routes: Route[], + fallbackModel: string +): { candidates: string[] } { + if (routeName === "arch_router_failure") { + return { candidates: [fallbackModel] }; + } + const sel = + routes.find((r) => r.name === routeName) || + routes.find((r) => r.name === "casual_conversation"); + if (!sel) return { candidates: [fallbackModel] }; + const fallbacks = Array.isArray(sel.fallback_models) ? sel.fallback_models : []; + return { candidates: [sel.primary_model, ...fallbacks] }; +} diff --git a/src/lib/server/router/types.ts b/src/lib/server/router/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..af34584a9b5f4f88c44ab7550ffd490d5982d784 --- /dev/null +++ b/src/lib/server/router/types.ts @@ -0,0 +1,13 @@ +export interface Route { + name: string; + description: string; + primary_model: string; + fallback_models?: string[]; +} + +export interface RouteConfig { + name: string; + description: string; +} + +export const ROUTER_FAILURE = "arch_router_failure"; diff --git a/src/lib/server/sentenceSimilarity.ts b/src/lib/server/sentenceSimilarity.ts deleted file mode 100644 index a9cdbbeb8e16ce7c3474a5af250b9ae09afcef71..0000000000000000000000000000000000000000 --- a/src/lib/server/sentenceSimilarity.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { dot } from "@huggingface/transformers"; -import type { EmbeddingBackendModel } from "$lib/server/embeddingModels"; -import type { Embedding } from "$lib/server/embeddingEndpoints/embeddingEndpoints"; - -// see here: https://github.com/nmslib/hnswlib/blob/359b2ba87358224963986f709e593d799064ace6/README.md?plain=1#L34 -export function innerProduct(embeddingA: Embedding, embeddingB: Embedding) { - return 1.0 - dot(embeddingA, embeddingB); -} - -export async function getSentenceSimilarity( - embeddingModel: EmbeddingBackendModel, - query: string, - sentences: string[] -): Promise<{ distance: number; embedding: Embedding; idx: number }[]> { - const inputs = [ - `${embeddingModel.preQuery}${query}`, - ...sentences.map((sentence) => `${embeddingModel.prePassage}${sentence}`), - ]; - - const embeddingEndpoint = await embeddingModel.getEndpoint(); - const output = await embeddingEndpoint({ inputs }).catch((err) => { - throw Error("Failed to generate embeddings for sentence similarity", { cause: err }); - }); - - const queryEmbedding: Embedding = output[0]; - const sentencesEmbeddings: Embedding[] = output.slice(1); - - return sentencesEmbeddings.map((sentenceEmbedding, idx) => ({ - distance: innerProduct(queryEmbedding, sentenceEmbedding), - embedding: sentenceEmbedding, - idx, - })); -} diff --git a/src/lib/server/textGeneration/assistant.ts b/src/lib/server/textGeneration/assistant.ts deleted file mode 100644 index ae986c63c6d612c17d3c4c65b5c7a04c9cf95cc2..0000000000000000000000000000000000000000 --- a/src/lib/server/textGeneration/assistant.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { isURLLocal } from "../isURLLocal"; -import { config } from "$lib/server/config"; -import { collections } from "$lib/server/database"; -import type { Assistant } from "$lib/types/Assistant"; -import type { ObjectId } from "mongodb"; - -export async function processPreprompt(preprompt: string, user_message: string | undefined) { - // Replace {{today}} with formatted date - const today = new Intl.DateTimeFormat("en-US", { - weekday: "long", - day: "numeric", - month: "long", - year: "numeric", - }).format(new Date()); - preprompt = preprompt.replaceAll("{{today}}", today); - const requestRegex = /{{\s?(get|post|url)=(.*?)\s?}}/g; - - for (const match of preprompt.matchAll(requestRegex)) { - const method = match[1].toUpperCase(); - const urlString = match[2]; - try { - const url = new URL(urlString); - if ((await isURLLocal(url)) && config.ENABLE_LOCAL_FETCH !== "true") { - throw new Error("URL couldn't be fetched, it resolved to a local address."); - } - - let res; - if (method == "POST") { - res = await fetch(url.href, { - method: "POST", - body: user_message, - headers: { - "Content-Type": "text/plain", - }, - }); - } else if (method == "GET" || method == "URL") { - res = await fetch(url.href); - } else { - throw new Error("Invalid method " + method); - } - - if (!res.ok) { - throw new Error("URL couldn't be fetched, error " + res.status); - } - const text = await res.text(); - preprompt = preprompt.replaceAll(match[0], text); - } catch (e) { - preprompt = preprompt.replaceAll(match[0], (e as Error).message); - } - } - - return preprompt; -} - -export async function getAssistantById(id?: ObjectId) { - return collections.assistants - .findOne< - Pick - >({ _id: id }, { projection: { rag: 1, dynamicPrompt: 1, generateSettings: 1, tools: 1 } }) - .then((a) => a ?? undefined); -} - -export function assistantHasWebSearch(assistant?: Pick | null) { - return ( - config.ENABLE_ASSISTANTS_RAG === "true" && - !!assistant?.rag && - (assistant.rag.allowedLinks.length > 0 || - assistant.rag.allowedDomains.length > 0 || - assistant.rag.allowAllDomains) - ); -} - -export function assistantHasDynamicPrompt(assistant?: Pick) { - return config.ENABLE_ASSISTANTS_RAG === "true" && Boolean(assistant?.dynamicPrompt); -} diff --git a/src/lib/server/textGeneration/generate.ts b/src/lib/server/textGeneration/generate.ts index 3445efdc9065ef812bc752a612d57d1cbac8907c..d116dbd64bcbf0f868021147bc4ee14636ab7d7f 100644 --- a/src/lib/server/textGeneration/generate.ts +++ b/src/lib/server/textGeneration/generate.ts @@ -1,5 +1,4 @@ import { config } from "$lib/server/config"; -import type { ToolResult, Tool } from "$lib/types/Tool"; import { MessageReasoningUpdateType, MessageUpdateType, @@ -15,10 +14,17 @@ import { logger } from "../logger"; type GenerateContext = Omit & { messages: EndpointMessage[] }; export async function* generate( - { model, endpoint, conv, messages, assistant, isContinue, promptedAt }: GenerateContext, - toolResults: ToolResult[], - preprompt?: string, - tools?: Tool[] + { + model, + endpoint, + conv, + messages, + assistant, + isContinue, + promptedAt, + forceMultimodal, + }: GenerateContext, + preprompt?: string ): AsyncIterable { // reasoning mode is false by default let reasoning = false; @@ -48,11 +54,24 @@ export async function* generate( preprompt, continueMessage: isContinue, generateSettings: assistant?.generateSettings, - tools, - toolResults, - isMultimodal: model.multimodal, + // Allow user-level override to force multimodal + isMultimodal: (forceMultimodal ?? false) || model.multimodal, conversationId: conv._id, })) { + // Check if this output contains router metadata + if ( + "routerMetadata" in output && + output.routerMetadata && + output.routerMetadata.route && + output.routerMetadata.model + ) { + yield { + type: MessageUpdateType.RouterMetadata, + route: output.routerMetadata.route, + model: output.routerMetadata.model, + }; + continue; + } // text generation completed if (output.generated_text) { let interrupted = @@ -94,6 +113,7 @@ Do not use prefixes such as Response: or Answer: when answering to the user.`, generateSettings: { max_new_tokens: 1024, }, + modelId: model.id, }); finalAnswer = summary; yield { @@ -126,7 +146,6 @@ Do not use prefixes such as Response: or Answer: when answering to the user.`, type: MessageUpdateType.FinalAnswer, text: finalAnswer, interrupted, - webSources: output.webSources, }; continue; } @@ -205,7 +224,7 @@ Do not use prefixes such as Response: or Answer: when answering to the user.`, ) { lastReasoningUpdate = new Date(); try { - generateSummaryOfReasoning(reasoningBuffer).then((summary) => { + generateSummaryOfReasoning(reasoningBuffer, model.id).then((summary) => { status = summary; }); } catch (e) { diff --git a/src/lib/server/textGeneration/index.ts b/src/lib/server/textGeneration/index.ts index 0142acfbb528490e33d8917356d4f47ad183fdfa..ffa123bb584e3a51f6338472916d1f026160d5aa 100644 --- a/src/lib/server/textGeneration/index.ts +++ b/src/lib/server/textGeneration/index.ts @@ -1,15 +1,6 @@ -import { runWebSearch } from "$lib/server/websearch/runWebSearch"; import { preprocessMessages } from "../endpoints/preprocessMessages"; import { generateTitleForConversation } from "./title"; -import { - assistantHasDynamicPrompt, - assistantHasWebSearch, - getAssistantById, - processPreprompt, -} from "./assistant"; -import { getTools, runTools } from "./tools"; -import type { WebSearch } from "$lib/types/WebSearch"; import { type MessageUpdate, MessageUpdateType, @@ -18,9 +9,6 @@ import { import { generate } from "./generate"; import { mergeAsyncGenerators } from "$lib/utils/mergeAsyncGenerators"; import type { TextGenerationContext } from "./types"; -import type { ToolResult } from "$lib/types/Tool"; -import { toolHasName } from "../tools/utils"; -import directlyAnswer from "../tools/directlyAnswer"; async function* keepAlive(done: AbortSignal): AsyncGenerator { while (!done.aborted) { @@ -53,37 +41,12 @@ async function* textGenerationWithoutTitle( status: MessageUpdateStatus.Started, }; - ctx.assistant ??= await getAssistantById(ctx.conv.assistantId); - const { model, conv, messages, assistant, isContinue, webSearch, toolsPreference } = ctx; + const { conv, messages } = ctx; const convId = conv._id; - let webSearchResult: WebSearch | undefined; - - // run websearch if: - // - it's not continuing a previous message - // - AND the model doesn't support tools and websearch is selected - // - OR the assistant has websearch enabled (no tools for assistants for now) - if (!isContinue && ((webSearch && !conv.assistantId) || assistantHasWebSearch(assistant))) { - webSearchResult = yield* runWebSearch(conv, messages, assistant?.rag); - } - - let preprompt = conv.preprompt; - if (assistantHasDynamicPrompt(assistant) && preprompt) { - preprompt = await processPreprompt(preprompt, messages.at(-1)?.content); - if (messages[0].from === "system") messages[0].content = preprompt; - } - - let toolResults: ToolResult[] = []; - let tools = model.tools ? await getTools(toolsPreference, ctx.assistant) : undefined; - - if (tools) { - const toolCallsRequired = tools.some((tool) => !toolHasName(directlyAnswer.name, tool)); - if (toolCallsRequired) { - toolResults = yield* runTools(ctx, tools, preprompt); - } else tools = undefined; - } + const preprompt = conv.preprompt; - const processedMessages = await preprocessMessages(messages, webSearchResult, convId); - yield* generate({ ...ctx, messages: processedMessages }, toolResults, preprompt); + const processedMessages = await preprocessMessages(messages, convId); + yield* generate({ ...ctx, messages: processedMessages }, preprompt); done.abort(); } diff --git a/src/lib/server/textGeneration/reasoning.ts b/src/lib/server/textGeneration/reasoning.ts index 84e3e1f2a3f5df681ed1543842985f2a123e35b1..4675d8bbff37889f0df0b7cda43db8f134956b0d 100644 --- a/src/lib/server/textGeneration/reasoning.ts +++ b/src/lib/server/textGeneration/reasoning.ts @@ -1,49 +1,13 @@ import { generateFromDefaultEndpoint } from "../generateFromDefaultEndpoint"; -import { taskModel } from "../models"; import { getReturnFromGenerator } from "$lib/utils/getReturnFromGenerator"; -import { getToolOutput } from "../tools/getToolOutput"; -import type { Tool } from "$lib/types/Tool"; -import { logger } from "../logger"; -export async function generateSummaryOfReasoning(buffer: string): Promise { +export async function generateSummaryOfReasoning( + buffer: string, + modelId?: string +): Promise { let summary: string | undefined; - const messages = [ - { - from: "user" as const, - content: buffer.slice(-300), - }, - ]; - - const preprompt = `You are tasked with submitting a summary of the latest reasoning steps into a tool. Never describe results of the reasoning, only the process. Remain vague in your summary. -The text might be incomplete, try your best to summarize it in one very short sentence, starting with a gerund and ending with three points. The sentence must be very short, ideally 5 words or less.`; - - if (taskModel.tools) { - const summaryTool = { - name: "summary", - description: "Submit a summary for the submitted text", - inputs: [ - { - name: "summary", - type: "str", - description: - "The short summary of the reasoning steps. 5 words or less. Must start with a gerund.", - paramType: "required", - }, - ], - } as unknown as Tool; - - const endpoint = await taskModel.getEndpoint(); - summary = await getToolOutput({ - messages, - preprompt, - tool: summaryTool, - endpoint, - }).catch(() => { - logger.warn("Error getting tool output"); - return undefined; - }); - } + // Tools removed: no tool-based summarization path if (!summary) { summary = await getReturnFromGenerator( @@ -60,6 +24,7 @@ The text might be incomplete, try your best to summarize it in one very short se generateSettings: { max_new_tokens: 50, }, + modelId, }) ); } diff --git a/src/lib/server/textGeneration/title.ts b/src/lib/server/textGeneration/title.ts index 2a908c9f3bd5fbc1f2143ed1fa42a88c6f037bb3..875a7610e4a17bec1880853ab09806585fa17fc2 100644 --- a/src/lib/server/textGeneration/title.ts +++ b/src/lib/server/textGeneration/title.ts @@ -4,9 +4,6 @@ import { logger } from "$lib/server/logger"; import { MessageUpdateType, type MessageUpdate } from "$lib/types/MessageUpdate"; import type { Conversation } from "$lib/types/Conversation"; import { getReturnFromGenerator } from "$lib/utils/getReturnFromGenerator"; -import { taskModel } from "../models"; -import type { Tool } from "$lib/types/Tool"; -import { getToolOutput } from "../tools/getToolOutput"; export async function* generateTitleForConversation( conv: Conversation @@ -17,7 +14,8 @@ export async function* generateTitleForConversation( if (conv.title !== "New Chat" || !userMessage) return; const prompt = userMessage.content; - const title = (await generateTitle(prompt)) ?? "New Chat"; + const modelForTitle = config.TASK_MODEL?.trim() ? config.TASK_MODEL : conv.model; + const title = (await generateTitle(prompt, modelForTitle)) ?? "New Chat"; yield { type: MessageUpdateType.Title, @@ -28,67 +26,39 @@ export async function* generateTitleForConversation( } } -export async function generateTitle(prompt: string) { +export async function generateTitle(prompt: string, modelId?: string) { if (config.LLM_SUMMARIZATION !== "true") { + // When summarization is disabled, use the first five words without adding emojis return prompt.split(/\s+/g).slice(0, 5).join(" "); } - if (taskModel.tools) { - const titleTool = { - name: "title", - description: - "Submit a title for the conversation so far. Do not try to answer the user question or the tool will fail.", - inputs: [ - { - name: "title", - type: "str", - description: - "The title for the conversation. It should be 5 words or less and start with a unicode emoji relevant to the query.", - }, - ], - } as unknown as Tool; - - const endpoint = await taskModel.getEndpoint(); - const title = await getToolOutput({ - messages: [ - { - from: "user" as const, - content: prompt, - }, - ], - preprompt: - "The task is to generate conversation titles based on text snippets. You'll never answer the provided question directly, but instead summarize the user's request into a short title.", - tool: titleTool, - endpoint, - }); - - if (title) { - if (!/\p{Emoji}/u.test(title.slice(0, 3))) { - return "💬 " + title; - } - return title; - } - } + // Tools removed: no tool-based title path return await getReturnFromGenerator( generateFromDefaultEndpoint({ - messages: [{ from: "user", content: prompt }], - preprompt: - "You are a summarization AI. Summarize the user's request into a single short sentence of four words or less. Do not try to answer it, only summarize the user's query. Always start your answer with an emoji relevant to the summary", + messages: [{ from: "user", content: `Prompt to summarize: "${prompt}"` }], + preprompt: `You are a titling assistant. +Summarize the user's request into a short title of at most 4 words. +Use the SAME language as the user's message. +Do not answer the question. +Do not include the word prompt into your response. +Do not include quotes, emojis, hashtags or trailing punctuation. +Return ONLY the title text.`, generateSettings: { max_new_tokens: 30, }, + modelId, }) ) .then((summary) => { - // add an emoji if none is found in the first three characters - if (!/\p{Emoji}/u.test(summary.slice(0, 3))) { - return "💬 " + summary; - } - return summary; + const firstFive = prompt.split(/\s+/g).slice(0, 5).join(" "); + const trimmed = summary.trim(); + // Fallback: if empty, return first five words only (no emoji) + return trimmed || firstFive; }) .catch((e) => { logger.error(e); - return null; + const firstFive = prompt.split(/\s+/g).slice(0, 5).join(" "); + return firstFive; }); } diff --git a/src/lib/server/textGeneration/tools.ts b/src/lib/server/textGeneration/tools.ts deleted file mode 100644 index 2612929f0e9193ef3251794d853559697123bbef..0000000000000000000000000000000000000000 --- a/src/lib/server/textGeneration/tools.ts +++ /dev/null @@ -1,332 +0,0 @@ -import { ToolResultStatus, type ToolCall, type Tool, type ToolResult } from "$lib/types/Tool"; -import { v4 as uuidV4 } from "uuid"; -import { getCallMethod, toolFromConfigs, type BackendToolContext } from "../tools"; -import { - MessageToolUpdateType, - MessageUpdateType, - type MessageUpdate, -} from "$lib/types/MessageUpdate"; -import type { TextGenerationContext } from "./types"; - -import directlyAnswer from "../tools/directlyAnswer"; -import websearch from "../tools/web/search"; -import { z } from "zod"; -import { logger } from "../logger"; -import { extractJson, toolHasName } from "../tools/utils"; -import { mergeAsyncGenerators } from "$lib/utils/mergeAsyncGenerators"; -import { MetricsServer } from "../metrics"; -import { stringifyError } from "$lib/utils/stringifyError"; -import { collections } from "../database"; -import { ObjectId } from "mongodb"; -import type { Message } from "$lib/types/Message"; -import type { Assistant } from "$lib/types/Assistant"; -import { assistantHasWebSearch } from "./assistant"; - -export async function getTools( - toolsPreference: Array, - assistant: Pick | undefined -): Promise { - let preferences = toolsPreference; - - if (assistant) { - if (assistant?.tools?.length) { - preferences = assistant.tools; - - if (assistantHasWebSearch(assistant)) { - preferences.push(websearch._id.toString()); - } - } else { - if (assistantHasWebSearch(assistant)) { - return [websearch, directlyAnswer]; - } - return [directlyAnswer]; - } - } - - // filter based on tool preferences, add the tools that are on by default - const activeConfigTools = toolFromConfigs.filter((el) => { - if (el.isLocked && el.isOnByDefault && !assistant) return true; - return preferences?.includes(el._id.toString()) ?? (el.isOnByDefault && !assistant); - }); - - // find tool where the id is in preferences - const activeCommunityTools = await collections.tools - .find({ - _id: { $in: preferences.map((el) => new ObjectId(el)) }, - }) - .toArray() - .then((el) => el.map((el) => ({ ...el, call: getCallMethod(el) }))); - - return [...activeConfigTools, ...activeCommunityTools]; -} - -async function* callTool( - ctx: BackendToolContext, - tools: Tool[], - call: ToolCall -): AsyncGenerator { - const uuid = uuidV4(); - - const tool = tools.find((el) => toolHasName(call.name, el)); - if (!tool) { - return { call, status: ToolResultStatus.Error, message: `Could not find tool "${call.name}"` }; - } - - // Special case for directly_answer tool where we ignore - if (toolHasName(directlyAnswer.name, tool)) return; - - const startTime = Date.now(); - MetricsServer.getMetrics().tool.toolUseCount.inc({ tool: call.name }); - - yield { - type: MessageUpdateType.Tool, - subtype: MessageToolUpdateType.Call, - uuid, - call, - }; - - try { - const toolResult = yield* tool.call(call.parameters, ctx, uuid); - - yield { - type: MessageUpdateType.Tool, - subtype: MessageToolUpdateType.Result, - uuid, - result: { ...toolResult, call, status: ToolResultStatus.Success }, - }; - - MetricsServer.getMetrics().tool.toolUseDuration.observe( - { tool: call.name }, - Date.now() - startTime - ); - - await collections.tools.findOneAndUpdate({ _id: tool._id }, { $inc: { useCount: 1 } }); - - return { ...toolResult, call, status: ToolResultStatus.Success }; - } catch (error) { - MetricsServer.getMetrics().tool.toolUseCountError.inc({ tool: call.name }); - logger.error(error, `Failed while running tool ${call.name}. ${stringifyError(error)}`); - - yield { - type: MessageUpdateType.Tool, - subtype: MessageToolUpdateType.Error, - uuid, - message: - "An error occurred while calling the tool " + call.name + ": " + stringifyError(error), - }; - - return { - call, - status: ToolResultStatus.Error, - message: - "An error occurred while calling the tool " + call.name + ": " + stringifyError(error), - }; - } -} - -export async function* runTools( - ctx: TextGenerationContext, - tools: Tool[], - preprompt?: string -): AsyncGenerator { - const { endpoint, conv, messages, assistant, ip, username } = ctx; - const calls: ToolCall[] = []; - - const pickToolStartTime = Date.now(); - // append a message with the list of all available files - - const files = messages.reduce((acc, curr, idx) => { - if (curr.files) { - const prefix = (curr.from === "user" ? "input" : "ouput") + "_" + idx; - acc.push( - ...curr.files.map( - (file, fileIdx) => `${prefix}_${fileIdx}.${file?.name?.split(".")?.pop()?.toLowerCase()}` - ) - ); - } - return acc; - }, [] as string[]); - - let formattedMessages = messages.map((message, msgIdx) => { - let content = message.content; - - if (message.files && message.files.length > 0) { - content += - "\n\nAdded files: \n - " + - message.files - .map((file, fileIdx) => { - const prefix = message.from === "user" ? "input" : "output"; - const fileName = file.name.split(".").pop()?.toLowerCase(); - - return `${prefix}_${msgIdx}_${fileIdx}.${fileName}`; - }) - .join("\n - "); - } - - return { - ...message, - content, - } satisfies Message; - }); - - const fileMsg = { - id: crypto.randomUUID(), - from: "system", - content: - "Here is the list of available filenames that can be used as input for tools. Use the filenames that are in this list. \n The filename structure is as follows : {input for user|output for tool}_{message index in the conversation}_{file index in the list of files}.{file extension} \n - " + - files.join("\n - ") + - "\n\n\n", - } satisfies Message; - - // put fileMsg before last if files.length > 0 - formattedMessages = files.length - ? [...formattedMessages.slice(0, 1), fileMsg, ...formattedMessages.slice(1)] - : messages; - - const mappedTools = tools.map((tool) => ({ - ...tool, - inputs: tool.inputs.map((input) => ({ - ...input, - type: input.type === "file" ? "str" : input.type, - })), - })); - - // do the function calling bits here - for await (const output of await endpoint({ - messages: formattedMessages, - preprompt, - generateSettings: { temperature: 0.1, ...assistant?.generateSettings }, - tools: mappedTools, - conversationId: conv._id, - })) { - // model natively supports tool calls - if (output.token.toolCalls) { - calls.push(...output.token.toolCalls); - continue; - } - - // look for a code blocks of ```json and parse them - // if they're valid json, add them to the calls array - if (output.generated_text) { - try { - const rawCalls = await extractJson(output.generated_text); - const newCalls = rawCalls - .map((call) => externalToToolCall(call, tools)) - .filter((call) => call !== undefined) as ToolCall[]; - - calls.push(...newCalls); - } catch (e) { - logger.warn({ rawCall: output.generated_text, error: e }, "Error while parsing tool calls"); - } - } - } - - MetricsServer.getMetrics().tool.timeToChooseTools.observe( - { model: conv.model }, - Date.now() - pickToolStartTime - ); - - const toolContext: BackendToolContext = { conv, messages, preprompt, assistant, ip, username }; - const toolResults: (ToolResult | undefined)[] = yield* mergeAsyncGenerators( - calls.map((call) => callTool(toolContext, tools, call)) - ); - return toolResults.filter((result): result is ToolResult => result !== undefined); -} - -export function externalToToolCall(call: unknown, tools: Tool[]): ToolCall | undefined { - // Early return if invalid input - if (!isValidCallObject(call)) { - return undefined; - } - - const parsedCall = parseExternalCall(call); - if (!parsedCall) return undefined; - - const tool = tools.find((tool) => toolHasName(parsedCall.tool_name, tool)); - if (!tool) { - logger.debug( - `Model requested tool that does not exist: "${parsedCall.tool_name}". Skipping tool...` - ); - return undefined; - } - - const parametersWithDefaults: Record = {}; - - for (const input of tool.inputs) { - const value = parsedCall.parameters[input.name]; - - // Required so ensure it's there, otherwise return undefined - if (input.paramType === "required") { - if (value === undefined) { - logger.debug( - `Model requested tool "${parsedCall.tool_name}" but was missing required parameter "${input.name}". Skipping tool...` - ); - return; - } - parametersWithDefaults[input.name] = value; - continue; - } - - // Optional so use default if not there - parametersWithDefaults[input.name] = value; - - if (input.paramType === "optional") { - parametersWithDefaults[input.name] ??= input.default.toString(); - } - } - - return { - name: parsedCall.tool_name, - parameters: parametersWithDefaults, - }; -} - -// Helper functions -function isValidCallObject(call: unknown): call is Record { - return typeof call === "object" && call !== null; -} - -function parseExternalCall(callObj: Record) { - let toolCall = callObj; - if ( - isValidCallObject(callObj) && - "function" in callObj && - isValidCallObject(callObj.function) && - "_name" in callObj.function - ) { - toolCall = { - tool_name: callObj["function"]["_name"], - parameters: { - ...callObj["function"], - _name: undefined, - }, - }; - } - - const nameFields = ["tool_name", "name"] as const; - const parametersFields = ["parameters", "arguments", "parameter_definitions"] as const; - - const groupedCall = { - tool_name: "" as string, - parameters: undefined as Record | undefined, - }; - - for (const name of nameFields) { - if (toolCall[name]) { - groupedCall.tool_name = toolCall[name] as string; - } - } - - for (const name of parametersFields) { - if (toolCall[name]) { - groupedCall.parameters = toolCall[name] as Record; - } - } - - return z - .object({ - tool_name: z.string(), - parameters: z.record(z.any()), - }) - .parse(groupedCall); -} diff --git a/src/lib/server/textGeneration/types.ts b/src/lib/server/textGeneration/types.ts index 05df23cf520d748a4aaa4229ce60ddac2726b0e3..ba0c6690aae2e3973d044ffd44a21f2c813dad5e 100644 --- a/src/lib/server/textGeneration/types.ts +++ b/src/lib/server/textGeneration/types.ts @@ -9,11 +9,11 @@ export interface TextGenerationContext { endpoint: Endpoint; conv: Conversation; messages: Message[]; - assistant?: Pick; + assistant?: Pick; isContinue: boolean; - webSearch: boolean; - toolsPreference: Array; promptedAt: Date; ip: string; username?: string; + /** Force-enable multimodal handling for endpoints that support it */ + forceMultimodal?: boolean; } diff --git a/src/lib/server/tools/calculator.ts b/src/lib/server/tools/calculator.ts deleted file mode 100644 index cf52da237586258a6011b14e976e0af9eb765d1f..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/calculator.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { ConfigTool } from "$lib/types/Tool"; -import { ObjectId } from "mongodb"; -import vm from "node:vm"; - -const calculator: ConfigTool = { - _id: new ObjectId("00000000000000000000000C"), - type: "config", - description: "Calculate the result of a mathematical expression", - color: "blue", - icon: "code", - displayName: "Calculator", - name: "calculator", - endpoint: null, - inputs: [ - { - name: "equation", - type: "str", - description: - "A mathematical expression to be evaluated. The result of the expression will be returned.", - paramType: "required", - }, - ], - outputComponent: null, - outputComponentIdx: null, - showOutput: false, - async *call({ equation }) { - try { - const blocks = String(equation).split("\n"); - const query = blocks[blocks.length - 1].replace(/[^-()\d/*+.]/g, ""); - - return { - outputs: [{ calculator: `${query} = ${vm.runInNewContext(query)}` }], - }; - } catch (cause) { - throw new Error("Invalid expression", { cause }); - } - }, -}; - -export default calculator; diff --git a/src/lib/server/tools/directlyAnswer.ts b/src/lib/server/tools/directlyAnswer.ts deleted file mode 100644 index b1670f255fd3f1fa59baa886f7a418aa476586c5..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/directlyAnswer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { ConfigTool } from "$lib/types/Tool"; -import { ObjectId } from "mongodb"; - -const directlyAnswer: ConfigTool = { - _id: new ObjectId("00000000000000000000000D"), - type: "config", - description: - "Answer the user's query directly. You must use this tool before you can answer the user's query.", - color: "blue", - icon: "chat", - displayName: "Directly Answer", - isOnByDefault: true, - isLocked: true, - isHidden: true, - name: "directlyAnswer", - endpoint: null, - inputs: [], - outputComponent: null, - outputComponentIdx: null, - showOutput: false, - async *call() { - return { - outputs: [], - display: false, - }; - }, -}; - -export default directlyAnswer; diff --git a/src/lib/server/tools/getToolOutput.ts b/src/lib/server/tools/getToolOutput.ts deleted file mode 100644 index adaa012f4bcc088a7b931ca33108a167070c7f15..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/getToolOutput.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Tool } from "$lib/types/Tool"; -import { extractJson } from "./utils"; -import { externalToToolCall } from "../textGeneration/tools"; -import { logger } from "../logger"; -import type { Endpoint, EndpointMessage } from "../endpoints/endpoints"; - -interface GetToolOutputOptions { - messages: EndpointMessage[]; - tool: Tool; - preprompt?: string; - endpoint: Endpoint; - generateSettings?: { - max_new_tokens?: number; - [key: string]: unknown; - }; -} - -export async function getToolOutput({ - messages, - preprompt, - tool, - endpoint, - generateSettings = { max_new_tokens: 64 }, -}: GetToolOutputOptions): Promise { - try { - const stream = await endpoint({ - messages, - preprompt: preprompt + `\n\n Only use tool ${tool.name}.`, - tools: [tool], - generateSettings, - }); - - const calls = []; - - for await (const output of stream) { - if (output.token.toolCalls) { - calls.push(...output.token.toolCalls); - } - if (output.generated_text) { - const extractedCalls = await extractJson(output.generated_text).then((calls) => - calls.map((call) => externalToToolCall(call, [tool])).filter((call) => call !== undefined) - ); - calls.push(...extractedCalls); - } - - if (calls.length > 0) { - break; - } - } - - if (calls.length > 0) { - // Find the tool call matching our tool - const toolCall = calls.find((call) => call.name === tool.name); - - // If we found a matching call and it has parameters - if (toolCall?.parameters) { - // Get the first parameter value since most tools have a single main parameter - const firstParamValue = Object.values(toolCall.parameters)[0]; - if (typeof firstParamValue === "string") { - return firstParamValue as T; - } - } - } - - return undefined; - } catch (error) { - logger.warn(error, "Error getting tool output"); - return undefined; - } -} diff --git a/src/lib/server/tools/index.ts b/src/lib/server/tools/index.ts deleted file mode 100644 index 71b17533982cb2bce6e03fd554c420e6467e88e5..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/index.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { MessageUpdateType } from "$lib/types/MessageUpdate"; -import { - ToolColor, - ToolIcon, - ToolOutputComponents, - type BackendCall, - type BaseTool, - type ConfigTool, - type ToolInput, -} from "$lib/types/Tool"; -import type { TextGenerationContext } from "../textGeneration/types"; - -import { z } from "zod"; -import JSON5 from "json5"; -import { config } from "$lib/server/config"; - -import jp from "jsonpath"; -import calculator from "./calculator"; -import directlyAnswer from "./directlyAnswer"; -import fetchUrl from "./web/url"; -import websearch from "./web/search"; -import { callSpace, getIpToken } from "./utils"; -import { uploadFile } from "../files/uploadFile"; -import type { MessageFile } from "$lib/types/Message"; -import { sha256 } from "$lib/utils/sha256"; -import { ObjectId } from "mongodb"; -import { isValidOutputComponent, ToolOutputPaths } from "./outputs"; -import { downloadFile } from "../files/downloadFile"; -import { fileTypeFromBlob } from "file-type"; - -export type BackendToolContext = Pick< - TextGenerationContext, - "conv" | "messages" | "assistant" | "ip" | "username" -> & { preprompt?: string }; - -const IOType = z.union([z.literal("str"), z.literal("int"), z.literal("float"), z.literal("bool")]); - -const toolInputBaseSchema = z.union([ - z.object({ - name: z.string().min(1).max(80), - description: z.string().max(200).optional(), - paramType: z.literal("required"), - }), - z.object({ - name: z.string().min(1).max(80), - description: z.string().max(200).optional(), - paramType: z.literal("optional"), - default: z - .union([z.string().max(300), z.number(), z.boolean(), z.undefined()]) - .transform((val) => (val === undefined ? "" : val)), - }), - z.object({ - name: z.string().min(1).max(80), - paramType: z.literal("fixed"), - value: z - .union([z.string().max(300), z.number(), z.boolean(), z.undefined()]) - .transform((val) => (val === undefined ? "" : val)), - }), -]); - -const toolInputSchema = toolInputBaseSchema.and( - z.object({ type: IOType }).or( - z.object({ - type: z.literal("file"), - mimeTypes: z.string().min(1), - }) - ) -); - -export const editableToolSchema = z - .object({ - name: z - .string() - .regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/) // only allow letters, numbers, and underscores, and start with a letter or underscore - .min(1) - .max(40), - // only allow huggingface spaces either through namespace or direct URLs - baseUrl: z.union([ - z.string().regex(/^[^/]+\/[^/]+$/), - z - .string() - .regex(/^https:\/\/huggingface\.co\/spaces\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+$/) - .transform((url) => url.split("/").slice(-2).join("/")), - ]), - endpoint: z.string().min(1).max(100), - inputs: z.array(toolInputSchema), - outputComponent: z.string().min(1).max(100), - showOutput: z.boolean(), - displayName: z.string().min(1).max(40), - color: ToolColor, - icon: ToolIcon, - description: z.string().min(1).max(100), - }) - .transform((tool) => ({ - ...tool, - outputComponentIdx: parseInt(tool.outputComponent.split(";")[0]), - outputComponent: ToolOutputComponents.parse(tool.outputComponent.split(";")[1]), - })); -export const configTools = z - .array( - z - .object({ - name: z.string(), - description: z.string(), - endpoint: z.union([z.string(), z.null()]), - inputs: z.array(toolInputSchema), - outputComponent: ToolOutputComponents.or(z.null()), - outputComponentIdx: z.number().int().default(0), - showOutput: z.boolean(), - _id: z - .string() - .length(24) - .regex(/^[0-9a-fA-F]{24}$/) - .transform((val) => new ObjectId(val)), - baseUrl: z.string().optional(), - displayName: z.string(), - color: ToolColor, - icon: ToolIcon, - isOnByDefault: z.optional(z.literal(true)), - isLocked: z.optional(z.literal(true)), - isHidden: z.optional(z.literal(true)), - }) - .transform((val) => ({ - type: "config" as const, - ...val, - call: getCallMethod(val), - })) - ) - // add the extra hardcoded tools - .transform((val) => [...val, calculator, directlyAnswer, fetchUrl, websearch]); - -export function getCallMethod(tool: Omit): BackendCall { - return async function* (params, ctx, uuid) { - if ( - tool.endpoint === null || - !tool.baseUrl || - !tool.outputComponent || - tool.outputComponentIdx === null - ) { - throw new Error(`Tool function ${tool.name} has no endpoint`); - } - - const ipToken = await getIpToken(ctx.ip, ctx.username); - - function coerceInput(value: unknown, type: ToolInput["type"]) { - const valueStr = String(value); - switch (type) { - case "str": - return valueStr; - case "int": - return parseInt(valueStr); - case "float": - return parseFloat(valueStr); - case "bool": - return valueStr === "true"; - default: - throw new Error(`Unsupported type ${type}`); - } - } - const inputs = tool.inputs.map(async (input) => { - if (input.type === "file" && input.paramType !== "required") { - throw new Error("File inputs are always required and cannot be optional or fixed"); - } - - if (input.paramType === "fixed") { - return coerceInput(input.value, input.type); - } else if (input.paramType === "optional") { - return coerceInput(params[input.name] ?? input.default, input.type); - } else if (input.paramType === "required") { - if (params[input.name] === undefined) { - throw new Error(`Missing required input ${input.name}`); - } - - if (input.type === "file") { - // todo: parse file here ! - // structure is {input|output}-{msgIdx}-{fileIdx}-{filename} - - const filename = params[input.name]; - - if (!filename || typeof filename !== "string") { - throw new Error(`Filename is not a string`); - } - - const messages = ctx.messages; - - const msgIdx = parseInt(filename.split("_")[1]); - const fileIdx = parseInt(filename.split("_")[2]); - - if (Number.isNaN(msgIdx) || Number.isNaN(fileIdx)) { - throw Error(`Message index or file index is missing`); - } - - if (msgIdx >= messages.length) { - throw Error(`Message index ${msgIdx} is out of bounds`); - } - - const file = messages[msgIdx].files?.[fileIdx]; - - if (!file) { - throw Error(`File index ${fileIdx} is out of bounds`); - } - - const blob = await downloadFile(file.value, ctx.conv._id) - .then((file) => fetch(`data:${file.mime};base64,${file.value}`)) - .then((res) => res.blob()) - .catch((err) => { - throw Error("Failed to download file", { cause: err }); - }); - - return blob; - } else { - return coerceInput(params[input.name], input.type); - } - } - }); - - const outputs = yield* callSpace( - tool.baseUrl, - tool.endpoint, - await Promise.all(inputs), - ipToken, - uuid - ); - - if (!isValidOutputComponent(tool.outputComponent)) { - throw new Error(`Tool output component is not defined`); - } - - const { type, path } = ToolOutputPaths[tool.outputComponent]; - - if (!path || !type) { - throw new Error(`Tool output type ${tool.outputComponent} is not supported`); - } - - const files: MessageFile[] = []; - - const toolOutputs: Array> = []; - - if (outputs.length <= tool.outputComponentIdx) { - throw new Error(`Tool output component index is out of bounds`); - } - - // if its not an object, return directly - if ( - outputs[tool.outputComponentIdx] !== undefined && - typeof outputs[tool.outputComponentIdx] !== "object" - ) { - return { - outputs: [{ [tool.name + "-0"]: outputs[tool.outputComponentIdx] }], - display: tool.showOutput, - }; - } - - await Promise.all( - jp - .query(outputs[tool.outputComponentIdx], path) - .map(async (output: string | string[], idx) => { - const arrayedOutput = Array.isArray(output) ? output : [output]; - if (type === "file") { - // output files are actually URLs - - await Promise.all( - arrayedOutput.map(async (output, idx) => { - await fetch(output) - .then((res) => res.blob()) - .then(async (blob) => { - const { ext, mime } = (await fileTypeFromBlob(blob)) ?? { ext: "octet-stream" }; - - return new File( - [blob], - `${idx}-${await sha256(JSON.stringify(params))}.${ext}`, - { - type: mime, - } - ); - }) - .then((file) => uploadFile(file, ctx.conv)) - .then((file) => files.push(file)); - }) - ); - - toolOutputs.push({ - [tool.name + "-" + idx.toString()]: - `Only and always answer: 'I used the tool ${tool.displayName}, here is the result.' Don't add anything else.`, - }); - } else { - for (const output of arrayedOutput) { - toolOutputs.push({ - [tool.name + "-" + idx.toString()]: output, - }); - } - } - }) - ); - - for (const file of files) { - yield { - type: MessageUpdateType.File, - name: file.name, - sha: file.value, - mime: file.mime, - }; - } - - return { outputs: toolOutputs, display: tool.showOutput }; - }; -} - -export const toolFromConfigs = configTools.parse(JSON5.parse(config.TOOLS)) satisfies ConfigTool[]; diff --git a/src/lib/server/tools/outputs.ts b/src/lib/server/tools/outputs.ts deleted file mode 100644 index d8484c6abd22d6f29af87672747fb47f0ca06595..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/outputs.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { ToolIOType, ToolOutputComponents } from "$lib/types/Tool"; - -export const ToolOutputPaths: Record< - ToolOutputComponents, - { - type: ToolIOType; - path: string; - } -> = { - textbox: { - type: "str", - path: "$", - }, - markdown: { - type: "str", - path: "$", - }, - number: { - type: "float", - path: "$", - }, - image: { - type: "file", - path: "$.url", - }, - gallery: { - type: "file", - path: "$[*].image.url", - }, - audio: { - type: "file", - path: "$.url", - }, - video: { - type: "file", - path: "$.video.url", - }, - file: { - type: "file", - path: "$.url", - }, - json: { - type: "str", - path: "$", - }, -}; - -export const isValidOutputComponent = ( - outputComponent: string -): outputComponent is keyof typeof ToolOutputPaths => { - return Object.keys(ToolOutputPaths).includes(outputComponent); -}; diff --git a/src/lib/server/tools/utils.ts b/src/lib/server/tools/utils.ts deleted file mode 100644 index 5f496a1088d83a2994bf6d77d796145a4820081c..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/utils.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { config } from "$lib/server/config"; -import { Client } from "@gradio/client"; -import { SignJWT } from "jose"; -import JSON5 from "json5"; -import { - MessageToolUpdateType, - MessageUpdateType, - type MessageToolUpdate, -} from "$lib/types/MessageUpdate"; -import { logger } from "$lib/server/logger"; -export async function* callSpace( - name: string, - func: string, - parameters: TInput, - ipToken: string | undefined, - uuid: string -): AsyncGenerator { - class CustomClient extends Client { - fetch(input: RequestInfo | URL, init?: RequestInit): Promise { - init = init || {}; - init.headers = { - ...(init.headers || {}), - ...(ipToken ? { "X-IP-Token": ipToken } : {}), - }; - return super.fetch(input, init); - } - } - const client = await CustomClient.connect(name, { - hf_token: ipToken // dont pass the hf token if we have an ip token - ? undefined - : ((config.HF_TOKEN ?? config.HF_ACCESS_TOKEN) as unknown as `hf_${string}`), - events: ["status", "data"], - }); - - const job = client.submit(func, parameters); - - let data; - for await (const output of job) { - if (output.type === "data") { - data = output.data as TOutput; - } - if (output.type === "status") { - if (output.stage === "error") { - logger.error(output.message); - throw new Error(output.message); - } - if (output.eta) { - yield { - type: MessageUpdateType.Tool, - subtype: MessageToolUpdateType.ETA, - eta: output.eta, - uuid, - }; - } - } - } - - if (!data) { - throw new Error("No data found in tool call"); - } - - return data; -} - -export async function getIpToken(ip: string, username?: string) { - const ipTokenSecret = config.IP_TOKEN_SECRET; - if (!ipTokenSecret) { - return; - } - return await new SignJWT({ ip, user: username }) - .setProtectedHeader({ alg: "HS256" }) - .setIssuedAt() - .setExpirationTime("1m") - .sign(new TextEncoder().encode(ipTokenSecret)); -} - -export { toolHasName } from "$lib/utils/tools"; - -export async function extractJson(text: string): Promise { - const calls: string[] = []; - - let codeBlocks = Array.from(text.matchAll(/```json\n(.*?)```/gs)) - .map(([, block]) => block) - // remove trailing comma - .map((block) => block.trim().replace(/,$/, "")); - - // if there is no code block, try to find the first json object - // by trimming the string and trying to parse with JSON5 - if (codeBlocks.length === 0) { - const start = [text.indexOf("["), text.indexOf("{")] - .filter((i) => i !== -1) - .reduce((a, b) => Math.max(a, b), -Infinity); - const end = [text.lastIndexOf("]"), text.lastIndexOf("}")] - .filter((i) => i !== -1) - .reduce((a, b) => Math.min(a, b), Infinity); - - if (start === -Infinity || end === Infinity) { - return [""]; - } - - const json = text.substring(start, end + 1); - codeBlocks = [json]; - } - - // grab only the capture group from the regex match - for (const block of codeBlocks) { - // make it an array if it's not already - let call = JSON5.parse(block); - if (!Array.isArray(call)) { - call = [call]; - } - calls.push(call); - } - return calls.flat(); -} diff --git a/src/lib/server/tools/web/search.ts b/src/lib/server/tools/web/search.ts deleted file mode 100644 index 9add86667d63e551ec4ea33a8ad2c6fd6f28a875..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/web/search.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { ConfigTool } from "$lib/types/Tool"; -import { ObjectId } from "mongodb"; -import { runWebSearch } from "../../websearch/runWebSearch"; - -const websearch: ConfigTool = { - _id: new ObjectId("00000000000000000000000A"), - type: "config", - description: "Search the web for up-to-date answers to the user's query.", - color: "blue", - icon: "wikis", - displayName: "Web Search", - name: "websearch", - endpoint: null, - inputs: [ - { - name: "query", - type: "str", - description: - "A search query which will be used to fetch the most relevant snippets regarding the user's query.", - paramType: "required", - }, - ], - outputComponent: null, - outputComponentIdx: null, - showOutput: false, - async *call({ query }, { conv, assistant, messages }) { - const webSearchToolResults = yield* runWebSearch(conv, messages, assistant?.rag, String(query)); - - const webSearchContext = webSearchToolResults?.contextSources - .map(({ context }, idx) => `Source [${idx + 1}]\n${context.trim()}`) - .join("\n\n----------\n\n"); - - return { - outputs: [ - { - websearch: - webSearchContext + - "\n\nWhen answering the question, you must reference the sources you used inline by wrapping the index in brackets like this: [1]. If multiple sources are used, you must reference each one of them without commas like this: [1][2][3]. This information was fetched live from the web, today on " + - new Date().toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - }), - }, - ], - display: false, - }; - }, -}; - -export default websearch; diff --git a/src/lib/server/tools/web/url.ts b/src/lib/server/tools/web/url.ts deleted file mode 100644 index e77ff185da72c2e488772486036c09f11b512e13..0000000000000000000000000000000000000000 --- a/src/lib/server/tools/web/url.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { stringifyMarkdownElementTree } from "$lib/server/websearch/markdown/utils/stringify"; -import { scrapeUrl } from "$lib/server/websearch/scrape/scrape"; -import type { ConfigTool } from "$lib/types/Tool"; -import { ObjectId } from "mongodb"; - -const fetchUrl: ConfigTool = { - _id: new ObjectId("00000000000000000000000B"), - type: "config", - description: "Fetch the contents of a URL", - color: "blue", - icon: "cloud", - displayName: "Fetch URL", - name: "fetchUrl", - endpoint: null, - inputs: [ - { - name: "url", - type: "str", - description: "The URL of the webpage to fetch", - paramType: "required", - }, - ], - outputComponent: null, - outputComponentIdx: null, - showOutput: false, - async *call({ url }) { - const blocks = String(url).split("\n"); - const urlStr = blocks[blocks.length - 1]; - - const { title, markdownTree } = await scrapeUrl(urlStr, Infinity); - - return { - outputs: [{ title, text: stringifyMarkdownElementTree(markdownTree) }], - display: false, - }; - }, -}; - -export default fetchUrl; diff --git a/src/lib/server/usageLimits.ts b/src/lib/server/usageLimits.ts index 021e85df08c3d95f2e9ac5ec06a046930d482d1b..12d46bb2cad4ff641c84b3fdcbfb4baf3dad05c7 100644 --- a/src/lib/server/usageLimits.ts +++ b/src/lib/server/usageLimits.ts @@ -2,12 +2,17 @@ import { z } from "zod"; import { config } from "$lib/server/config"; import JSON5 from "json5"; +const sanitizeJSONEnv = (val: string, fallback: string) => { + const raw = (val ?? "").trim(); + const unquoted = raw.startsWith("`") && raw.endsWith("`") ? raw.slice(1, -1) : raw; + return unquoted || fallback; +}; + // RATE_LIMIT is the legacy way to define messages per minute limit export const usageLimitsSchema = z .object({ conversations: z.coerce.number().optional(), // how many conversations messages: z.coerce.number().optional(), // how many messages in a conversation - assistants: z.coerce.number().optional(), // how many assistants messageLength: z.coerce.number().optional(), // how long can a message be before we cut it off messagesPerMinute: z .preprocess((val) => { @@ -17,8 +22,9 @@ export const usageLimitsSchema = z return val; }, z.coerce.number().optional()) .optional(), // how many messages per minute - tools: z.coerce.number().optional(), // how many tools }) .optional(); -export const usageLimits = usageLimitsSchema.parse(JSON5.parse(config.USAGE_LIMITS)); +export const usageLimits = usageLimitsSchema.parse( + JSON5.parse(sanitizeJSONEnv(config.USAGE_LIMITS, "{}")) +); diff --git a/src/lib/server/websearch/embed/combine.ts b/src/lib/server/websearch/embed/combine.ts deleted file mode 100644 index 29b4113c2d89658e4725f94ea00f4b08153a1e0e..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/embed/combine.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { EmbeddingBackendModel } from "$lib/server/embeddingModels"; -import { getSentenceSimilarity } from "$lib/server/sentenceSimilarity"; - -/** - * Combines sentences together to reach the maximum character limit of the embedding model - * Improves performance considerably when using CPU embedding - */ -export async function getCombinedSentenceSimilarity( - embeddingModel: EmbeddingBackendModel, - query: string, - sentences: string[] -): ReturnType { - const combinedSentences = sentences.reduce<{ text: string; indices: number[] }[]>( - (acc, sentence, idx) => { - const lastSentence = acc[acc.length - 1]; - if (!lastSentence) return [{ text: sentence, indices: [idx] }]; - if (lastSentence.text.length + sentence.length < embeddingModel.chunkCharLength) { - lastSentence.text += ` ${sentence}`; - lastSentence.indices.push(idx); - return acc; - } - return [...acc, { text: sentence, indices: [idx] }]; - }, - [] - ); - - const embeddings = await getSentenceSimilarity( - embeddingModel, - query, - combinedSentences.map(({ text }) => text) - ); - - return embeddings.flatMap((embedding, idx) => { - const { indices } = combinedSentences[idx]; - return indices.map((i) => ({ ...embedding, idx: i })); - }); -} diff --git a/src/lib/server/websearch/embed/embed.ts b/src/lib/server/websearch/embed/embed.ts deleted file mode 100644 index aba7dee13bc16393450c4baf4aee75f64b0b6f85..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/embed/embed.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { MetricsServer } from "$lib/server/metrics"; -import type { WebSearchScrapedSource, WebSearchUsedSource } from "$lib/types/WebSearch"; -import type { EmbeddingBackendModel } from "../../embeddingModels"; -import { getSentenceSimilarity, innerProduct } from "../../sentenceSimilarity"; -import { MarkdownElementType, type MarkdownElement } from "../markdown/types"; -import { stringifyMarkdownElement } from "../markdown/utils/stringify"; -import { getCombinedSentenceSimilarity } from "./combine"; -import { flattenTree } from "./tree"; - -const MIN_CHARS = 3_000; -const SOFT_MAX_CHARS = 8_000; - -export async function findContextSources( - sources: WebSearchScrapedSource[], - prompt: string, - embeddingModel: EmbeddingBackendModel -) { - const startTime = Date.now(); - - const sourcesMarkdownElems = sources.map((source) => flattenTree(source.page.markdownTree)); - const markdownElems = sourcesMarkdownElems.flat(); - - // When using CPU embedding (transformersjs), join sentences together to the max character limit - // to reduce inference time - const embeddingFunc = - embeddingModel.endpoints[0].type === "transformersjs" - ? getCombinedSentenceSimilarity - : getSentenceSimilarity; - - const embeddings = await embeddingFunc( - embeddingModel, - prompt, - markdownElems - .map(stringifyMarkdownElement) - // Safety in case the stringified markdown elements are too long - // but chunking should have happened earlier - .map((elem) => elem.slice(0, embeddingModel.chunkCharLength)) - ); - - const topEmbeddings = embeddings - .sort((a, b) => a.distance - b.distance) - .filter((embedding) => markdownElems[embedding.idx].type !== MarkdownElementType.Header); - - let totalChars = 0; - const selectedMarkdownElems = new Set(); - const selectedEmbeddings: number[][] = []; - for (const embedding of topEmbeddings) { - const elem = markdownElems[embedding.idx]; - - // Ignore elements that are too similar to already selected elements - const tooSimilar = selectedEmbeddings.some( - (selectedEmbedding) => innerProduct(selectedEmbedding, embedding.embedding) < 0.01 - ); - if (tooSimilar) continue; - - // Add element - if (!selectedMarkdownElems.has(elem)) { - selectedMarkdownElems.add(elem); - selectedEmbeddings.push(embedding.embedding); - totalChars += elem.content.length; - } - - // Add element's parent (header) - if (elem.parent && !selectedMarkdownElems.has(elem.parent)) { - selectedMarkdownElems.add(elem.parent); - totalChars += elem.parent.content.length; - } - - if (totalChars > SOFT_MAX_CHARS) break; - if (totalChars > MIN_CHARS && embedding.distance > 0.25) break; - } - - const contextSources = sourcesMarkdownElems - .map((elems, idx) => { - const sourceSelectedElems = elems.filter((elem) => selectedMarkdownElems.has(elem)); - const context = sourceSelectedElems.map(stringifyMarkdownElement).join("\n"); - const source = sources[idx]; - return { ...source, context }; - }) - .filter((contextSource) => contextSource.context.length > 0); - - MetricsServer.getMetrics().webSearch.embeddingDuration.observe(Date.now() - startTime); - - return contextSources; -} diff --git a/src/lib/server/websearch/embed/tree.ts b/src/lib/server/websearch/embed/tree.ts deleted file mode 100644 index f40e4eb6f08ea2efd3f986efe03491d9f0606661..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/embed/tree.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { MarkdownElement } from "../markdown/types"; - -export function flattenTree(elem: MarkdownElement): MarkdownElement[] { - if ("children" in elem) return [elem, ...elem.children.flatMap(flattenTree)]; - return [elem]; -} diff --git a/src/lib/server/websearch/markdown/fromHtml.ts b/src/lib/server/websearch/markdown/fromHtml.ts deleted file mode 100644 index ee58d398c333143882916fbcc353569f6b1ce400..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/fromHtml.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { collapseString, sanitizeString } from "./utils/nlp"; -import { stringifyHTMLElements, stringifyHTMLElementsUnformatted } from "./utils/stringify"; -import { MarkdownElementType, tagNameMap, type HeaderElement, type MarkdownElement } from "./types"; -import type { SerializedHTMLElement } from "../scrape/types"; - -interface ConversionState { - defaultType: - | MarkdownElementType.Paragraph - | MarkdownElementType.BlockQuote - | MarkdownElementType.UnorderedListItem - | MarkdownElementType.OrderedListItem; - listDepth: number; - blockQuoteDepth: number; -} -export function htmlElementToMarkdownElements( - parent: HeaderElement, - elem: SerializedHTMLElement | string, - prevState: ConversionState = { - defaultType: MarkdownElementType.Paragraph, - listDepth: 0, - blockQuoteDepth: 0, - } -): MarkdownElement | MarkdownElement[] { - // Found text so create an element based on the previous state - if (typeof elem === "string") { - if (elem.trim().length === 0) return []; - if ( - prevState.defaultType === MarkdownElementType.UnorderedListItem || - prevState.defaultType === MarkdownElementType.OrderedListItem - ) { - return { - parent, - type: prevState.defaultType, - content: elem, - depth: prevState.listDepth, - }; - } - if (prevState.defaultType === MarkdownElementType.BlockQuote) { - return { - parent, - type: prevState.defaultType, - content: elem, - depth: prevState.blockQuoteDepth, - }; - } - return { parent, type: prevState.defaultType, content: elem }; - } - - const type = tagNameMap[elem.tagName] ?? MarkdownElementType.Paragraph; - - // Update the state based on the current element - const state: ConversionState = { ...prevState }; - if (type === MarkdownElementType.UnorderedList || type === MarkdownElementType.OrderedList) { - state.listDepth += 1; - state.defaultType = - type === MarkdownElementType.UnorderedList - ? MarkdownElementType.UnorderedListItem - : MarkdownElementType.OrderedListItem; - } - if (type === MarkdownElementType.BlockQuote) { - state.defaultType = MarkdownElementType.BlockQuote; - state.blockQuoteDepth += 1; - } - - // Headers - if (type === MarkdownElementType.Header) { - return { - parent, - type, - level: Number(elem.tagName[1]), - content: collapseString(stringifyHTMLElements(elem.content)), - children: [], - }; - } - - // Code blocks - if (type === MarkdownElementType.CodeBlock) { - return { - parent, - type, - content: sanitizeString(stringifyHTMLElementsUnformatted(elem.content)), - }; - } - - // Typical case, we want to flatten the DOM and only create elements when we see text - return elem.content.flatMap((el) => htmlElementToMarkdownElements(parent, el, state)); -} - -export function mergeAdjacentElements(elements: MarkdownElement[]): MarkdownElement[] { - return elements.reduce((acc, elem) => { - const last = acc[acc.length - 1]; - if (last && last.type === MarkdownElementType.Paragraph && last.type === elem.type) { - last.content += elem.content; - return acc; - } - return [...acc, elem]; - }, []); -} diff --git a/src/lib/server/websearch/markdown/tree.ts b/src/lib/server/websearch/markdown/tree.ts deleted file mode 100644 index dd4b652aed6c8ba06798bcf12107ffbc651da708..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/tree.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { SerializedHTMLElement } from "../scrape/types"; -import { htmlElementToMarkdownElements, mergeAdjacentElements } from "./fromHtml"; -import type { HeaderElement, MarkdownElement } from "./types"; -import { MarkdownElementType } from "./types"; -import { chunkElements } from "./utils/chunk"; - -/** - * Converts HTML elements to Markdown elements and creates a tree based on header tags - * For example: h1 [h2 [p p blockquote] h2 [h3 [...] ] ] - **/ -export function htmlToMarkdownTree( - title: string, - htmlElements: SerializedHTMLElement[], - maxCharsPerElem: number -): HeaderElement { - let parent: HeaderElement = { - type: MarkdownElementType.Header, - level: 1, - parent: null, - content: title, - children: [], - }; - - const markdownElements = chunkElements( - mergeAdjacentElements( - htmlElements.flatMap((elem) => htmlElementToMarkdownElements(parent, elem)) - ), - maxCharsPerElem - ); - - for (const elem of markdownElements) { - if (elem.type !== MarkdownElementType.Header) { - elem.parent = parent; - parent.children.push(elem); - continue; - } - - // add 1 to current level to offset for the title being level 1 - elem.level += 1; - - // Pop up header levels until reaching the same level as the current header - // or until we reach the root - inner: while (parent !== null && parent.parent !== null) { - if (parent.level < elem.level) break inner; - parent = parent.parent; - } - parent.children.push(elem); - parent = elem; - } - - // Pop up to the root - while (parent.parent !== null) { - parent = parent.parent; - } - return parent; -} - -export function removeParents(elem: T): T { - if ("children" in elem) { - return { ...elem, parent: null, children: elem.children.map((child) => removeParents(child)) }; - } - return { ...elem, parent: null }; -} diff --git a/src/lib/server/websearch/markdown/types.ts b/src/lib/server/websearch/markdown/types.ts deleted file mode 100644 index e4c99f0369c95f81cb8a83a7980602f7945a9c6b..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/types.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint-disable-next-line no-shadow */ -export enum MarkdownElementType { - Header = "HEADER", - Paragraph = "PARAGRAPH", - BlockQuote = "BLOCKQUOTE", - CodeBlock = "CODE_BLOCK", - - UnorderedList = "UNORDERED_LIST", - OrderedList = "ORDERED_LIST", - UnorderedListItem = "UNORDERED_LIST_ITEM", - OrderedListItem = "ORDERED_LIST_ITEM", -} - -interface BaseMarkdownElement { - type: T; - content: string; - parent: HeaderElement | null; -} - -export interface HeaderElement extends BaseMarkdownElement { - level: number; - children: MarkdownElement[]; -} -type ListItem = MarkdownElementType.UnorderedListItem | MarkdownElementType.OrderedListItem; -interface ListItemElement extends BaseMarkdownElement { - depth: number; -} -interface BlockQuoteElement extends BaseMarkdownElement { - depth: number; -} -interface ParagraphElement extends BaseMarkdownElement {} -interface CodeBlockElement extends BaseMarkdownElement {} - -export type MarkdownElement = - | HeaderElement - | ParagraphElement - | BlockQuoteElement - | CodeBlockElement - | ListItemElement; - -export const tagNameMap: Record = { - h1: MarkdownElementType.Header, - h2: MarkdownElementType.Header, - h3: MarkdownElementType.Header, - h4: MarkdownElementType.Header, - h5: MarkdownElementType.Header, - h6: MarkdownElementType.Header, - div: MarkdownElementType.Paragraph, - p: MarkdownElementType.Paragraph, - blockquote: MarkdownElementType.BlockQuote, - pre: MarkdownElementType.CodeBlock, - ul: MarkdownElementType.UnorderedList, - ol: MarkdownElementType.OrderedList, - li: MarkdownElementType.UnorderedListItem, -}; diff --git a/src/lib/server/websearch/markdown/utils/chunk.ts b/src/lib/server/websearch/markdown/utils/chunk.ts deleted file mode 100644 index ed035fbb01664fac5f979303c816633c5bb76953..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/utils/chunk.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { sentences as splitBySentences } from "sbd"; -import { MarkdownElementType, type MarkdownElement } from "../types"; - -export function chunkElements(elements: MarkdownElement[], maxLength: number): MarkdownElement[] { - return elements.flatMap((elem) => { - // Can't split headers because it would break the tree, and this situation should be rare - // so we just cut off the end - if (elem.type === MarkdownElementType.Header) { - return { ...elem, content: elem.content.slice(0, maxLength) }; - } - const contentChunks = enforceMaxLength(elem.content, maxLength); - return contentChunks.map((content) => ({ ...elem, content })); - }); -} - -const delimitersByPriority = ["?", "!", ".", ";", ":", ",", "|", " - ", " ", "-"]; -function enforceMaxLength(text: string, maxLength: number): string[] { - if (text.length <= maxLength) return [text].filter(Boolean); - return splitBySentences(text) - .flatMap((sentence) => { - if (sentence.length <= maxLength) return sentence; - - // Discover all necessary split points to fit the sentence within the max length - const indices: [number, number][] = []; - while ((indices.at(-1)?.[1] ?? 0) < sentence.length) { - const prevIndex = indices.at(-1)?.[1] ?? 0; - - // Remaining text fits within maxLength - if (prevIndex + maxLength >= sentence.length) { - indices.push([prevIndex, sentence.length]); - continue; - } - - const bestDelimiter = delimitersByPriority.find( - (delimiter) => sentence.lastIndexOf(delimiter, prevIndex + maxLength) !== -1 - ); - // Fallback in the unusual case that no delimiter is found - if (!bestDelimiter) { - indices.push([prevIndex, prevIndex + maxLength]); - continue; - } - - const closestDelimiter = sentence.lastIndexOf(bestDelimiter, prevIndex + maxLength); - indices.push([prevIndex, Math.max(prevIndex + 1, closestDelimiter)]); - } - - return indices.map((sliceIndices) => sentence.slice(...sliceIndices)); - }) - .reduce( - (chunks, sentence) => { - const lastChunk = chunks[chunks.length - 1]; - if (lastChunk.length + sentence.length <= maxLength) { - return [...chunks.slice(0, -1), lastChunk + sentence]; - } - return [...chunks, sentence]; - }, - [""] - ) - .filter(Boolean); -} diff --git a/src/lib/server/websearch/markdown/utils/nlp.ts b/src/lib/server/websearch/markdown/utils/nlp.ts deleted file mode 100644 index 3a49a77122d5fddeb67329a2c6cdbb8a628fb7e7..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/utils/nlp.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** Remove excess whitespace and newlines */ -export const sanitizeString = (str: string) => - str - .split("\n") - .map((s) => s.trim()) - .filter(Boolean) - .join("\n") - .replaceAll(/ +/g, " "); - -/** Collapses a string into a single line */ -export const collapseString = (str: string) => sanitizeString(str.replaceAll(/\n/g, " ")); diff --git a/src/lib/server/websearch/markdown/utils/stringify.ts b/src/lib/server/websearch/markdown/utils/stringify.ts deleted file mode 100644 index 0e6941f7182a1dd9f04efbf042f7abb1e73c98b7..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/markdown/utils/stringify.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { SerializedHTMLElement } from "../../scrape/types"; -import { MarkdownElementType, type MarkdownElement } from "../types"; - -// --- Markdown Elements --- - -/** Converts markdown element to a string with formatting */ -export function stringifyMarkdownElement(elem: MarkdownElement): string { - const content = elem.content.trim(); - if (elem.type === MarkdownElementType.Header) return `${"#".repeat(elem.level)} ${content}\n\n`; - if (elem.type === MarkdownElementType.BlockQuote) { - return `${"> ".repeat(elem.depth)}${content}\n\n`; - } - if (elem.type === MarkdownElementType.CodeBlock) return `\`\`\`\n${content}\n\`\`\`\n\n`; - - if (elem.type === MarkdownElementType.UnorderedListItem) return `- ${content}\n`; - if (elem.type === MarkdownElementType.OrderedListItem) { - const siblings = elem.parent?.children ?? [elem]; - const currentIndex = siblings.indexOf(elem); - const lastAdjacentIndex = siblings - .slice(currentIndex + 1) - .findLastIndex((child) => child.type === MarkdownElementType.OrderedListItem); - const order = currentIndex - lastAdjacentIndex + 1; - return `${order}. ${content}\n`; - } - - return `${content}\n\n`; -} - -/** Converts a tree of markdown elements to a string with formatting */ -export function stringifyMarkdownElementTree(elem: MarkdownElement): string { - const stringified = stringifyMarkdownElement(elem); - if (!("children" in elem)) return stringified; - return stringified + elem.children.map(stringifyMarkdownElementTree).join(""); -} - -// ----- HTML Elements ----- - -/** Ignores all non-inline tag types and grabs their text. Converts inline tags to markdown */ -export function stringifyHTMLElements(elems: (SerializedHTMLElement | string)[]): string { - return elems.map(stringifyHTMLElement).join("").trim(); -} - -/** Ignores all non-inline tag types and grabs their text. Converts inline tags to markdown */ -export function stringifyHTMLElement(elem: SerializedHTMLElement | string): string { - if (typeof elem === "string") return elem; - if (elem.tagName === "br") return "\n"; - - const content = elem.content.map(stringifyHTMLElement).join(""); - if (content.length === 0) return content; - - if (elem.tagName === "strong" || elem.tagName === "b") return `**${content}**`; - if (elem.tagName === "em" || elem.tagName === "i") return `*${content}*`; - if (elem.tagName === "s" || elem.tagName === "strike") return `~~${content}~~`; - - if (elem.tagName === "code" || elem.tagName === "var" || elem.tagName === "tt") { - return `\`${content}\``; - } - - if (elem.tagName === "sup") return `${content}`; - if (elem.tagName === "sub") return `${content}`; - - if (elem.tagName === "a" && content.trim().length > 0) { - const href = elem.attributes.href; - if (!href) return elem.content.map(stringifyHTMLElement).join(""); - return `[${elem.content.map(stringifyHTMLElement).join("")}](${href})`; - } - - return elem.content.map(stringifyHTMLElement).join(""); -} - -/** Grabs all text content directly, ignoring HTML tags */ -export function stringifyHTMLElementsUnformatted( - elems: (SerializedHTMLElement | string)[] -): string { - return elems.map(stringifyHTMLElementUnformatted).join(""); -} - -/** Grabs all text content directly, ignoring HTML tags */ -function stringifyHTMLElementUnformatted(elem: SerializedHTMLElement | string): string { - if (typeof elem === "string") return elem; - return elem.content.map(stringifyHTMLElementUnformatted).join(""); -} diff --git a/src/lib/server/websearch/runWebSearch.ts b/src/lib/server/websearch/runWebSearch.ts deleted file mode 100644 index 39f203b1a38ea9587d85d614849d6b130cd8caff..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/runWebSearch.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { defaultEmbeddingModel, embeddingModels } from "$lib/server/embeddingModels"; - -import type { Conversation } from "$lib/types/Conversation"; -import type { Message } from "$lib/types/Message"; -import type { WebSearch, WebSearchScrapedSource } from "$lib/types/WebSearch"; -import type { Assistant } from "$lib/types/Assistant"; -import type { MessageWebSearchUpdate } from "$lib/types/MessageUpdate"; - -import { search } from "./search/search"; -import { scrape } from "./scrape/scrape"; -import { findContextSources } from "./embed/embed"; -import { removeParents } from "./markdown/tree"; -import { - makeErrorUpdate, - makeFinalAnswerUpdate, - makeGeneralUpdate, - makeSourcesUpdate, -} from "./update"; -import { mergeAsyncGenerators } from "$lib/utils/mergeAsyncGenerators"; -import { MetricsServer } from "../metrics"; -import { logger } from "$lib/server/logger"; - -const MAX_N_PAGES_TO_SCRAPE = 8 as const; -const MAX_N_PAGES_TO_EMBED = 5 as const; - -export async function* runWebSearch( - conv: Conversation, - messages: Message[], - ragSettings?: Assistant["rag"], - query?: string -): AsyncGenerator { - const prompt = messages[messages.length - 1].content; - const createdAt = new Date(); - const updatedAt = new Date(); - - MetricsServer.getMetrics().webSearch.requestCount.inc(); - - try { - const embeddingModel = - embeddingModels.find((m) => m.id === conv.embeddingModel) ?? defaultEmbeddingModel; - if (!embeddingModel) { - throw Error(`Embedding model ${conv.embeddingModel} not available anymore`); - } - - // Search the web - const { searchQuery, pages } = yield* search(messages, ragSettings, query); - if (pages.length === 0) throw Error("No results found for this search query"); - - // Scrape pages - yield makeGeneralUpdate({ message: "Browsing search results" }); - - const allScrapedPages = yield* mergeAsyncGenerators( - pages.slice(0, MAX_N_PAGES_TO_SCRAPE).map(scrape(embeddingModel.chunkCharLength)) - ); - const scrapedPages = allScrapedPages - .filter((p): p is WebSearchScrapedSource => Boolean(p)) - .filter((p) => p.page.markdownTree.children.length > 0) - .slice(0, MAX_N_PAGES_TO_EMBED); - - if (!scrapedPages.length) { - throw Error(`No text found in the first ${MAX_N_PAGES_TO_SCRAPE} results`); - } - - // Chunk the text of each of the elements and find the most similar chunks to the prompt - yield makeGeneralUpdate({ message: "Extracting relevant information" }); - const contextSources = await findContextSources(scrapedPages, prompt, embeddingModel).then( - (ctxSources) => - ctxSources.map((source) => ({ - ...source, - page: { ...source.page, markdownTree: removeParents(source.page.markdownTree) }, - })) - ); - yield makeSourcesUpdate(contextSources); - - const webSearch: WebSearch = { - prompt, - searchQuery, - results: scrapedPages.map(({ page, ...source }) => ({ - ...source, - page: { ...page, markdownTree: removeParents(page.markdownTree) }, - })), - contextSources, - createdAt, - updatedAt, - }; - yield makeFinalAnswerUpdate(); - return webSearch; - } catch (searchError) { - const message = searchError instanceof Error ? searchError.message : String(searchError); - logger.error(message); - yield makeErrorUpdate({ message: "An error occurred", args: [message] }); - - const webSearch: WebSearch = { - prompt, - searchQuery: "", - results: [], - contextSources: [], - createdAt, - updatedAt, - }; - yield makeFinalAnswerUpdate(); - return webSearch; - } -} diff --git a/src/lib/server/websearch/scrape/parser.ts b/src/lib/server/websearch/scrape/parser.ts deleted file mode 100644 index e5502f820a711bf8022ac4f6f41baa10da9856d8..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/scrape/parser.ts +++ /dev/null @@ -1,555 +0,0 @@ -import type { SerializedHTMLElement } from "./types"; - -interface DBSCANOptions { - dataset: T[]; - epsilon?: number; - epsilonCompare?: (distance: number, epsilon: number) => boolean; - minimumPoints?: number; - distanceFunction: (a: T, b: T) => number; -} - -export function spatialParser() { - /** - * Implementation for dbscan, inlined and migrated to typescript from https://github.com/cdxOo/dbscan (MIT License) - */ - const DBSCAN = ({ - dataset, - epsilon = 1, - epsilonCompare = (dist, e) => dist < e, - minimumPoints = 2, - distanceFunction, - }: DBSCANOptions) => { - const visitedIndices: Record = {}; - const isVisited = (i: number) => visitedIndices[i]; - const markVisited = (i: number) => { - visitedIndices[i] = true; - }; - - const clusteredIndices: Record = {}; - const isClustered = (i: number) => clusteredIndices[i]; - const markClustered = (i: number) => { - clusteredIndices[i] = true; - }; - - const uniqueMerge = (targetArray: U[], sourceArray: U[]) => { - for (let i = 0; i < sourceArray.length; i += 1) { - const item = sourceArray[i]; - if (targetArray.indexOf(item) < 0) { - targetArray.push(item); - } - } - }; - - const findNeighbors = (index: number) => { - const neighbors = []; - for (let other = 0; other < dataset.length; other += 1) { - const distance = distanceFunction(dataset[index], dataset[other]); - if (epsilonCompare(distance, epsilon)) { - neighbors.push(other); - } - } - return neighbors; - }; - - const noise: number[] = []; - const addNoise = (i: number) => noise.push(i); - - const clusters: number[][] = []; - const createCluster = () => clusters.push([]) - 1; - const addIndexToCluster = (c: number, i: number) => { - clusters[c].push(i); - markClustered(i); - }; - - const expandCluster = (c: number, neighbors: number[]) => { - for (let i = 0; i < neighbors.length; i += 1) { - const neighborIndex = neighbors[i]; - if (!isVisited(neighborIndex)) { - markVisited(neighborIndex); - - const secondaryNeighbors = findNeighbors(neighborIndex); - if (secondaryNeighbors.length >= minimumPoints) { - uniqueMerge(neighbors, secondaryNeighbors); - } - } - - if (!isClustered(neighborIndex)) { - addIndexToCluster(c, neighborIndex); - } - } - }; - - dataset.forEach((_, index) => { - if (!isVisited(index)) { - markVisited(index); - - const neighbors = findNeighbors(index); - if (neighbors.length < minimumPoints) { - addNoise(index); - } else { - const clusterIndex = createCluster(); - addIndexToCluster(clusterIndex, index); - expandCluster(clusterIndex, neighbors); - } - } - }); - - return { clusters, noise }; - }; - - // ----------- - // Scraping implementation - - const IgnoredTagsList = [ - "footer", - "nav", - "aside", - "script", - "style", - "noscript", - "form", - "button", - ]; - const InlineTags = [ - "a", - "abbrv", - "span", - "address", - "time", - "acronym", - "strong", - "b", - "br", - "sub", - "sup", - "tt", - "var", - "em", - "i", - ]; - - type ReadableNode = HTMLElement; - type NodeWithRect = { - node: ReadableNode; - rect: DOMRect; - }; - - const isOnlyChild = (node: Node) => { - if (!node.parentElement) return true; - if (node.parentElement.nodeName === "body") return false; - if (node.parentElement.childNodes.length === 1) return true; - return false; - }; - - const hasValidInlineParent = (node: Node) => { - return node.parentElement && !node.parentElement.matches("div, section, article, main, body "); - }; - - const hasValidParent = (node: Node) => { - return node.parentElement && !node.parentElement.isSameNode(document.body); - }; - - const possibleCodeParents = Array.from(document.querySelectorAll("pre, p")); - const possibleTableParents = Array.from(document.querySelectorAll("table")); - const possibleListParents = Array.from(document.querySelectorAll("ul, ol")); - /** - * We want to find the highest parent of text node in the cluster. - * For example in this case:

    Text here

    - * the P tag is highest parent. - */ - const findHighestDirectParentOfReadableNode = (node: Node): HTMLElement => { - // go up the tree until the parent is no longer an only child - let parent = node.parentElement; - // if the parent is an inline tag, then go up one more level - while ( - parent && - hasValidInlineParent(parent) && - InlineTags.includes(parent?.tagName.toLowerCase()) - ) { - parent = parent.parentElement; - } - - while (parent && isOnlyChild(parent)) { - if (!hasValidParent(parent)) break; - parent = parent.parentElement; - } - - if (!parent) { - throw new Error( - "disconnected node found, this should not really be possible when traversing through the dom" - ); - } - - // if the parent is a span, code or div tag check if there is a pre tag or p tag above it - if (["span", "code", "div"].includes(parent.nodeName.toLowerCase())) { - const hasParent = possibleCodeParents.find((tag) => tag.contains(parent)) as HTMLElement; - if (hasParent) { - parent = hasParent; - } - } - - // if the parent is a li tag check if there is a ul or ol tag above it - if (parent.nodeName.toLowerCase() === "li") { - const hasParent = possibleListParents.find((tag) => tag.contains(parent)) as HTMLElement; - if (hasParent) { - parent = hasParent; - } - } - - // if the parent is a td, th, tr tag check if there is a table tag above it - if (["td", "th", "tr"].includes(parent.nodeName.toLowerCase())) { - const hasParent = possibleTableParents.find((tag) => tag.contains(parent)) as HTMLElement; - if (hasParent) { - parent = hasParent; - } - } - - return parent; - }; - const barredNodes = Array.from(document.querySelectorAll(IgnoredTagsList.join(","))); - - const doesNodePassHeuristics = (node: Node) => { - if ((node.textContent ?? "").trim().length < 10) { - return false; - } - - const parentNode = findHighestDirectParentOfReadableNode(node); - - if (parentNode && parentNode instanceof Element) { - if ( - !parentNode.checkVisibility({ - checkOpacity: true, - checkVisibilityCSS: true, - }) - ) - return false; - - const rect = parentNode.getBoundingClientRect(); - // elements that are readable usually don't have really small height or width - if (rect.width < 4 || rect.height < 4) { - return false; - } - } - - if (parentNode && parentNode instanceof Element) { - if (barredNodes.some((barredNode) => barredNode.contains(parentNode))) { - return false; - } - } - - return true; - }; - - const getAllReadableNodes = (): NodeWithRect[] => { - if (!document.body) throw new Error("Page failed to load"); - const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { - acceptNode(node) { - if (doesNodePassHeuristics(node)) { - return NodeFilter.FILTER_ACCEPT; - } else { - return NodeFilter.FILTER_SKIP; - } - }, - }); - - const readableNodes = []; - - while (treeWalker.nextNode()) { - readableNodes.push(treeWalker.currentNode as ReadableNode); - } - - /* - *

    hello

    world

    - * table is already included in the parent of the first p tag - */ - - const parentsForReadableNodes = readableNodes.map(findHighestDirectParentOfReadableNode); - const listWithOnlyParents: HTMLElement[] = []; - // find unique nodes in the parent list, a unique node is a node that is not a child of any other node in the list - for (let i = 0; i < parentsForReadableNodes.length; i++) { - const node = parentsForReadableNodes[i]; - const hasParentInList = parentsForReadableNodes.find((otherNode, idx) => { - if (i === idx) return false; - return otherNode.contains(node); - }); - listWithOnlyParents.push(hasParentInList ? hasParentInList : node); - } - - const uniqueParents = Array.from(new Set(listWithOnlyParents)); - - return uniqueParents.map((node) => { - return { - node, - rect: node.getBoundingClientRect(), - }; - }); - }; - - const distanceFunction = (a: NodeWithRect, b: NodeWithRect) => { - // we make two assumptions here which are fine to make for rects returned from getBoundingClientRect - // 1. rects are upright and not rotated - // 2. If two rects intersect, we assume distance to be 0 - let dx = 0; - let dy = 0; - const rect1 = a.rect; - const rect2 = b.rect; - // Calculate the horizontal distance - if (rect1.x + rect1.width < rect2.x) { - dx = rect2.x - (rect1.x + rect1.width); - } else if (rect2.x + rect2.width < rect1.x) { - dx = rect1.x - (rect2.x + rect2.width); - } - - // Calculate the vertical distance - if (rect1.y + rect1.height < rect2.y) { - dy = rect2.y - (rect1.y + rect1.height); - } else if (rect2.y + rect2.height < rect1.y) { - dy = rect1.y - (rect2.y + rect2.height); - } - - const distance = Math.sqrt(dx * dx + dy * dy); - // Return the Euclidean distance - return distance; - }; - /** - * Clusters nodes using dbscan - */ - const clusterReadableNodes = (nodes: NodeWithRect[]) => { - const { clusters } = DBSCAN({ - dataset: nodes, - epsilon: 28, - minimumPoints: 1, - distanceFunction, - }); - - return clusters; - }; - - const totalTextLength = (cluster: number[]) => { - return cluster - .map((t) => readableNodes[t].node.innerText?.replaceAll(/ {2}|\r\n|\n|\r/gm, "")) - .join("").length; - }; - - const approximatelyEqual = (a: number, b: number, epsilon = 1) => { - return Math.abs(a - b) < epsilon; - }; - - const getClusterBounds = (cluster: number[]) => { - const leftMostPoint = Math.min(...cluster.map((c) => readableNodes[c].rect.x)); - const topMostPoint = Math.min(...cluster.map((c) => readableNodes[c].rect.y)); - const rightMostPoint = Math.max( - ...cluster.map((c) => readableNodes[c].rect.x + readableNodes[c].rect.width) - ); - const bottomMostPoint = Math.max( - ...cluster.map((c) => readableNodes[c].rect.y + readableNodes[c].rect.height) - ); - return { - // left most element - x: leftMostPoint, - y: topMostPoint, - width: rightMostPoint - leftMostPoint, - height: bottomMostPoint - topMostPoint, - }; - }; - - const round = (num: number, decimalPlaces = 2) => { - const factor = Math.pow(10, decimalPlaces); - return Math.round(num * factor) / factor; - }; - - /** minimum distance to center of the screen */ - const clusterCentrality = (cluster: number[]) => { - const bounds = getClusterBounds(cluster); - const centerOfScreen = window.innerWidth / 2; - // the cluster contains the center of the screen - if (bounds.x < centerOfScreen && bounds.x + bounds.width > centerOfScreen) { - return 0; - } - - // the cluster is to the left of the screen - if (bounds.x + bounds.width < centerOfScreen) { - return centerOfScreen - (bounds.x + bounds.width); - } - - // the cluster is to the right of the screen - return bounds.x - centerOfScreen; - }; - /** measure of text share that belong to the cluster */ - const percentageTextShare = (cluster: number[], totalLength: number) => { - // apply an exponentially increasing penalty for centrality per 100 pixels distance from center - - return round((totalTextLength(cluster) / totalLength) * 100); - }; - - const shouldMergeClusters = (clusterA: number[], clusterB: number[]) => { - const clusterABounds = getClusterBounds(clusterA); - const clusterBBounds = getClusterBounds(clusterB); - - // A cluster is horizontally aligned if the x and width are roughly equal - const isHorizontallyAligned = - approximatelyEqual(clusterABounds.x, clusterBBounds.x, 40) && - approximatelyEqual(clusterABounds.width, clusterBBounds.width, 40); - - if (!isHorizontallyAligned) return false; - - // check the y gap between the clusters - const higherCluster = clusterABounds.y < clusterBBounds.y ? clusterABounds : clusterBBounds; - const lowerCluster = clusterABounds.y < clusterBBounds.y ? clusterBBounds : clusterABounds; - const yGap = lowerCluster.y - (higherCluster.y + higherCluster.height); - - if (approximatelyEqual(yGap, 0, 100)) return true; - }; - - const findCriticalClusters = (clusters: number[][]) => { - // merge the clusters that have similar widths and x position - - let i = 0; - while (i < clusters.length) { - const cluster = clusters[i]; - for (let j = i + 1; j < clusters.length; j++) { - const otherCluster = clusters[j]; - if (shouldMergeClusters(cluster, otherCluster)) { - cluster.push(...otherCluster); - clusters.splice(j, 1); - j -= 1; - } - } - - i++; - } - - const totalText = totalTextLength(clusters.flat()); - - // sort in descending order of text share - const clusterWithMetrics = clusters.map((cluster) => { - const centrality = clusterCentrality(cluster); - return { - cluster, - centrality, - percentageTextShare: percentageTextShare(cluster, totalText), - }; - }); - - // if there is a dominant cluster with more than 60% text share, return that - const dominantCluster = clusterWithMetrics[0]?.percentageTextShare > 60; - if (dominantCluster) return [clusterWithMetrics[0].cluster]; - - // clusters are sorted by text share after applying a penalty for centrality - const sortedClusters = clusterWithMetrics.sort((a, b) => { - const penaltyForA = Math.pow(0.9, a.centrality / 100); - const penaltyForB = Math.pow(0.9, b.centrality / 100); - const adjustedTextShareA = a.percentageTextShare * penaltyForA; - const adjustedTextShareB = b.percentageTextShare * penaltyForB; - - return adjustedTextShareB - adjustedTextShareA; - }); - - // find all clusters that are similar to the largest cluster in terms of text share - // and see if they are enough to cover at least 60% of the text share - const largeTextShareClusters = sortedClusters.filter((c) => - approximatelyEqual(c.percentageTextShare, sortedClusters[0]?.percentageTextShare, 10) - ); - - const totalTextShareOfLargeClusters = largeTextShareClusters.reduce( - (acc, cluster) => acc + cluster.percentageTextShare, - 0 - ); - - if (totalTextShareOfLargeClusters > 60) { - return largeTextShareClusters.map((c) => c.cluster); - } - - // choose clusters till the text share is greater than 60% - let totalTextShare = 0; - const criticalClusters = []; - for (const cluster of sortedClusters) { - /** Ignore clusters with less than 2%*/ - if (cluster.percentageTextShare < 2) continue; - if (totalTextShare > 60) break; - criticalClusters.push(cluster.cluster); - totalTextShare += cluster.percentageTextShare; - } - - // if the total text share is less than 60% then return an empty array - // as this website should not be particularly useful for the web search anyways - // this should almost never happen on structured website with a lot of text - if (totalTextShare < 60) { - return []; - } - - return criticalClusters; - }; - - const allowListedAttributes = ["href", "src", "alt", "title", "class", "id"]; - function serializeHTMLElement(node: Element): SerializedHTMLElement { - return { - tagName: node.tagName.toLowerCase(), - attributes: allowListedAttributes.reduce( - (acc, attr) => { - const value = node.getAttribute(attr); - if (value) { - acc[attr] = value; - } - return acc; - }, - {} as Record - ), - content: Array.from(node.childNodes).map(serializeNode).filter(Boolean), - }; - } - - function serializeNode(node: Node): SerializedHTMLElement | string { - if (node.nodeType === 1) return serializeHTMLElement(node as Element); - else if (node.nodeType === 3) return node.textContent ?? ""; - else return ""; - } - - function getPageMetadata(): { - title: string; - siteName?: string; - author?: string; - description?: string; - createdAt?: string; - updatedAt?: string; - } { - const title = document.title ?? ""; - const siteName = - document.querySelector("meta[property='og:site_name']")?.getAttribute("content") ?? undefined; - const author = - document.querySelector("meta[name='author']")?.getAttribute("content") ?? undefined; - const description = - document.querySelector("meta[name='description']")?.getAttribute("content") ?? - document.querySelector("meta[property='og:description']")?.getAttribute("content") ?? - undefined; - const createdAt = - document.querySelector("meta[property='article:published_time']")?.getAttribute("content") ?? - document.querySelector("meta[name='date']")?.getAttribute("content") ?? - undefined; - const updatedAt = - document.querySelector("meta[property='article:modified_time']")?.getAttribute("content") ?? - undefined; - - return { title, siteName, author, description, createdAt, updatedAt }; - } - - const readableNodes = getAllReadableNodes(); - const clusters = clusterReadableNodes(readableNodes); - - const criticalClusters = findCriticalClusters(clusters); - - // filter readable nodes using the above information as well as heuristics - const filteredNodes = readableNodes.filter((_, idx) => { - return criticalClusters.some((cluster) => { - return cluster.includes(idx); - }); - }); - - const elements = filteredNodes - .filter( - (node, idx, nodes) => !nodes.slice(idx + 1).some((otherNode) => node.node === otherNode.node) - ) - .map(({ node }) => serializeHTMLElement(node)); - const metadata = getPageMetadata(); - return { ...metadata, elements }; -} diff --git a/src/lib/server/websearch/scrape/playwright.ts b/src/lib/server/websearch/scrape/playwright.ts deleted file mode 100644 index 910eea043e0a1b5c9e23603b04412ac7408e0e8c..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/scrape/playwright.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { - chromium, - devices, - type Page, - type BrowserContextOptions, - type Response, - type Browser, -} from "playwright"; -import { PlaywrightBlocker } from "@cliqz/adblocker-playwright"; -import { config } from "$lib/server/config"; -import { logger } from "$lib/server/logger"; -import { onExit } from "$lib/server/exitHandler"; - -const blocker = - config.PLAYWRIGHT_ADBLOCKER === "true" - ? await PlaywrightBlocker.fromPrebuiltAdsAndTracking(fetch) - .then((blker) => { - const mostBlocked = blker.blockFonts().blockMedias().blockFrames().blockImages(); - if (config.WEBSEARCH_JAVASCRIPT === "false") return mostBlocked.blockScripts(); - return mostBlocked; - }) - .catch((err) => { - logger.error(err, "Failed to initialize PlaywrightBlocker from prebuilt lists"); - return PlaywrightBlocker.empty(); - }) - : PlaywrightBlocker.empty(); - -let browserSingleton: Promise | undefined; -async function getBrowser() { - const browser = await chromium.launch({ headless: true }); - onExit(() => browser.close()); - browser.on("disconnected", () => { - logger.warn("Browser closed"); - browserSingleton = undefined; - }); - return browser; -} - -async function getPlaywrightCtx() { - if (!browserSingleton) browserSingleton = getBrowser(); - const browser = await browserSingleton; - - const device = devices["Desktop Chrome"]; - const options: BrowserContextOptions = { - ...device, - // Increasing width improves spatial clustering accuracy - screen: { - width: 3840, - height: 1080, - }, - viewport: { - width: 3840, - height: 1080, - }, - reducedMotion: "reduce", - acceptDownloads: false, - timezoneId: "America/New_York", - locale: "en-US", - }; - return browser.newContext(options); -} - -export async function withPage( - url: string, - callback: (page: Page, response?: Response) => Promise -): Promise { - const ctx = await getPlaywrightCtx(); - - try { - const page = await ctx.newPage(); - if (config.PLAYWRIGHT_ADBLOCKER === "true") { - await blocker.enableBlockingInPage(page); - } - - await page.route("**", (route, request) => { - const requestUrl = request.url(); - if (!requestUrl.startsWith("https://")) { - logger.warn(`Blocked request to: ${requestUrl}`); - return route.abort(); - } - return route.continue(); - }); - - const res = await page - .goto(url, { waitUntil: "load", timeout: parseInt(config.WEBSEARCH_TIMEOUT) }) - .catch(() => { - console.warn( - `Failed to load page within ${parseInt(config.WEBSEARCH_TIMEOUT) / 1000}s: ${url}` - ); - }); - - return await callback(page, res ?? undefined); - } finally { - await ctx.close(); - } -} diff --git a/src/lib/server/websearch/scrape/scrape.ts b/src/lib/server/websearch/scrape/scrape.ts deleted file mode 100644 index 9f12a439fe401fcb5c10bc0c5a1f9b3b870a0530..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/scrape/scrape.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { WebSearchScrapedSource, WebSearchSource } from "$lib/types/WebSearch"; -import type { MessageWebSearchUpdate } from "$lib/types/MessageUpdate"; -import { withPage } from "./playwright"; - -import { spatialParser } from "./parser"; -import { htmlToMarkdownTree } from "../markdown/tree"; -import { timeout } from "$lib/utils/timeout"; -import { makeGeneralUpdate } from "../update"; -import { MetricsServer } from "$lib/server/metrics"; -import { logger } from "$lib/server/logger"; - -export const scrape = (maxCharsPerElem: number) => - async function* ( - source: WebSearchSource - ): AsyncGenerator { - try { - const startTime = Date.now(); - MetricsServer.getMetrics().webSearch.pageFetchCount.inc(); - - const page = await scrapeUrl(source.link, maxCharsPerElem); - - MetricsServer.getMetrics().webSearch.pageFetchDuration.observe(Date.now() - startTime); - - yield makeGeneralUpdate({ - message: "Browsing webpage", - args: [source.link], - }); - return { ...source, page }; - } catch (e) { - MetricsServer.getMetrics().webSearch.pageFetchCountError.inc(); - logger.error(e, `Error scraping webpage: ${source.link}`); - } - }; - -export async function scrapeUrl(url: string, maxCharsPerElem: number) { - return withPage(url, async (page, res) => { - if (!res) throw Error("Failed to load page"); - if (!res.ok()) throw Error(`Failed to load page: ${res.status()}`); - - // Check if it's a non-html content type that we can handle directly - // TODO: direct mappings to markdown can be added for markdown, csv and others - const contentType = res.headers()["content-type"] ?? ""; - if ( - contentType.includes("text/plain") || - contentType.includes("text/markdown") || - contentType.includes("application/json") || - contentType.includes("application/xml") || - contentType.includes("text/csv") - ) { - const title = await page.title(); - const content = await page.content(); - return { - title, - markdownTree: htmlToMarkdownTree( - title, - [{ tagName: "p", attributes: {}, content: [content] }], - maxCharsPerElem - ), - }; - } - - const scrapedOutput = await timeout(page.evaluate(spatialParser), 2000) - .then(({ elements, ...parsed }) => ({ - ...parsed, - markdownTree: htmlToMarkdownTree(parsed.title, elements, maxCharsPerElem), - })) - .catch((cause) => { - throw Error("Parsing failed", { cause }); - }); - return scrapedOutput; - }); -} diff --git a/src/lib/server/websearch/scrape/types.ts b/src/lib/server/websearch/scrape/types.ts deleted file mode 100644 index f156703584778690ec3459f96cac011b91f87275..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/scrape/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface SerializedHTMLElement { - tagName: string; - attributes: Record; - content: (SerializedHTMLElement | string)[]; -} diff --git a/src/lib/server/websearch/search/endpoints.ts b/src/lib/server/websearch/search/endpoints.ts deleted file mode 100644 index 76bf2d746b29e8841ee900957211d8ad4ed03d7c..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { WebSearchProvider, type WebSearchSource } from "$lib/types/WebSearch"; -import { config } from "$lib/server/config"; -import searchSerper from "./endpoints/serper"; -import searchSerpApi from "./endpoints/serpApi"; -import searchSerpStack from "./endpoints/serpStack"; -import searchYouApi from "./endpoints/youApi"; -import searchWebLocal from "./endpoints/webLocal"; -import searchSearxng from "./endpoints/searxng"; -import searchSearchApi from "./endpoints/searchApi"; -import searchBing from "./endpoints/bing"; - -export function getWebSearchProvider() { - if (config.YDC_API_KEY) return WebSearchProvider.YOU; - if (config.SEARXNG_QUERY_URL) return WebSearchProvider.SEARXNG; - if (config.BING_SUBSCRIPTION_KEY) return WebSearchProvider.BING; - return WebSearchProvider.GOOGLE; -} - -/** Searches the web using the first available provider, based on the env */ -export async function searchWeb(query: string): Promise { - if (config.USE_LOCAL_WEBSEARCH) return searchWebLocal(query); - if (config.SEARXNG_QUERY_URL) return searchSearxng(query); - if (config.SERPER_API_KEY) return searchSerper(query); - if (config.YDC_API_KEY) return searchYouApi(query); - if (config.SERPAPI_KEY) return searchSerpApi(query); - if (config.SERPSTACK_API_KEY) return searchSerpStack(query); - if (config.SEARCHAPI_KEY) return searchSearchApi(query); - if (config.BING_SUBSCRIPTION_KEY) return searchBing(query); - throw new Error( - "No configuration found for web search. Please set USE_LOCAL_WEBSEARCH, SEARXNG_QUERY_URL, SERPER_API_KEY, YDC_API_KEY, SERPSTACK_API_KEY, or SEARCHAPI_KEY in your environment variables." - ); -} diff --git a/src/lib/server/websearch/search/endpoints/bing.ts b/src/lib/server/websearch/search/endpoints/bing.ts deleted file mode 100644 index 91b52220477b0571def556441a9b6cd4c2ef3dff..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/bing.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { WebSearchSource } from "$lib/types/WebSearch"; -import { config } from "$lib/server/config"; - -export default async function search(query: string): Promise { - // const params = { - // q: query, - // // You can add other parameters if needed, like 'count', 'offset', etc. - // }; - - const response = await fetch( - "https://api.bing.microsoft.com/v7.0/search" + "?q=" + encodeURIComponent(query), - { - method: "GET", - headers: { - "Ocp-Apim-Subscription-Key": config.BING_SUBSCRIPTION_KEY, - "Content-type": "application/json", - }, - } - ); - - /* eslint-disable @typescript-eslint/no-explicit-any */ - const data = (await response.json()) as Record; - - if (!response.ok) { - throw new Error( - data["message"] ?? `Bing API returned error code ${response.status} - ${response.statusText}` - ); - } - - // Adapt the data structure from the Bing response to match the WebSearchSource type - const webPages = data["webPages"]?.["value"] ?? []; - return webPages.map((page: any) => ({ - title: page.name, - link: page.url, - text: page.snippet, - displayLink: page.displayUrl, - })); -} diff --git a/src/lib/server/websearch/search/endpoints/searchApi.ts b/src/lib/server/websearch/search/endpoints/searchApi.ts deleted file mode 100644 index 4784c9e5337676cd1afc1473e9e46eb3c8ad1a71..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/searchApi.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { config } from "$lib/server/config"; -import type { WebSearchSource } from "$lib/types/WebSearch"; - -export default async function search(query: string): Promise { - const response = await fetch( - `https://www.searchapi.io/api/v1/search?engine=google&hl=en&gl=us&q=${query}`, - { - method: "GET", - headers: { - Authorization: `Bearer ${config.SEARCHAPI_KEY}`, - "Content-type": "application/json", - }, - } - ); - - /* eslint-disable @typescript-eslint/no-explicit-any */ - const data = (await response.json()) as Record; - - if (!response.ok) { - throw new Error( - data["message"] ?? `SearchApi returned error code ${response.status} - ${response.statusText}` - ); - } - - return data["organic_results"] ?? []; -} diff --git a/src/lib/server/websearch/search/endpoints/searxng.ts b/src/lib/server/websearch/search/endpoints/searxng.ts deleted file mode 100644 index 029d2e666f6787df9d1ef77c1defec5420abd8a7..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/searxng.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { config } from "$lib/server/config"; -import { logger } from "$lib/server/logger"; -import type { WebSearchSource } from "$lib/types/WebSearch"; -import { isURL } from "$lib/utils/isUrl"; - -export default async function searchSearxng(query: string): Promise { - const abortController = new AbortController(); - setTimeout(() => abortController.abort(), 10000); - - // Insert the query into the URL template - let url = config.SEARXNG_QUERY_URL.replace("", query); - - // Check if "&format=json" already exists in the URL - if (!url.includes("&format=json")) { - url += "&format=json"; - } - - // Call the URL to return JSON data - const jsonResponse = await fetch(url, { - signal: abortController.signal, - }) - .then((response) => response.json() as Promise<{ results: { url: string }[] }>) - .catch((error) => { - logger.error(error, "Failed to fetch or parse JSON"); - throw new Error("Failed to fetch or parse JSON", { cause: error }); - }); - - // Extract 'url' elements from the JSON response and trim to the top 5 URLs - const urls = jsonResponse.results.slice(0, 5).map((item) => item.url); - - if (!urls.length) { - throw new Error(`Response doesn't contain any "url" elements`); - } - - // Map URLs to the correct object shape - return urls.filter(isURL).map((link) => ({ link })); -} diff --git a/src/lib/server/websearch/search/endpoints/serpApi.ts b/src/lib/server/websearch/search/endpoints/serpApi.ts deleted file mode 100644 index a30ae55dca435a789cd8437d4c215fd8e4984576..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/serpApi.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { config } from "$lib/server/config"; -import { getJson, type GoogleParameters } from "serpapi"; -import type { WebSearchSource } from "$lib/types/WebSearch"; -import { isURL } from "$lib/utils/isUrl"; - -type SerpApiResponse = { - organic_results: { - link: string; - }[]; -}; - -export default async function searchWebSerpApi(query: string): Promise { - const params = { - q: query, - hl: "en", - gl: "us", - google_domain: "google.com", - api_key: config.SERPAPI_KEY, - } satisfies GoogleParameters; - - // Show result as JSON - const response = (await getJson("google", params)) as unknown as SerpApiResponse; - - return response.organic_results.filter(({ link }) => isURL(link)); -} diff --git a/src/lib/server/websearch/search/endpoints/serpStack.ts b/src/lib/server/websearch/search/endpoints/serpStack.ts deleted file mode 100644 index 553604a5a199dbc44f0dbb8b614bb74be3bc36f5..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/serpStack.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { config } from "$lib/server/config"; -import { isURL } from "$lib/utils/isUrl"; -import type { WebSearchSource } from "$lib/types/WebSearch"; - -type SerpStackResponse = { - organic_results: { - title: string; - url: string; - snippet?: string; - }[]; - error?: string; -}; - -export default async function searchSerpStack(query: string): Promise { - const response = await fetch( - `http://api.serpstack.com/search?access_key=${config.SERPSTACK_API_KEY}&query=${query}&hl=en&gl=us`, - { headers: { "Content-type": "application/json; charset=UTF-8" } } - ); - - const data = (await response.json()) as SerpStackResponse; - - if (!response.ok) { - throw new Error( - data.error ?? `SerpStack API returned error code ${response.status} - ${response.statusText}` - ); - } - - return data.organic_results - .filter(({ url }) => isURL(url)) - .map(({ title, url, snippet }) => ({ - title, - link: url, - text: snippet ?? "", - })); -} diff --git a/src/lib/server/websearch/search/endpoints/serper.ts b/src/lib/server/websearch/search/endpoints/serper.ts deleted file mode 100644 index ffa3733607907a31c7ef26d036fd6ef99e45aaa4..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/serper.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { config } from "$lib/server/config"; -import type { WebSearchSource } from "$lib/types/WebSearch"; - -export default async function search(query: string): Promise { - const params = { - q: query, - hl: "en", - gl: "us", - }; - - const response = await fetch("https://google.serper.dev/search", { - method: "POST", - body: JSON.stringify(params), - headers: { - "x-api-key": config.SERPER_API_KEY, - "Content-type": "application/json", - }, - }); - - /* eslint-disable @typescript-eslint/no-explicit-any */ - const data = (await response.json()) as Record; - - if (!response.ok) { - throw new Error( - data["message"] ?? - `Serper API returned error code ${response.status} - ${response.statusText}` - ); - } - - return data["organic"] ?? []; -} diff --git a/src/lib/server/websearch/search/endpoints/webLocal.ts b/src/lib/server/websearch/search/endpoints/webLocal.ts deleted file mode 100644 index a847707675c5636da6d141b53e25073dcdefca9e..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/webLocal.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { JSDOM, VirtualConsole } from "jsdom"; -import { isURL } from "$lib/utils/isUrl"; -import type { WebSearchSource } from "$lib/types/WebSearch"; - -export default async function searchWebLocal(query: string): Promise { - const abortController = new AbortController(); - setTimeout(() => abortController.abort(), 10000); - - const htmlString = await fetch( - "https://www.google.com/search?hl=en&q=" + encodeURIComponent(query), - { signal: abortController.signal } - ) - .then((response) => response.text()) - .catch(); - - const virtualConsole = new VirtualConsole(); - virtualConsole.on("error", () => {}); // No-op to skip console errors. - const document = new JSDOM(htmlString ?? "", { virtualConsole }).window.document; - - // get all links - const links = document.querySelectorAll("a"); - if (!links.length) throw new Error(`webpage doesn't have any "a" element`); - - // take url that start wirth /url?q= - // and do not contain google.com links - // and strip them up to '&sa=' - const linksHref = Array.from(links) - .map((el) => el.href) - .filter((link) => link.startsWith("/url?q=") && !link.includes("google.com/")) - .map((link) => link.slice("/url?q=".length, link.indexOf("&sa="))) - .filter(isURL); - - // remove duplicate links and map links to the correct object shape - return [...new Set(linksHref)].map((link) => ({ link })); -} diff --git a/src/lib/server/websearch/search/endpoints/youApi.ts b/src/lib/server/websearch/search/endpoints/youApi.ts deleted file mode 100644 index ee11c872650bb55a792db4ae7eafef0ecd3b72b7..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/endpoints/youApi.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { config } from "$lib/server/config"; -import { isURL } from "$lib/utils/isUrl"; -import type { WebSearchSource } from "$lib/types/WebSearch"; - -interface YouWebSearch { - hits: YouSearchHit[]; - latency: number; -} - -interface YouSearchHit { - url: string; - title: string; - description: string; - snippets: string[]; -} - -export default async function searchWebYouApi(query: string): Promise { - const response = await fetch(`https://api.ydc-index.io/search?query=${query}`, { - method: "GET", - headers: { - "X-API-Key": config.YDC_API_KEY, - "Content-type": "application/json; charset=UTF-8", - }, - }); - - if (!response.ok) { - throw new Error(`You.com API returned error code ${response.status} - ${response.statusText}`); - } - - const data = (await response.json()) as YouWebSearch; - const formattedResultsWithSnippets = data.hits - .filter(({ url }) => isURL(url)) - .map(({ title, url, snippets }) => ({ - title, - link: url, - text: snippets?.join("\n") || "", - })) - .sort((a, b) => b.text.length - a.text.length); // desc order by text length - - return formattedResultsWithSnippets; -} diff --git a/src/lib/server/websearch/search/generateQuery.ts b/src/lib/server/websearch/search/generateQuery.ts deleted file mode 100644 index 66247a1adbf68a2c9f6c928cac240f703e1ae71b..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/generateQuery.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Message } from "$lib/types/Message"; -import { format } from "date-fns"; -import type { EndpointMessage } from "../../endpoints/endpoints"; -import { generateFromDefaultEndpoint } from "../../generateFromDefaultEndpoint"; -import { getReturnFromGenerator } from "$lib/utils/getReturnFromGenerator"; -import { taskModel } from "$lib/server/models"; -import type { Tool } from "$lib/types/Tool"; -import { getToolOutput } from "$lib/server/tools/getToolOutput"; - -export async function generateQuery(messages: Message[]) { - const currentDate = format(new Date(), "MMMM d, yyyy"); - - if (taskModel.tools) { - const webSearchTool = { - name: "web_search", - description: "Search the web for information", - inputs: [ - { - name: "query", - type: "str", - description: "The query to search the web for", - paramType: "required", - }, - ], - } as unknown as Tool; - - const endpoint = await taskModel.getEndpoint(); - const query = await getToolOutput({ - messages, - preprompt: `The user wants you to search the web for information. Give a relevant google search query to answer the question. Answer with only the query. Today is ${currentDate}`, - tool: webSearchTool, - endpoint, - }); - - if (query) { - return query; - } - } - - const userMessages = messages.filter(({ from }) => from === "user"); - const previousUserMessages = userMessages.slice(0, -1); - - const lastMessage = userMessages.slice(-1)[0]; - - const convQuery: Array = [ - { - from: "user", - content: - (previousUserMessages.length > 0 - ? `Previous questions: \n${previousUserMessages - .map(({ content }) => `- ${content}`) - .join("\n")}` - : "") + - "\n\nCurrent Question: " + - lastMessage.content, - }, - ]; - - const webQuery = await getReturnFromGenerator( - generateFromDefaultEndpoint({ - messages: convQuery, - preprompt: `The user wants you to search the web for information. Give a relevant google search query to answer the question. Answer with only the query. Today is ${currentDate}. The conversation follows: \n`, - generateSettings: { - max_new_tokens: 30, - }, - }) - ); - - return webQuery.trim().replace(/^"|"$/g, ""); -} diff --git a/src/lib/server/websearch/search/search.ts b/src/lib/server/websearch/search/search.ts deleted file mode 100644 index 366819b0be06cb6d4af951aaa8d4c897b49ce2b3..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/search/search.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { WebSearchSource } from "$lib/types/WebSearch"; -import type { Message } from "$lib/types/Message"; -import type { Assistant } from "$lib/types/Assistant"; -import { getWebSearchProvider, searchWeb } from "./endpoints"; -import { generateQuery } from "./generateQuery"; -import { isURLStringLocal } from "$lib/server/isURLLocal"; -import { isURL } from "$lib/utils/isUrl"; - -import z from "zod"; -import JSON5 from "json5"; -import { config } from "$lib/server/config"; -import { makeGeneralUpdate } from "../update"; -import type { MessageWebSearchUpdate } from "$lib/types/MessageUpdate"; - -const listSchema = z.array(z.string()).default([]); -const allowList = listSchema.parse(JSON5.parse(config.WEBSEARCH_ALLOWLIST)); -const blockList = listSchema.parse(JSON5.parse(config.WEBSEARCH_BLOCKLIST)); - -export async function* search( - messages: Message[], - ragSettings?: Assistant["rag"], - query?: string -): AsyncGenerator< - MessageWebSearchUpdate, - { searchQuery: string; pages: WebSearchSource[] }, - undefined -> { - if (ragSettings && ragSettings?.allowedLinks.length > 0) { - yield makeGeneralUpdate({ message: "Using links specified in Assistant" }); - return { - searchQuery: "", - pages: await directLinksToSource(ragSettings.allowedLinks).then(filterByBlockList), - }; - } - - const searchQuery = query ?? (await generateQuery(messages)); - yield makeGeneralUpdate({ message: `Searching ${getWebSearchProvider()}`, args: [searchQuery] }); - - // handle the global and (optional) rag lists - if (ragSettings && ragSettings?.allowedDomains.length > 0) { - yield makeGeneralUpdate({ message: "Filtering on specified domains" }); - } - const filters = buildQueryFromSiteFilters( - [...(ragSettings?.allowedDomains ?? []), ...allowList], - blockList - ); - - const searchQueryWithFilters = `${filters} ${searchQuery}`; - const searchResults = await searchWeb(searchQueryWithFilters).then(filterByBlockList); - - return { - searchQuery: searchQueryWithFilters, - pages: searchResults, - }; -} - -// ---------- -// Utils -function filterByBlockList(results: WebSearchSource[]): WebSearchSource[] { - return results.filter((result) => !blockList.some((blocked) => result.link.includes(blocked))); -} - -function buildQueryFromSiteFilters(allow: string[], block: string[]) { - return ( - allow.map((item) => "site:" + item).join(" OR ") + - " " + - block.map((item) => "-site:" + item).join(" ") - ); -} - -async function directLinksToSource(links: string[]): Promise { - if (config.ENABLE_LOCAL_FETCH !== "true") { - const localLinks = await Promise.all(links.map(isURLStringLocal)); - links = links.filter((_, index) => !localLinks[index]); - } - - return links.filter(isURL).map((link) => ({ - link, - title: "", - text: [""], - })); -} diff --git a/src/lib/server/websearch/update.ts b/src/lib/server/websearch/update.ts deleted file mode 100644 index 9a44779f799ca1550d8c88d06082606bede8ce45..0000000000000000000000000000000000000000 --- a/src/lib/server/websearch/update.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { WebSearchSource } from "$lib/types/WebSearch"; -import { - MessageUpdateType, - MessageWebSearchUpdateType, - type MessageWebSearchErrorUpdate, - type MessageWebSearchFinishedUpdate, - type MessageWebSearchGeneralUpdate, - type MessageWebSearchSourcesUpdate, -} from "$lib/types/MessageUpdate"; - -export function makeGeneralUpdate( - update: Pick -): MessageWebSearchGeneralUpdate { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Update, - ...update, - }; -} - -export function makeErrorUpdate( - update: Pick -): MessageWebSearchErrorUpdate { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Error, - ...update, - }; -} - -export function makeSourcesUpdate(sources: WebSearchSource[]): MessageWebSearchSourcesUpdate { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Sources, - message: "sources", - sources: sources.map(({ link, title }) => ({ link, title })), - }; -} - -export function makeFinalAnswerUpdate(): MessageWebSearchFinishedUpdate { - return { - type: MessageUpdateType.WebSearch, - subtype: MessageWebSearchUpdateType.Finished, - }; -} diff --git a/src/lib/shareConversation.ts b/src/lib/shareConversation.ts deleted file mode 100644 index 8c11fb17660f7e90c597a1c3e39d2195e20c742e..0000000000000000000000000000000000000000 --- a/src/lib/shareConversation.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { base } from "$app/paths"; -import { ERROR_MESSAGES, error } from "$lib/stores/errors"; -import { share } from "./utils/share"; -import { page } from "$app/state"; - -export async function shareConversation(id: string, title: string) { - try { - if (id.length === 7) { - const shareUrl = `${ - page.data.publicConfig.PUBLIC_SHARE_PREFIX || - `${page.data.publicConfig.PUBLIC_ORIGIN || page.url.origin}${base}` - }/r/${id}`; - await share(shareUrl, title, true); - } else { - const res = await fetch(`${base}/conversation/${id}/share`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!res.ok) { - error.set("Error while sharing conversation, try again."); - console.error("Error while sharing conversation: " + (await res.text())); - return; - } - - const { shareId } = await res.json(); - - const shareUrl = `${ - page.data.publicConfig.PUBLIC_SHARE_PREFIX || - `${page.data.publicConfig.PUBLIC_ORIGIN || page.url.origin}${base}` - }/r/${shareId}`; - - await share(shareUrl, title, true); - } - } catch (err) { - error.set(ERROR_MESSAGES.default); - console.error(err); - } -} diff --git a/src/lib/stores/settings.ts b/src/lib/stores/settings.ts index 0d5b6121960ce0de7838fc4dde56a22bb329fd34..1b99ce02f4dd2ada5a8af1fb50794f0d1266ab6b 100644 --- a/src/lib/stores/settings.ts +++ b/src/lib/stores/settings.ts @@ -2,22 +2,20 @@ import { browser } from "$app/environment"; import { invalidate } from "$app/navigation"; import { base } from "$app/paths"; import { UrlDependency } from "$lib/types/UrlDependency"; -import type { ObjectId } from "mongodb"; import { getContext, setContext } from "svelte"; import { type Writable, writable, get } from "svelte/store"; type SettingsStore = { shareConversationsWithModelAuthors: boolean; - hideEmojiOnSidebar: boolean; - ethicsModalAccepted: boolean; - ethicsModalAcceptedAt: Date | null; + welcomeModalSeen: boolean; + welcomeModalSeenAt: Date | null; activeModel: string; customPrompts: Record; + multimodalOverrides: Record; recentlySaved: boolean; - assistants: Array; - tools?: Array; disableStream: boolean; directPaste: boolean; + hidePromptExamples: Record; }; type SettingsStoreWritable = Writable & { diff --git a/src/lib/stores/shareModal.ts b/src/lib/stores/shareModal.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c3fe0c78b091c0f663676046eee9ee7cd314732 --- /dev/null +++ b/src/lib/stores/shareModal.ts @@ -0,0 +1,13 @@ +import { writable } from "svelte/store"; + +function createShareModalStore() { + const { subscribe, set } = writable(false); + + return { + subscribe, + open: () => set(true), + close: () => set(false), + }; +} + +export const shareModal = createShareModalStore(); diff --git a/src/lib/stores/webSearchParameters.ts b/src/lib/stores/webSearchParameters.ts deleted file mode 100644 index fd088a60621090930e9600c6086380afd2b412e8..0000000000000000000000000000000000000000 --- a/src/lib/stores/webSearchParameters.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { writable } from "svelte/store"; -export interface WebSearchParameters { - useSearch: boolean; - nItems: number; -} -export const webSearchParameters = writable({ - useSearch: false, - nItems: 5, -}); diff --git a/src/lib/switchTheme.ts b/src/lib/switchTheme.ts index fef1991bd9d2cfc24b846ee2ab603f9f814231a5..178e1f0aa26162899895e1bcb947ded4f198eb8f 100644 --- a/src/lib/switchTheme.ts +++ b/src/lib/switchTheme.ts @@ -1,14 +1,86 @@ -export function switchTheme() { +export type ThemePreference = "light" | "dark" | "system"; + +function setMetaThemeColor(isDark: boolean) { + const metaTheme = document.querySelector('meta[name="theme-color"]') as HTMLMetaElement | null; + if (!metaTheme) return; + metaTheme.setAttribute("content", isDark ? "rgb(26, 36, 50)" : "rgb(249, 250, 251)"); +} + +function applyDarkClass(isDark: boolean) { const { classList } = document.querySelector("html") as HTMLElement; - const metaTheme = document.querySelector('meta[name="theme-color"]') as HTMLMetaElement; - - if (classList.contains("dark")) { - classList.remove("dark"); - metaTheme.setAttribute("content", "rgb(249, 250, 251)"); - localStorage.theme = "light"; - } else { - classList.add("dark"); - metaTheme.setAttribute("content", "rgb(26, 36, 50)"); - localStorage.theme = "dark"; + if (isDark) classList.add("dark"); + else classList.remove("dark"); + setMetaThemeColor(isDark); +} + +export function getThemePreference(): ThemePreference { + const raw = typeof localStorage !== "undefined" ? localStorage.getItem("theme") : null; + if (raw === "light" || raw === "dark" || raw === "system") return raw; + return "system"; +} + +/** + * Explicitly set the theme preference and apply it immediately. + * - "light": force light + * - "dark": force dark + * - "system": follow the OS preference + */ +export function setTheme(preference: ThemePreference) { + try { + localStorage.theme = preference; + } catch (_err) { + void 0; // ignore write errors } + + const mql = window.matchMedia("(prefers-color-scheme: dark)"); + const resolve = () => + applyDarkClass(preference === "dark" || (preference === "system" && mql.matches)); + + // Apply now + resolve(); + + // If following system, listen for changes; otherwise remove listener + const listener = () => resolve(); + // Store on window to allow replacing listener later + const key = "__theme_mql_listener" as const; + const w = window as unknown as { + [key: string]: ((this: MediaQueryList, ev: MediaQueryListEvent) => void) | undefined; + }; + const existing = w[key]; + if (existing) { + try { + mql.removeEventListener("change", existing); + } catch (_err) { + // older Safari compatibility + const legacy = ( + mql as unknown as { + removeListener?: (l: (this: MediaQueryList, ev: MediaQueryListEvent) => void) => void; + } + ).removeListener; + legacy?.(existing); + } + w[key] = undefined; + } + if (preference === "system") { + try { + mql.addEventListener("change", listener); + } catch (_err) { + // older Safari compatibility + const legacy = ( + mql as unknown as { + addListener?: (l: (this: MediaQueryList, ev: MediaQueryListEvent) => void) => void; + } + ).addListener; + legacy?.(listener); + } + w[key] = listener; + } +} + +// Backward-compatible toggle used by the sidebar button +export function switchTheme() { + const html = document.querySelector("html") as HTMLElement; + const isDark = html.classList.contains("dark"); + const next: ThemePreference = isDark ? "light" : "dark"; + setTheme(next); } diff --git a/src/lib/types/Assistant.ts b/src/lib/types/Assistant.ts index 805c38041d1424598b9b4f42f2436a04f815bdd2..5c176bdfafda231ed4dcd1f42fec1d21f69d3f91 100644 --- a/src/lib/types/Assistant.ts +++ b/src/lib/types/Assistant.ts @@ -15,11 +15,7 @@ export interface Assistant extends Timestamps { preprompt: string; userCount?: number; review: ReviewStatus; - rag?: { - allowAllDomains: boolean; - allowedDomains: string[]; - allowedLinks: string[]; - }; + // Web search / RAG removed in this build generateSettings?: { temperature?: number; top_p?: number; @@ -29,11 +25,7 @@ export interface Assistant extends Timestamps { dynamicPrompt?: boolean; searchTokens: string[]; last24HoursCount: number; - tools?: string[]; } // eslint-disable-next-line no-shadow -export enum SortKey { - POPULAR = "popular", - TRENDING = "trending", -} +// Removed duplicate unused SortKey enum (shared enum exists elsewhere) diff --git a/src/lib/types/ConvSidebar.ts b/src/lib/types/ConvSidebar.ts index 55c57ad5992eeac6a5e1f5ab9240459ef28ccecb..bbba9abc56d1c0a16cb5c664aa86cf1878a627f1 100644 --- a/src/lib/types/ConvSidebar.ts +++ b/src/lib/types/ConvSidebar.ts @@ -5,6 +5,5 @@ export interface ConvSidebar { title: string; updatedAt: Date; model?: string; - assistantId?: ObjectId | string; avatarUrl?: string | Promise; } diff --git a/src/lib/types/Conversation.ts b/src/lib/types/Conversation.ts index a1f97978d90e18c8ae961296164a27d832638b2d..1b9523f7a6f8d122f44d6b304616b2d55fe1994d 100644 --- a/src/lib/types/Conversation.ts +++ b/src/lib/types/Conversation.ts @@ -11,7 +11,6 @@ export interface Conversation extends Timestamps { userId?: User["_id"]; model: string; - embeddingModel: string; title: string; rootMessageId?: Message["id"]; diff --git a/src/lib/types/Message.ts b/src/lib/types/Message.ts index 171dc5ece9f2db494b4e02d062dd4795138b0231..debda2d73659feb13effb8be9fb86a3d03696971 100644 --- a/src/lib/types/Message.ts +++ b/src/lib/types/Message.ts @@ -1,6 +1,5 @@ import type { MessageUpdate } from "./MessageUpdate"; import type { Timestamps } from "./Timestamps"; -import type { WebSearch } from "./WebSearch"; import type { v4 } from "uuid"; export type Message = Partial & { @@ -8,8 +7,6 @@ export type Message = Partial & { id: ReturnType; content: string; updates?: MessageUpdate[]; - webSearchId?: WebSearch["_id"]; // legacy version - webSearch?: WebSearch; reasoning?: string; score?: -1 | 0 | 1; @@ -20,6 +17,12 @@ export type Message = Partial & { files?: MessageFile[]; interrupted?: boolean; + // Router metadata when using llm-router + routerMetadata?: { + route: string; + model: string; + }; + // needed for conversation trees ancestors?: Message["id"][]; diff --git a/src/lib/types/MessageUpdate.ts b/src/lib/types/MessageUpdate.ts index 17a953289dc831524966f5f465c040123a047782..7759e1b99f3238137d373347523df9a9db63013a 100644 --- a/src/lib/types/MessageUpdate.ts +++ b/src/lib/types/MessageUpdate.ts @@ -1,25 +1,20 @@ -import type { WebSearchSource } from "$lib/types/WebSearch"; -import type { ToolCall, ToolResult } from "$lib/types/Tool"; - export type MessageUpdate = | MessageStatusUpdate | MessageTitleUpdate - | MessageToolUpdate - | MessageWebSearchUpdate | MessageStreamUpdate | MessageFileUpdate | MessageFinalAnswerUpdate - | MessageReasoningUpdate; + | MessageReasoningUpdate + | MessageRouterMetadataUpdate; export enum MessageUpdateType { Status = "status", Title = "title", - Tool = "tool", - WebSearch = "webSearch", Stream = "stream", File = "file", FinalAnswer = "finalAnswer", Reasoning = "reasoning", + RouterMetadata = "routerMetadata", } // Status @@ -35,78 +30,6 @@ export interface MessageStatusUpdate { message?: string; } -// Web search -export enum MessageWebSearchUpdateType { - Update = "update", - Error = "error", - Sources = "sources", - Finished = "finished", -} -export interface BaseMessageWebSearchUpdate { - type: MessageUpdateType.WebSearch; - subtype: TSubType; -} -export interface MessageWebSearchErrorUpdate - extends BaseMessageWebSearchUpdate { - message: string; - args?: string[]; -} -export interface MessageWebSearchGeneralUpdate - extends BaseMessageWebSearchUpdate { - message: string; - args?: string[]; -} -export interface MessageWebSearchSourcesUpdate - extends BaseMessageWebSearchUpdate { - message: string; - sources: WebSearchSource[]; -} -export type MessageWebSearchFinishedUpdate = - BaseMessageWebSearchUpdate; -export type MessageWebSearchUpdate = - | MessageWebSearchErrorUpdate - | MessageWebSearchGeneralUpdate - | MessageWebSearchSourcesUpdate - | MessageWebSearchFinishedUpdate; - -// Tool -export enum MessageToolUpdateType { - /** A request to call a tool alongside it's parameters */ - Call = "call", - /** The result of a tool call */ - Result = "result", - /** Error while running tool */ - Error = "error", - /** ETA update */ - ETA = "eta", -} - -interface MessageToolBaseUpdate { - type: MessageUpdateType.Tool; - subtype: TSubType; - uuid: string; -} -export interface MessageToolCallUpdate extends MessageToolBaseUpdate { - call: ToolCall; -} -export interface MessageToolResultUpdate - extends MessageToolBaseUpdate { - result: ToolResult; -} -export interface MessageToolErrorUpdate extends MessageToolBaseUpdate { - message: string; -} - -export interface MessageToolETAUpdate extends MessageToolBaseUpdate { - eta: number; -} - -export type MessageToolUpdate = - | MessageToolCallUpdate - | MessageToolResultUpdate - | MessageToolErrorUpdate - | MessageToolETAUpdate; - // Everything else export interface MessageTitleUpdate { type: MessageUpdateType.Title; @@ -145,5 +68,9 @@ export interface MessageFinalAnswerUpdate { type: MessageUpdateType.FinalAnswer; text: string; interrupted: boolean; - webSources?: { uri: string; title: string }[]; +} +export interface MessageRouterMetadataUpdate { + type: MessageUpdateType.RouterMetadata; + route: string; + model: string; } diff --git a/src/lib/types/Model.ts b/src/lib/types/Model.ts index d69ffbdeb95c6d2b3e2e076365e6100d1c3c7283..2c6711d5c0805b192c681a0914a575cae029da2b 100644 --- a/src/lib/types/Model.ts +++ b/src/lib/types/Model.ts @@ -5,6 +5,7 @@ export type Model = Pick< | "id" | "name" | "displayName" + | "isRouter" | "websiteUrl" | "datasetName" | "promptExamples" @@ -12,12 +13,11 @@ export type Model = Pick< | "description" | "logoUrl" | "modelUrl" - | "tokenizer" | "datasetUrl" | "preprompt" | "multimodal" | "multimodalAcceptedMimetypes" | "unlisted" - | "tools" | "hasInferenceAPI" + | "providers" >; diff --git a/src/lib/types/Semaphore.ts b/src/lib/types/Semaphore.ts index b4bb5d889e550d19180b0b2c51a5bd05de4763c9..d3ba12ea3ee999842f4d569ffc3832b40ca9748e 100644 --- a/src/lib/types/Semaphore.ts +++ b/src/lib/types/Semaphore.ts @@ -6,7 +6,6 @@ export interface Semaphore extends Timestamps { } export enum Semaphores { - ASSISTANTS_COUNT = "assistants.count", CONVERSATION_STATS = "conversation.stats", CONFIG_UPDATE = "config.update", MIGRATION = "migration", diff --git a/src/lib/types/Settings.ts b/src/lib/types/Settings.ts index b66b0c8023bbadae460e9884eeb8349940b7a9d3..d988ca8c8d836074b12f6be6a979e2f8c26225d5 100644 --- a/src/lib/types/Settings.ts +++ b/src/lib/types/Settings.ts @@ -1,5 +1,4 @@ import { defaultModel } from "$lib/server/models"; -import type { Assistant } from "./Assistant"; import type { Timestamps } from "./Timestamps"; import type { User } from "./User"; @@ -7,34 +6,39 @@ export interface Settings extends Timestamps { userId?: User["_id"]; sessionId?: string; - /** - * Note: Only conversations with this settings explicitly set to true should be shared. - * - * This setting is explicitly set to true when users accept the ethics modal. - * */ shareConversationsWithModelAuthors: boolean; - ethicsModalAcceptedAt: Date | null; + /** One-time welcome modal acknowledgement */ + welcomeModalSeenAt?: Date | null; activeModel: string; - hideEmojiOnSidebar?: boolean; // model name and system prompts customPrompts?: Record; - assistants?: Assistant["_id"][]; - tools?: string[]; + /** + * Per‑model overrides to enable multimodal (image) support + * even when not advertised by the provider/model list. + * Only the `true` value is meaningful (enables images). + */ + multimodalOverrides?: Record; + + /** + * Per-model toggle to hide Omni prompt suggestions shown near the composer. + * When set to `true`, prompt examples for that model are suppressed. + */ + hidePromptExamples?: Record; + disableStream: boolean; directPaste: boolean; } -export type SettingsEditable = Omit; +export type SettingsEditable = Omit; // TODO: move this to a constant file along with other constants export const DEFAULT_SETTINGS = { shareConversationsWithModelAuthors: true, activeModel: defaultModel.id, - hideEmojiOnSidebar: false, customPrompts: {}, - assistants: [], - tools: [], + multimodalOverrides: {}, + hidePromptExamples: {}, disableStream: false, directPaste: false, } satisfies SettingsEditable; diff --git a/src/lib/types/SharedConversation.ts b/src/lib/types/SharedConversation.ts index 99e4affb6e928d5ac06a7a3af295b1d950c1e955..021c1860fbda42c8e99570075108398aac19079f 100644 --- a/src/lib/types/SharedConversation.ts +++ b/src/lib/types/SharedConversation.ts @@ -2,15 +2,7 @@ import type { Conversation } from "./Conversation"; export type SharedConversation = Pick< Conversation, - | "model" - | "embeddingModel" - | "title" - | "rootMessageId" - | "messages" - | "preprompt" - | "assistantId" - | "createdAt" - | "updatedAt" + "model" | "title" | "rootMessageId" | "messages" | "preprompt" | "createdAt" | "updatedAt" > & { _id: string; hash: string; diff --git a/src/lib/types/Template.ts b/src/lib/types/Template.ts index d81569827c49f55ec258247f973c9fc130a431c0..9c31ac3614987a89734772157a32074a928f60ca 100644 --- a/src/lib/types/Template.ts +++ b/src/lib/types/Template.ts @@ -1,10 +1,7 @@ import type { Message } from "./Message"; -import type { Tool, ToolResult } from "./Tool"; export type ChatTemplateInput = { messages: Pick[]; preprompt?: string; - tools?: Tool[]; - toolResults?: ToolResult[]; continueMessage?: boolean; }; diff --git a/src/lib/types/Tool.ts b/src/lib/types/Tool.ts deleted file mode 100644 index 1764b7b5f424feb79eb9a79c8a0cc01215ed7281..0000000000000000000000000000000000000000 --- a/src/lib/types/Tool.ts +++ /dev/null @@ -1,188 +0,0 @@ -import type { ObjectId } from "mongodb"; -import type { User } from "./User"; -import type { Timestamps } from "./Timestamps"; -import type { BackendToolContext } from "$lib/server/tools"; -import type { MessageUpdate } from "./MessageUpdate"; -import { z } from "zod"; -import type { ReviewStatus } from "./Review"; - -export const ToolColor = z.union([ - z.literal("purple"), - z.literal("blue"), - z.literal("green"), - z.literal("yellow"), - z.literal("red"), -]); - -export const ToolIcon = z.union([ - z.literal("wikis"), - z.literal("tools"), - z.literal("camera"), - z.literal("code"), - z.literal("email"), - z.literal("cloud"), - z.literal("terminal"), - z.literal("game"), - z.literal("chat"), - z.literal("speaker"), - z.literal("video"), -]); - -export const ToolOutputComponents = z - .string() - .toLowerCase() - .pipe( - z.union([ - z.literal("textbox"), - z.literal("markdown"), - z.literal("image"), - z.literal("gallery"), - z.literal("number"), - z.literal("audio"), - z.literal("video"), - z.literal("file"), - z.literal("json"), - ]) - ); - -export type ToolOutputComponents = z.infer; - -export type ToolLogoColor = z.infer; -export type ToolLogoIcon = z.infer; - -export type ToolIOType = "str" | "int" | "float" | "bool" | "file"; - -export type ToolInputRequired = { - paramType: "required"; - name: string; - description?: string; -}; - -export type ToolInputOptional = { - paramType: "optional"; - name: string; - description?: string; - default: string | number | boolean; -}; - -export type ToolInputFixed = { - paramType: "fixed"; - name: string; - value: string | number | boolean; -}; - -type ToolInputBase = ToolInputRequired | ToolInputOptional | ToolInputFixed; - -export type ToolInputFile = ToolInputBase & { - type: "file"; - mimeTypes: string; -}; - -export type ToolInputSimple = ToolInputBase & { - type: Exclude; -}; - -export type ToolInput = ToolInputFile | ToolInputSimple; - -export interface BaseTool { - _id: ObjectId; - - name: string; // name that will be shown to the AI - - baseUrl?: string; // namespace for the tool - endpoint: string | null; // endpoint to call in gradio, if null we expect to override this function in code - outputComponent: string | null; // Gradio component type to use for the output - outputComponentIdx: number | null; // index of the output component - - inputs: Array; - showOutput: boolean; // show output in chat or not - - call: BackendCall; - - // for displaying in the UI - displayName: string; - color: ToolLogoColor; - icon: ToolLogoIcon; - description: string; -} - -export interface ConfigTool extends BaseTool { - type: "config"; - isOnByDefault?: true; - isLocked?: true; - isHidden?: true; -} - -export interface CommunityTool extends BaseTool, Timestamps { - type: "community"; - - createdById: User["_id"] | string; // user id or session - createdByName?: User["username"]; - - // used to compute popular & trending - useCount: number; - last24HoursUseCount: number; - - review: ReviewStatus; - searchTokens: string[]; -} - -// no call function in db -export type CommunityToolDB = Omit; - -export type CommunityToolEditable = Omit< - CommunityToolDB, - | "_id" - | "useCount" - | "last24HoursUseCount" - | "createdById" - | "createdByName" - | "review" - | "searchTokens" - | "type" - | "createdAt" - | "updatedAt" ->; - -export type Tool = ConfigTool | CommunityTool; - -export type ToolFront = Pick< - Tool, - "type" | "name" | "displayName" | "description" | "color" | "icon" -> & { - _id: string; - isOnByDefault: boolean; - isLocked: boolean; - mimeTypes: string[]; - timeToUseMS?: number; -}; - -export enum ToolResultStatus { - Success = "success", - Error = "error", -} -export interface ToolResultSuccess { - status: ToolResultStatus.Success; - call: ToolCall; - outputs: Record[]; - display?: boolean; -} -export interface ToolResultError { - status: ToolResultStatus.Error; - call: ToolCall; - message: string; - display?: boolean; -} -export type ToolResult = ToolResultSuccess | ToolResultError; - -export interface ToolCall { - name: string; - parameters: Record; - toolId?: string; -} - -export type BackendCall = ( - params: Record, - context: BackendToolContext, - uuid: string -) => AsyncGenerator, undefined>; diff --git a/src/lib/types/WebSearch.ts b/src/lib/types/WebSearch.ts deleted file mode 100644 index 7fddc3a99ae24877f3babb583a73663bcc9caca3..0000000000000000000000000000000000000000 --- a/src/lib/types/WebSearch.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { ObjectId } from "mongodb"; -import type { Conversation } from "./Conversation"; -import type { Timestamps } from "./Timestamps"; -import type { HeaderElement } from "$lib/server/websearch/markdown/types"; - -export interface WebSearch extends Timestamps { - _id?: ObjectId; - convId?: Conversation["_id"]; - - prompt: string; - - searchQuery: string; - results: WebSearchSource[]; - contextSources: WebSearchUsedSource[]; -} - -export interface WebSearchSource { - title?: string; - link: string; -} -export interface WebSearchScrapedSource extends WebSearchSource { - page: WebSearchPage; -} -export interface WebSearchPage { - title: string; - siteName?: string; - author?: string; - description?: string; - createdAt?: string; - modifiedAt?: string; - markdownTree: HeaderElement; -} - -export interface WebSearchUsedSource extends WebSearchScrapedSource { - context: string; -} - -export type WebSearchMessageSources = { - type: "sources"; - sources: WebSearchSource[]; -}; - -// eslint-disable-next-line no-shadow -export enum WebSearchProvider { - GOOGLE = "Google", - YOU = "You.com", - SEARXNG = "SearXNG", - BING = "Bing", -} diff --git a/src/lib/utils/getTokenizer.ts b/src/lib/utils/getTokenizer.ts deleted file mode 100644 index 1c6be9b153d710f4c5173a5ae9e6d6e32656eba0..0000000000000000000000000000000000000000 --- a/src/lib/utils/getTokenizer.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Model } from "$lib/types/Model"; -import { AutoTokenizer, PreTrainedTokenizer } from "@huggingface/transformers"; - -export async function getTokenizer(_modelTokenizer: Exclude) { - if (typeof _modelTokenizer === "string") { - // return auto tokenizer - return await AutoTokenizer.from_pretrained(_modelTokenizer); - } else { - // construct & return pretrained tokenizer - const { tokenizerUrl, tokenizerConfigUrl } = _modelTokenizer satisfies { - tokenizerUrl: string; - tokenizerConfigUrl: string; - }; - const tokenizerJSON = await (await fetch(tokenizerUrl)).json(); - const tokenizerConfig = await (await fetch(tokenizerConfigUrl)).json(); - return new PreTrainedTokenizer(tokenizerJSON, tokenizerConfig); - } -} diff --git a/src/lib/utils/hashConv.ts b/src/lib/utils/hashConv.ts index de014324f6f21fbb67a61d098844027cfcdad0bf..7231e500bd313877f6df8194a77bf050feec0349 100644 --- a/src/lib/utils/hashConv.ts +++ b/src/lib/utils/hashConv.ts @@ -4,7 +4,7 @@ import { sha256 } from "./sha256"; export async function hashConv(conv: Conversation) { // messages contains the conversation message but only the immutable part const messages = conv.messages.map((message) => { - return (({ from, id, content, webSearchId }) => ({ from, id, content, webSearchId }))(message); + return (({ from, id, content }) => ({ from, id, content }))(message); }); const hash = await sha256(JSON.stringify(messages)); diff --git a/src/lib/utils/marked.ts b/src/lib/utils/marked.ts index 84fa7bc5081a4d3796757541c9121ae9cf3b3e05..f5375dfc67f7032bf570e2f0fe5a7e5d949ecc8f 100644 --- a/src/lib/utils/marked.ts +++ b/src/lib/utils/marked.ts @@ -2,7 +2,11 @@ import katex from "katex"; import "katex/dist/contrib/mhchem.mjs"; import { Marked } from "marked"; import type { Tokens, TokenizerExtension, RendererExtension } from "marked"; -import type { WebSearchSource } from "$lib/types/WebSearch"; +// Simple type to replace removed WebSearchSource +type SimpleSource = { + title?: string; + link: string; +}; import hljs from "highlight.js"; interface katexBlockToken extends Tokens.Generic { @@ -133,7 +137,7 @@ function escapeHTML(content: string) { ); } -function addInlineCitations(md: string, webSearchSources: WebSearchSource[] = []): string { +function addInlineCitations(md: string, webSearchSources: SimpleSource[] = []): string { const linkStyle = "color: rgb(59, 130, 246); text-decoration: none; hover:text-decoration: underline;"; return md.replace(/\[(\d+)\]/g, (match: string) => { @@ -153,7 +157,7 @@ function addInlineCitations(md: string, webSearchSources: WebSearchSource[] = [] }); } -function createMarkedInstance(sources: WebSearchSource[]): Marked { +function createMarkedInstance(sources: SimpleSource[]): Marked { return new Marked({ hooks: { postprocess: (html) => addInlineCitations(html, sources), @@ -180,7 +184,7 @@ type TextToken = { html: string | Promise; }; -export async function processTokens(content: string, sources: WebSearchSource[]): Promise { +export async function processTokens(content: string, sources: SimpleSource[]): Promise { const marked = createMarkedInstance(sources); const tokens = marked.lexer(content); @@ -205,7 +209,7 @@ export async function processTokens(content: string, sources: WebSearchSource[]) return processedTokens; } -export function processTokensSync(content: string, sources: WebSearchSource[]): Token[] { +export function processTokensSync(content: string, sources: SimpleSource[]): Token[] { const marked = createMarkedInstance(sources); const tokens = marked.lexer(content); return tokens.map((token) => { diff --git a/src/lib/utils/messageUpdates.ts b/src/lib/utils/messageUpdates.ts index febdce4391eeeb4fe4aea0ced8459489f71c349d..c847dfbc5efbd382a3a0a401e33b44e37e69a587 100644 --- a/src/lib/utils/messageUpdates.ts +++ b/src/lib/utils/messageUpdates.ts @@ -2,55 +2,17 @@ import type { MessageFile } from "$lib/types/Message"; import { type MessageUpdate, type MessageStreamUpdate, - type MessageToolCallUpdate, - MessageToolUpdateType, MessageUpdateType, - type MessageToolUpdate, - type MessageWebSearchUpdate, - type MessageWebSearchGeneralUpdate, - type MessageWebSearchSourcesUpdate, - type MessageWebSearchErrorUpdate, - MessageWebSearchUpdateType, - type MessageToolErrorUpdate, - type MessageToolResultUpdate, } from "$lib/types/MessageUpdate"; import { page } from "$app/state"; -export const isMessageWebSearchUpdate = (update: MessageUpdate): update is MessageWebSearchUpdate => - update.type === MessageUpdateType.WebSearch; -export const isMessageWebSearchGeneralUpdate = ( - update: MessageUpdate -): update is MessageWebSearchGeneralUpdate => - isMessageWebSearchUpdate(update) && update.subtype === MessageWebSearchUpdateType.Update; -export const isMessageWebSearchSourcesUpdate = ( - update: MessageUpdate -): update is MessageWebSearchSourcesUpdate => - isMessageWebSearchUpdate(update) && update.subtype === MessageWebSearchUpdateType.Sources; -export const isMessageWebSearchErrorUpdate = ( - update: MessageUpdate -): update is MessageWebSearchErrorUpdate => - isMessageWebSearchUpdate(update) && update.subtype === MessageWebSearchUpdateType.Error; - -export const isMessageToolUpdate = (update: MessageUpdate): update is MessageToolUpdate => - update.type === MessageUpdateType.Tool; -export const isMessageToolCallUpdate = (update: MessageUpdate): update is MessageToolCallUpdate => - isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Call; -export const isMessageToolResultUpdate = ( - update: MessageUpdate -): update is MessageToolResultUpdate => - isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Result; -export const isMessageToolErrorUpdate = (update: MessageUpdate): update is MessageToolErrorUpdate => - isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Error; - type MessageUpdateRequestOptions = { base: string; inputs?: string; messageId?: string; isRetry: boolean; isContinue: boolean; - webSearch: boolean; - tools?: Array; files?: MessageFile[]; }; export async function fetchMessageUpdates( @@ -68,8 +30,6 @@ export async function fetchMessageUpdates( id: opts.messageId, is_retry: opts.isRetry, is_continue: opts.isContinue, - web_search: opts.webSearch, - tools: opts.tools, }); opts.files?.forEach((file) => { diff --git a/src/lib/utils/models.ts b/src/lib/utils/models.ts index 9d3f6949d37073ae552b2e9e7677d9aba427c0eb..2853994e2cd1c0f42391289dc664bfd66aca6e17 100644 --- a/src/lib/utils/models.ts +++ b/src/lib/utils/models.ts @@ -1,4 +1,20 @@ import type { Model } from "$lib/types/Model"; -export const findCurrentModel = (models: Model[], id?: string): Model => - models.find((m) => m.id === id) ?? models[0]; +export const findCurrentModel = ( + models: Model[], + oldModels: { id: string; transferTo?: string }[] = [], + id?: string +): Model => { + if (id) { + const direct = models.find((m) => m.id === id); + if (direct) return direct; + + const legacy = oldModels.find((m) => m.id === id); + if (legacy?.transferTo) { + const mapped = models.find((m) => m.id === legacy.transferTo); + if (mapped) return mapped; + } + } + + return models[0]; +}; diff --git a/src/lib/utils/screenshot.ts b/src/lib/utils/screenshot.ts deleted file mode 100644 index ebfee90a82deb2f6148a9ae543fd2677b776b9c8..0000000000000000000000000000000000000000 --- a/src/lib/utils/screenshot.ts +++ /dev/null @@ -1,43 +0,0 @@ -export async function captureScreen(): Promise { - let stream: MediaStream | undefined; - try { - // This will show the native browser dialog for screen capture - stream = await navigator.mediaDevices.getDisplayMedia({ - video: true, - audio: false, - }); - - // Create a canvas element to capture the screenshot - const canvas = document.createElement("canvas"); - const video = document.createElement("video"); - - // Wait for the video to load metadata - await new Promise((resolve) => { - video.onloadedmetadata = () => { - canvas.width = video.videoWidth; - canvas.height = video.videoHeight; - video.play(); - resolve(null); - }; - if (stream) { - video.srcObject = stream; - } else { - throw Error("No stream available"); - } - }); - - // Draw the video frame to canvas - const context = canvas.getContext("2d"); - context?.drawImage(video, 0, 0, canvas.width, canvas.height); - // Convert to base64 - return canvas.toDataURL("image/png"); - } catch (error) { - console.error("Error capturing screenshot:", error); - throw error; - } finally { - // Stop all tracks - if (stream) { - stream.getTracks().forEach((track) => track.stop()); - } - } -} diff --git a/src/lib/utils/share.ts b/src/lib/utils/share.ts deleted file mode 100644 index 25352732f646a8bdd44ae667d8e90a67959accdc..0000000000000000000000000000000000000000 --- a/src/lib/utils/share.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { browser } from "$app/environment"; -import { isDesktop } from "./isDesktop"; - -export async function share(url: string, title: string, appendLeafId: boolean = false) { - if (!browser) return; - - // Retrieve the leafId from localStorage - const leafId = localStorage.getItem("leafId"); - - if (appendLeafId && leafId) { - // Use URL and URLSearchParams to add the leafId parameter - const shareUrl = new URL(url); - shareUrl.searchParams.append("leafId", leafId); - url = shareUrl.toString(); - } - - if (navigator.share && !isDesktop(window)) { - navigator.share({ url, title }); - } else { - // this is really ugly - // but on chrome the clipboard write doesn't work if the window isn't focused - // and after we use confirm() to ask the user if they want to share, the window is no longer focused - // for a few ms until the confirm dialog closes. tried await tick(), tried window.focus(), didnt work - // bug doesnt occur in firefox, if you can find a better fix for it please do - await new Promise((resolve) => setTimeout(resolve, 250)); - await navigator.clipboard.writeText(url); - } -} diff --git a/src/lib/utils/toolIds.ts b/src/lib/utils/toolIds.ts deleted file mode 100644 index 0b2f74851d785447e51c992cd2559bac0cae039a..0000000000000000000000000000000000000000 --- a/src/lib/utils/toolIds.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const webSearchToolId = "00000000000000000000000a"; -export const fetchUrlToolId = "00000000000000000000000b"; -export const imageGenToolId = "000000000000000000000001"; -export const documentParserToolId = "000000000000000000000002"; diff --git a/src/lib/utils/tools.ts b/src/lib/utils/tools.ts deleted file mode 100644 index 52b3077c092b2a1500df04a3a36b4c859c09dd83..0000000000000000000000000000000000000000 --- a/src/lib/utils/tools.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Tool } from "$lib/types/Tool"; - -/** - * Checks if a tool's name equals a value. Replaces all hyphens with underscores before comparison - * since some models return underscores even when hyphens are used in the request. - **/ -export function toolHasName(name: string, tool: Pick): boolean { - return tool.name.replaceAll("-", "_") === name.replaceAll("-", "_"); -} - -export const colors = ["purple", "blue", "green", "yellow", "red"] as const; - -export const icons = [ - "wikis", - "tools", - "camera", - "code", - "email", - "cloud", - "terminal", - "game", - "chat", - "speaker", - "video", -] as const; diff --git a/src/lib/utils/tree/treeHelpers.spec.ts b/src/lib/utils/tree/treeHelpers.spec.ts index 75ce04927c45176077aa30fa270194d52ad12377..9fce45bc0e30bb1b9622dbdf33e2ed0f3320d286 100644 --- a/src/lib/utils/tree/treeHelpers.spec.ts +++ b/src/lib/utils/tree/treeHelpers.spec.ts @@ -11,7 +11,7 @@ export const insertLegacyConversation = async () => { updatedAt: new Date(), title: "legacy conversation", model: "", - embeddingModel: "", + messages: [ { id: "1-1-1-1-1", @@ -45,7 +45,6 @@ export const insertLinearBranchConversation = async () => { updatedAt: new Date(), title: "linear branch conversation", model: "", - embeddingModel: "", rootMessageId: "1-1-1-1-1", messages: [ @@ -89,7 +88,7 @@ export const insertSideBranchesConversation = async () => { updatedAt: new Date(), title: "side branches conversation", model: "", - embeddingModel: "", + rootMessageId: "1-1-1-1-1", messages: [ { diff --git a/src/lib/workers/markdownWorker.ts b/src/lib/workers/markdownWorker.ts index 9e71f60877ca7e3b2c6a400895a9cb70c1b6817d..a7fa57d8b6cb446f0d11d3bdbc903c0b483bb6de 100644 --- a/src/lib/workers/markdownWorker.ts +++ b/src/lib/workers/markdownWorker.ts @@ -1,10 +1,14 @@ -import type { WebSearchSource } from "$lib/types/WebSearch"; +// Simple type to replace removed WebSearchSource +type SimpleSource = { + title?: string; + link: string; +}; import { processTokens, type Token } from "$lib/utils/marked"; export type IncomingMessage = { type: "process"; content: string; - sources: WebSearchSource[]; + sources: SimpleSource[]; }; export type OutgoingMessage = { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 26417944f70ef0520781256ddf426ed83318bc68..77d50bf07416853687df3d9740c0710b77a2518f 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,25 +4,25 @@ import { onDestroy, onMount, untrack } from "svelte"; import { goto } from "$app/navigation"; import { base } from "$app/paths"; - import { page } from "$app/stores"; + import { page } from "$app/state"; import { error } from "$lib/stores/errors"; import { createSettingsStore } from "$lib/stores/settings"; - import { shareConversation } from "$lib/shareConversation"; - import Toast from "$lib/components/Toast.svelte"; import NavMenu from "$lib/components/NavMenu.svelte"; import MobileNav from "$lib/components/MobileNav.svelte"; import titleUpdate from "$lib/stores/titleUpdate"; - import DisclaimerModal from "$lib/components/DisclaimerModal.svelte"; + import WelcomeModal from "$lib/components/WelcomeModal.svelte"; import ExpandNavigation from "$lib/components/ExpandNavigation.svelte"; import { loginModalOpen } from "$lib/stores/loginModal"; import LoginModal from "$lib/components/LoginModal.svelte"; import OverloadedModal from "$lib/components/OverloadedModal.svelte"; - import Search from "$lib/components/chat/Search.svelte"; import { setContext } from "svelte"; import { handleResponse, useAPIClient } from "$lib/APIClient"; + import { isAborted } from "$lib/stores/isAborted"; + import IconShare from "$lib/components/icons/IconShare.svelte"; + import { shareModal } from "$lib/stores/shareModal"; let { data = $bindable(), children } = $props(); @@ -59,9 +59,15 @@ errorToastTimeout = setTimeout(() => { $error = undefined; currentError = undefined; - }, 10000); + }, 5000); } + const canShare = $derived( + publicConfig.isHuggingChat && + Boolean(page.params?.id) && + page.route.id?.startsWith("/conversation/") + ); + async function deleteConversation(id: string) { client .conversations({ id }) @@ -70,7 +76,7 @@ .then(async () => { conversations = conversations.filter((conv) => conv.id !== id); - if ($page.params.id === id) { + if (page.params.id === id) { await goto(`${base}/`, { invalidateAll: true }); } }) @@ -117,13 +123,13 @@ const settings = createSettingsStore(data.settings); onMount(async () => { - if ($page.url.searchParams.has("model")) { + if (page.url.searchParams.has("model")) { await settings .instantSet({ - activeModel: $page.url.searchParams.get("model") ?? $settings.activeModel, + activeModel: page.url.searchParams.get("model") ?? $settings.activeModel, }) .then(async () => { - const query = new URLSearchParams($page.url.searchParams.toString()); + const query = new URLSearchParams(page.url.searchParams.toString()); query.delete("model"); await goto(`${base}/?${query.toString()}`, { invalidateAll: true, @@ -131,24 +137,8 @@ }); } - if ($page.url.searchParams.has("tools")) { - const tools = $page.url.searchParams.get("tools")?.split(","); - - await settings - .instantSet({ - tools: [...($settings.tools ?? []), ...(tools ?? [])], - }) - .then(async () => { - const query = new URLSearchParams($page.url.searchParams.toString()); - query.delete("tools"); - await goto(`${base}/?${query.toString()}`, { - invalidateAll: true, - }); - }); - } - - if ($page.url.searchParams.has("token")) { - const token = $page.url.searchParams.get("token"); + if (page.url.searchParams.has("token")) { + const token = page.url.searchParams.get("token"); await fetch(`${base}/api/user/validate-token`, { method: "POST", @@ -157,38 +147,63 @@ goto(`${base}/`, { invalidateAll: true }); }); } + + // Global keyboard shortcut: New Chat (Ctrl/Cmd + Shift + O) + const onKeydown = (e: KeyboardEvent) => { + // Ignore when a modal has focus (app is inert) + const appEl = document.getElementById("app"); + if (appEl?.hasAttribute("inert")) return; + + const oPressed = e.key?.toLowerCase() === "o"; + const metaOrCtrl = e.metaKey || e.ctrlKey; + if (oPressed && e.shiftKey && metaOrCtrl) { + e.preventDefault(); + isAborted.set(true); + goto(`${base}/`, { invalidateAll: true }); + } + }; + + window.addEventListener("keydown", onKeydown, { capture: true }); + onDestroy(() => window.removeEventListener("keydown", onKeydown, { capture: true })); }); let mobileNavTitle = $derived( - ["/models", "/assistants", "/privacy", "/tools"].includes($page.route.id ?? "") + ["/models", "/privacy"].includes(page.route.id ?? "") ? "" - : conversations.find((conv) => conv.id === $page.params.id)?.title + : conversations.find((conv) => conv.id === page.params.id)?.title ); - let showDisclaimer = $derived( - !$settings.ethicsModalAccepted && - $page.url.pathname !== `${base}/privacy` && - publicConfig.PUBLIC_APP_DISCLAIMER === "1" && - !($page.data.shared === true) - ); + // Show the welcome modal once on first app load + let showWelcome = $derived(!$settings.welcomeModalSeen && !(page.data.shared === true)); {publicConfig.PUBLIC_APP_NAME} - + - + - {#if !$page.url.pathname.includes("/assistant/") && $page.route.id !== "/assistants" && !$page.url.pathname.includes("/models/") && !$page.url.pathname.includes("/tools")} + {#if !page.url.pathname.includes("/models/")} - + {/if} - + + @@ -206,13 +221,13 @@ {/if} -{#if showDisclaimer} - ($settings.ethicsModalAccepted = true)} /> +{#if showWelcome} + settings.set({ welcomeModalSeen: true })} /> {/if} {#if $loginModalOpen} { + onclose={() => { $loginModalOpen = false; }} /> @@ -222,8 +237,6 @@ (overloadedModalOpen = false)} /> {/if} - -
    + {#if canShare} + + {/if} + shareConversation(ev.detail.id, ev.detail.title)} - on:deleteConversation={(ev) => deleteConversation(ev.detail)} - on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)} + ondeleteConversation={(id) => deleteConversation(id)} + oneditConversationTitle={(payload) => editConversationTitle(payload.id, payload.title)} /> {#if currentError} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index f18b96b05e6ea6699a91ae61295f408cbb331244..9651e594dfff9a3ba00b69b87008370524037663 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -3,44 +3,29 @@ import type { ConvSidebar } from "$lib/types/ConvSidebar"; import { useAPIClient, handleResponse } from "$lib/APIClient"; import { getConfigManager } from "$lib/utils/PublicConfig.svelte"; -export const load = async ({ depends, fetch }) => { +export const load = async ({ depends, fetch, url }) => { depends(UrlDependency.ConversationList); - const client = useAPIClient({ fetch }); + const client = useAPIClient({ fetch, origin: url.origin }); - const [ - settings, - models, - assistants, - oldModels, - tools, - communityToolCount, - user, - publicConfig, - featureFlags, - conversationsData, - ] = await Promise.all([ - client.user.settings.get().then(handleResponse), - client.models.get().then(handleResponse), - client.user.assistants.get().then(handleResponse), - client.models.old.get().then(handleResponse), - client.tools.active.get().then(handleResponse), - client.tools.count.get().then(handleResponse), - client.user.get().then(handleResponse), - client["public-config"].get().then(handleResponse), - client["feature-flags"].get().then(handleResponse), - client.conversations.get({ query: { p: 0 } }).then(handleResponse), - ]); + const [settings, models, oldModels, user, publicConfig, featureFlags, conversationsData] = + await Promise.all([ + client.user.settings.get().then(handleResponse), + client.models.get().then(handleResponse), + client.models.old.get().then(handleResponse), + client.user.get().then(handleResponse), + client["public-config"].get().then(handleResponse), + client["feature-flags"].get().then(handleResponse), + client.conversations.get({ query: { p: 0 } }).then(handleResponse), + ]); const defaultModel = models[0]; - const assistantActive = !models.map(({ id }) => id).includes(settings?.activeModel ?? ""); - const { conversations: rawConversations, nConversations } = conversationsData; const conversations = rawConversations.map((conv) => { - if (settings?.hideEmojiOnSidebar) { - conv.title = conv.title.replace(/\p{Emoji}/gu, ""); - } + // Always strip emojis and markers from titles for sidebar display + conv.title = conv.title.replace(/\p{Emoji}/gu, ""); + conv.title = conv.title.replace(/<\/?think>/gi, ""); // remove invalid unicode and trim whitespaces conv.title = conv.title.replace(/\uFFFD/gu, "").trimStart(); @@ -50,45 +35,19 @@ export const load = async ({ depends, fetch }) => { title: conv.title, model: conv.model ?? defaultModel, updatedAt: new Date(conv.updatedAt), - ...(conv.assistantId - ? { - assistantId: conv.assistantId.toString(), - avatarUrl: client - .assistants({ id: conv.assistantId.toString() }) - .get() - .then(handleResponse) - .then((assistant) => { - if (!assistant || !assistant.avatar) { - return undefined; - } - return `/settings/assistants/${conv.assistantId}/avatar.jpg?hash=${assistant.avatar}`; - }) - .catch(() => undefined), - } - : {}), } satisfies ConvSidebar; }); return { nConversations, conversations, - assistant: assistantActive - ? await client - .assistants({ id: settings?.activeModel }) - .get() - .then(handleResponse) - .catch(() => undefined) - : undefined, - assistants, models, oldModels, - tools, - communityToolCount, user, settings: { ...settings, - ethicsModalAcceptedAt: settings.ethicsModalAcceptedAt - ? new Date(settings.ethicsModalAcceptedAt) + welcomeModalSeenAt: settings.welcomeModalSeenAt + ? new Date(settings.welcomeModalSeenAt) : null, }, publicConfig: getConfigManager(publicConfig), diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 23daf651c795e4c59298aca34ef7ec517357eced..15ce3d0acaa8fe1dfffecdec1a4dc625bb98404a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -14,6 +14,8 @@ import { onMount } from "svelte"; let { data } = $props(); + + let hasModels = $derived(Boolean(data.models?.length)); let loading = $state(false); let files: File[] = $state([]); @@ -33,11 +35,7 @@ if (validModels.includes($settings.activeModel)) { model = $settings.activeModel; } else { - if (data.assistant?.modelId && validModels.includes(data.assistant.modelId)) { - model = data.assistant.modelId; - } else { - model = data.models[0].id; - } + model = data.models[0].id; } const res = await fetch(`${base}/conversation`, { method: "POST", @@ -47,7 +45,6 @@ body: JSON.stringify({ model, preprompt: $settings.customPrompts[$settings.activeModel], - assistantId: data.assistant?._id, }), }); @@ -82,25 +79,27 @@ if (query) createConversation(query); }); - let currentModel = $derived( - findCurrentModel( - [...data.models, ...data.oldModels], - !$settings.assistants.includes($settings.activeModel) - ? $settings.activeModel - : data.assistant?.modelId - ) - ); + let currentModel = $derived(findCurrentModel(data.models, data.oldModels, $settings.activeModel)); {publicConfig.PUBLIC_APP_NAME} - createConversation(ev.detail)} - {loading} - assistant={data.assistant} - {currentModel} - models={data.models} - bind:files -/> +{#if hasModels} + createConversation(message)} + {loading} + {currentModel} + models={data.models} + bind:files + /> +{:else} +
    +

    No models available

    +

    + No chat models are configured. Set `OPENAI_BASE_URL` and ensure the server can reach the + endpoint, then reload. If unset, the app defaults to the Hugging Face router. +

    +
    +{/if} diff --git a/src/routes/__debug/openai/+server.ts b/src/routes/__debug/openai/+server.ts new file mode 100644 index 0000000000000000000000000000000000000000..a4017ece991d739737c202e05ac27703947491ac --- /dev/null +++ b/src/routes/__debug/openai/+server.ts @@ -0,0 +1,21 @@ +import { json } from "@sveltejs/kit"; +import { config } from "$lib/server/config"; +const DEFAULT_OPENAI_BASE = "https://router.huggingface.co/v1"; + +export async function GET() { + const base = (config.OPENAI_BASE_URL || DEFAULT_OPENAI_BASE).replace(/\/$/, ""); + try { + const res = await fetch(`${base}/models`); + const text = await res.text(); + let length: number | null = null; + try { + const parsed = JSON.parse(text); + length = Array.isArray(parsed?.data) ? parsed.data.length : null; + } catch (_err) { + length = null; // ignore parse errors + } + return json({ base, status: res.status, ok: res.ok, length, sample: text.slice(0, 1000) }); + } catch (e) { + return json({ base, error: String(e) }); + } +} diff --git a/src/routes/api/assistant/+server.ts b/src/routes/api/assistant/+server.ts deleted file mode 100644 index dcf3a383aea73804ac6ef656cac809195d9f66bc..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/+server.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { authCondition } from "$lib/server/auth.js"; -import { requiresUser } from "$lib/server/auth.js"; -import { asssistantSchema } from "./utils.js"; -import { uploadAssistantAvatar } from "./utils.js"; -import { collections } from "$lib/server/database.js"; -import { ObjectId } from "mongodb"; -import sharp from "sharp"; -import { generateSearchTokens } from "$lib/utils/searchTokens"; -import { usageLimits } from "$lib/server/usageLimits.js"; -import { ReviewStatus } from "$lib/types/Review.js"; - -export async function POST({ request, locals }) { - const formData = await request.formData(); - const parse = await asssistantSchema.safeParseAsync(Object.fromEntries(formData)); - - if (!parse.success) { - // Loop through the errors array and create a custom errors array - const errors = parse.error.errors.map((error) => { - return { - field: error.path[0], - message: error.message, - }; - }); - - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - // can only create assistants when logged in, IF login is setup - if (!locals.user && requiresUser) { - const errors = [{ field: "preprompt", message: "Must be logged in. Unauthorized" }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const createdById = locals.user?._id ?? locals.sessionId; - - const assistantsCount = await collections.assistants.countDocuments({ createdById }); - - if (usageLimits?.assistants && assistantsCount > usageLimits.assistants) { - const errors = [ - { - field: "preprompt", - message: "You have reached the maximum number of assistants. Delete some to continue.", - }, - ]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const newAssistantId = new ObjectId(); - - const exampleInputs: string[] = [ - parse?.data?.exampleInput1 ?? "", - parse?.data?.exampleInput2 ?? "", - parse?.data?.exampleInput3 ?? "", - parse?.data?.exampleInput4 ?? "", - ].filter((input) => !!input); - - let hash; - if (parse.data.avatar && parse.data.avatar instanceof File && parse.data.avatar.size > 0) { - let image; - try { - image = await sharp(await parse.data.avatar.arrayBuffer()) - .resize(512, 512, { fit: "inside" }) - .jpeg({ quality: 80 }) - .toBuffer(); - } catch (e) { - const errors = [{ field: "avatar", message: (e as Error).message }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - hash = await uploadAssistantAvatar(new File([image], "avatar.jpg"), newAssistantId); - } - - const { insertedId } = await collections.assistants.insertOne({ - _id: newAssistantId, - createdById, - createdByName: locals.user?.username ?? locals.user?.name, - ...parse.data, - tools: parse.data.tools, - exampleInputs, - avatar: hash, - createdAt: new Date(), - updatedAt: new Date(), - userCount: 1, - review: ReviewStatus.PRIVATE, - rag: { - allowedLinks: parse.data.ragLinkList, - allowedDomains: parse.data.ragDomainList, - allowAllDomains: parse.data.ragAllowAll, - }, - dynamicPrompt: parse.data.dynamicPrompt, - searchTokens: generateSearchTokens(parse.data.name), - last24HoursCount: 0, - generateSettings: { - temperature: parse.data.temperature, - top_p: parse.data.top_p, - repetition_penalty: parse.data.repetition_penalty, - top_k: parse.data.top_k, - }, - }); - - // add insertedId to user settings - - await collections.settings.updateOne(authCondition(locals), { - $addToSet: { assistants: insertedId }, - }); - - return new Response(JSON.stringify({ success: true, assistantId: insertedId }), { status: 200 }); -} diff --git a/src/routes/api/assistant/[id]/+server.ts b/src/routes/api/assistant/[id]/+server.ts deleted file mode 100644 index aaf35e4a812ac1015ebc522f27722979076370fc..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/[id]/+server.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { collections } from "$lib/server/database"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { asssistantSchema, uploadAssistantAvatar } from "../utils.js"; -import { requiresUser } from "$lib/server/auth.js"; -import sharp from "sharp"; -import { generateSearchTokens } from "$lib/utils/searchTokens"; - -export async function GET({ params }) { - const id = params.id; - const assistantId = new ObjectId(id); - - const assistant = await collections.assistants.findOne({ - _id: assistantId, - }); - - if (assistant) { - return Response.json(assistant); - } else { - return Response.json({ message: "Assistant not found" }, { status: 404 }); - } -} - -export async function PATCH({ request, locals, params }) { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.id), - }); - - if (!assistant) { - throw Error("Assistant not found"); - } - - if (assistant.createdById.toString() !== (locals.user?._id ?? locals.sessionId).toString()) { - throw Error("You are not the author of this assistant"); - } - - const formData = Object.fromEntries(await request.formData()); - - const parse = await asssistantSchema.safeParseAsync(formData); - - if (!parse.success) { - // Loop through the errors array and create a custom errors array - const errors = parse.error.errors.map((error) => { - return { - field: error.path[0], - message: error.message, - }; - }); - - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - // can only create assistants when logged in, IF login is setup - if (!locals.user && requiresUser) { - const errors = [{ field: "preprompt", message: "Must be logged in. Unauthorized" }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const exampleInputs: string[] = [ - parse?.data?.exampleInput1 ?? "", - parse?.data?.exampleInput2 ?? "", - parse?.data?.exampleInput3 ?? "", - parse?.data?.exampleInput4 ?? "", - ].filter((input) => !!input); - - const deleteAvatar = parse.data.avatar === "null"; - - let hash; - if (parse.data.avatar && parse.data.avatar !== "null" && parse.data.avatar.size > 0) { - let image; - try { - image = await sharp(await parse.data.avatar.arrayBuffer()) - .resize(512, 512, { fit: "inside" }) - .jpeg({ quality: 80 }) - .toBuffer(); - } catch (e) { - const errors = [{ field: "avatar", message: (e as Error).message }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const fileCursor = collections.bucket.find({ filename: assistant._id.toString() }); - - // Step 2: Delete the existing file if it exists - let fileId = await fileCursor.next(); - while (fileId) { - await collections.bucket.delete(fileId._id); - fileId = await fileCursor.next(); - } - - hash = await uploadAssistantAvatar(new File([image], "avatar.jpg"), assistant._id); - } else if (deleteAvatar) { - // delete the avatar - const fileCursor = collections.bucket.find({ filename: assistant._id.toString() }); - - let fileId = await fileCursor.next(); - while (fileId) { - await collections.bucket.delete(fileId._id); - fileId = await fileCursor.next(); - } - } - - const { acknowledged } = await collections.assistants.updateOne( - { - _id: assistant._id, - }, - { - $set: { - name: parse.data.name, - description: parse.data.description, - modelId: parse.data.modelId, - preprompt: parse.data.preprompt, - exampleInputs, - avatar: deleteAvatar ? undefined : (hash ?? assistant.avatar), - updatedAt: new Date(), - rag: { - allowedLinks: parse.data.ragLinkList, - allowedDomains: parse.data.ragDomainList, - allowAllDomains: parse.data.ragAllowAll, - }, - tools: parse.data.tools, - dynamicPrompt: parse.data.dynamicPrompt, - searchTokens: generateSearchTokens(parse.data.name), - generateSettings: { - temperature: parse.data.temperature, - top_p: parse.data.top_p, - repetition_penalty: parse.data.repetition_penalty, - top_k: parse.data.top_k, - }, - }, - } - ); - - if (acknowledged) { - return new Response(JSON.stringify({ success: true, assistantId: assistant._id }), { - status: 200, - }); - } else { - return new Response(JSON.stringify({ error: true, message: "Update failed" }), { status: 500 }); - } -} - -export async function DELETE({ params, locals }) { - const assistant = await collections.assistants.findOne({ _id: new ObjectId(params.id) }); - - if (!assistant) { - return error(404, "Assistant not found"); - } - - if ( - assistant.createdById.toString() !== (locals.user?._id ?? locals.sessionId).toString() && - !locals.isAdmin - ) { - return error(403, "You are not the author of this assistant"); - } - - await collections.assistants.deleteOne({ _id: assistant._id }); - - // and remove it from all users settings - await collections.settings.updateMany( - { - assistants: { $in: [assistant._id] }, - }, - { - $pull: { assistants: assistant._id }, - } - ); - - // and delete all avatars - const fileCursor = collections.bucket.find({ filename: assistant._id.toString() }); - - // Step 2: Delete the existing file if it exists - let fileId = await fileCursor.next(); - while (fileId) { - await collections.bucket.delete(fileId._id); - fileId = await fileCursor.next(); - } - - return new Response("Assistant deleted", { status: 200 }); -} diff --git a/src/routes/api/assistant/[id]/report/+server.ts b/src/routes/api/assistant/[id]/report/+server.ts deleted file mode 100644 index 6756aeb32f9e29ee2824f16435ed46975fb8c75d..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/[id]/report/+server.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { base } from "$app/paths"; - -import { collections } from "$lib/server/database"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { z } from "zod"; - -import { config } from "$lib/server/config"; -import { sendSlack } from "$lib/server/sendSlack"; -import type { Assistant } from "$lib/types/Assistant"; - -export async function POST({ params, request, locals, url }) { - // is there already a report from this user for this model ? - const report = await collections.reports.findOne({ - createdBy: locals.user?._id ?? locals.sessionId, - object: "assistant", - contentId: new ObjectId(params.id), - }); - - if (report) { - return error(400, "Already reported"); - } - - const { reason } = z.object({ reason: z.string().min(1).max(128) }).parse(await request.json()); - - if (!reason) { - return error(400, "Invalid report reason"); - } - - const { acknowledged } = await collections.reports.insertOne({ - _id: new ObjectId(), - contentId: new ObjectId(params.id), - object: "assistant", - createdBy: locals.user?._id ?? locals.sessionId, - createdAt: new Date(), - updatedAt: new Date(), - reason, - }); - - if (!acknowledged) { - return error(500, "Failed to report assistant"); - } - - if (config.WEBHOOK_URL_REPORT_ASSISTANT) { - const prefixUrl = config.PUBLIC_SHARE_PREFIX || `${config.PUBLIC_ORIGIN || url.origin}${base}`; - const assistantUrl = `${prefixUrl}/assistant/${params.id}`; - - const assistant = await collections.assistants.findOne>( - { _id: new ObjectId(params.id) }, - { projection: { name: 1 } } - ); - - const username = locals.user?.username; - - await sendSlack( - `🔴 Assistant <${assistantUrl}|${assistant?.name}> reported by ${ - username ? `` : "non-logged in user" - }.\n\n> ${reason}` - ); - } - - return new Response("Assistant reported", { status: 200 }); -} diff --git a/src/routes/api/assistant/[id]/review/+server.ts b/src/routes/api/assistant/[id]/review/+server.ts deleted file mode 100644 index 450263b1a56562c12fb2740d74bae0a8315597f3..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/[id]/review/+server.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { collections } from "$lib/server/database"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { base } from "$app/paths"; -import { config } from "$lib/server/config"; -import { ReviewStatus } from "$lib/types/Review"; -import { sendSlack } from "$lib/server/sendSlack"; -import { z } from "zod"; - -const schema = z.object({ - status: z.nativeEnum(ReviewStatus), -}); - -export async function PATCH({ params, request, locals, url }) { - const assistantId = params.id; - - const { status } = schema.parse(await request.json()); - - if (!assistantId) { - return error(400, "Assistant ID is required"); - } - - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(assistantId), - }); - - if (!assistant) { - return error(404, "Assistant not found"); - } - - if ( - !locals.user || - (!locals.isAdmin && assistant.createdById.toString() !== locals.user._id.toString()) - ) { - return error(403, "Permission denied"); - } - - // only admins can set the status to APPROVED or DENIED - // if the status is already APPROVED or DENIED, only admins can change it - - if ( - (status === ReviewStatus.APPROVED || - status === ReviewStatus.DENIED || - assistant.review === ReviewStatus.APPROVED || - assistant.review === ReviewStatus.DENIED) && - !locals.isAdmin - ) { - return error(403, "Permission denied"); - } - - const result = await collections.assistants.updateOne( - { _id: assistant._id }, - { $set: { review: status } } - ); - - if (result.modifiedCount === 0) { - return error(500, "Failed to update review status"); - } - - if (status === ReviewStatus.PENDING) { - const prefixUrl = config.PUBLIC_SHARE_PREFIX || `${config.PUBLIC_ORIGIN || url.origin}${base}`; - const assistantUrl = `${prefixUrl}/assistant/${assistantId}`; - - const username = locals.user?.username; - - await sendSlack( - `🟢 Assistant <${assistantUrl}|${assistant?.name}> requested to be featured by ${ - username ? `` : "non-logged in user" - }.` - ); - } - - return new Response("Review status updated", { status: 200 }); -} diff --git a/src/routes/api/assistant/[id]/subscribe/+server.ts b/src/routes/api/assistant/[id]/subscribe/+server.ts deleted file mode 100644 index ffc7ec6026526ff43e2774400bc7598aa09b1794..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/[id]/subscribe/+server.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { authCondition } from "$lib/server/auth"; - -import { collections } from "$lib/server/database"; -import { defaultModel } from "$lib/server/models.js"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; - -export async function POST({ params, locals }) { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.id), - }); - - if (!assistant) { - return error(404, "Assistant not found"); - } - - // don't push if it's already there - const settings = await collections.settings.findOne(authCondition(locals)); - - if (settings?.assistants?.includes(assistant._id)) { - return error(400, "Already subscribed"); - } - - const result = await collections.settings.updateOne(authCondition(locals), { - $addToSet: { assistants: assistant._id }, - $set: { activeModel: assistant._id.toString() }, - }); - - // reduce count only if push succeeded - if (result.modifiedCount > 0) { - await collections.assistants.updateOne({ _id: assistant._id }, { $inc: { userCount: 1 } }); - } - - return new Response("Assistant subscribed", { status: 200 }); -} - -export async function DELETE({ params, locals }) { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.id), - }); - - if (!assistant) { - return error(404, "Assistant not found"); - } - - const result = await collections.settings.updateOne(authCondition(locals), { - $pull: { assistants: assistant._id }, - }); - - // reduce count only if pull succeeded - if (result.modifiedCount > 0) { - await collections.assistants.updateOne({ _id: assistant._id }, { $inc: { userCount: -1 } }); - } - - const settings = await collections.settings.findOne(authCondition(locals)); - - // if the assistant was the active model, set the default model as active - if (settings?.activeModel === assistant._id.toString()) { - await collections.settings.updateOne(authCondition(locals), { - $set: { activeModel: defaultModel.id }, - }); - } - - return new Response("Assistant unsubscribed", { status: 200 }); -} diff --git a/src/routes/api/assistant/utils.ts b/src/routes/api/assistant/utils.ts deleted file mode 100644 index 7f26f526b959294e7bd9ca14a0d794f426b10e33..0000000000000000000000000000000000000000 --- a/src/routes/api/assistant/utils.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { parseStringToList } from "$lib/utils/parseStringToList"; -import { toolFromConfigs } from "$lib/server/tools"; -import { z } from "zod"; -import { collections } from "$lib/server/database"; -import { ObjectId } from "mongodb"; -import { sha256 } from "$lib/utils/sha256"; - -export const asssistantSchema = z.object({ - name: z.string().min(1), - modelId: z.string().min(1), - preprompt: z.string().min(1), - description: z.string().optional(), - exampleInput1: z.string().optional(), - exampleInput2: z.string().optional(), - exampleInput3: z.string().optional(), - exampleInput4: z.string().optional(), - avatar: z.union([z.instanceof(File), z.literal("null")]).optional(), - ragLinkList: z.preprocess(parseStringToList, z.string().url().array().max(10)), - ragDomainList: z.preprocess(parseStringToList, z.string().array()), - ragAllowAll: z.preprocess((v) => v === "true", z.boolean()), - dynamicPrompt: z.preprocess((v) => v === "on", z.boolean()), - temperature: z - .union([z.literal(""), z.coerce.number().min(0.1).max(2)]) - .transform((v) => (v === "" ? undefined : v)), - top_p: z - .union([z.literal(""), z.coerce.number().min(0.05).max(1)]) - .transform((v) => (v === "" ? undefined : v)), - - repetition_penalty: z - .union([z.literal(""), z.coerce.number().min(0.1).max(2)]) - .transform((v) => (v === "" ? undefined : v)), - - top_k: z - .union([z.literal(""), z.coerce.number().min(5).max(100)]) - .transform((v) => (v === "" ? undefined : v)), - tools: z - .string() - .optional() - .transform((v) => (v ? v.split(",") : [])) - .transform(async (v) => [ - ...(await collections.tools - .find({ _id: { $in: v.map((toolId) => new ObjectId(toolId)) } }) - .project({ _id: 1 }) - .toArray() - .then((tools) => tools.map((tool) => tool._id.toString()))), - ...toolFromConfigs - .filter((el) => (v ?? []).includes(el._id.toString())) - .map((el) => el._id.toString()), - ]) - .optional(), -}); - -export const uploadAssistantAvatar = async ( - avatar: File, - assistantId: ObjectId -): Promise => { - const hash = await sha256(await avatar.text()); - const upload = collections.bucket.openUploadStream(`${assistantId.toString()}`, { - metadata: { type: avatar.type, hash }, - }); - - upload.write((await avatar.arrayBuffer()) as unknown as Buffer); - upload.end(); - - // only return the filename when upload throws a finish event or a 10s time out occurs - return new Promise((resolve, reject) => { - upload.once("finish", () => resolve(hash)); - upload.once("error", reject); - setTimeout(() => reject(new Error("Upload timed out")), 10000); - }); -}; diff --git a/src/routes/api/assistants/+server.ts b/src/routes/api/assistants/+server.ts deleted file mode 100644 index 1e77b8b4238025c470facd38110699e5123ce78f..0000000000000000000000000000000000000000 --- a/src/routes/api/assistants/+server.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { collections } from "$lib/server/database"; -import type { Assistant } from "$lib/types/Assistant"; -import type { User } from "$lib/types/User"; -import { generateQueryTokens } from "$lib/utils/searchTokens.js"; -import type { Filter } from "mongodb"; -import { config } from "$lib/server/config"; -import { ReviewStatus } from "$lib/types/Review"; - -const NUM_PER_PAGE = 24; - -export async function GET({ url, locals }) { - const modelId = url.searchParams.get("modelId"); - const pageIndex = parseInt(url.searchParams.get("p") ?? "0"); - const username = url.searchParams.get("user"); - const query = url.searchParams.get("q")?.trim() ?? null; - const showUnfeatured = url.searchParams.get("showUnfeatured") === "true"; - const createdByCurrentUser = locals.user?.username && locals.user.username === username; - - let user: Pick | null = null; - if (username) { - user = await collections.users.findOne>( - { username }, - { projection: { _id: 1 } } - ); - if (!user) { - return Response.json({ message: `User "${username}" doesn't exist` }, { status: 404 }); - } - } - - // if we require featured assistants, that we are not on a user page and we are not an admin who wants to see unfeatured assistants, we show featured assistants - let shouldBeFeatured = {}; - - if (config.REQUIRE_FEATURED_ASSISTANTS === "true" && !(locals.isAdmin && showUnfeatured)) { - if (!user) { - // only show featured assistants on the community page - shouldBeFeatured = { review: ReviewStatus.APPROVED }; - } else if (!createdByCurrentUser) { - // on a user page show assistants that have been approved or are pending - shouldBeFeatured = { review: { $in: [ReviewStatus.APPROVED, ReviewStatus.PENDING] } }; - } - } - // fetch the top assistants sorted by user count from biggest to smallest, filter out all assistants with only 1 users. filter by model too if modelId is provided - const filter: Filter = { - ...(modelId && { modelId }), - ...(user && { createdById: user._id }), - ...(query && { searchTokens: { $all: generateQueryTokens(query) } }), - ...shouldBeFeatured, - }; - const assistants = await collections.assistants - .find(filter) - .skip(NUM_PER_PAGE * pageIndex) - .sort({ userCount: -1 }) - .limit(NUM_PER_PAGE) - .toArray(); - - const numTotalItems = await collections.assistants.countDocuments(filter); - - return Response.json({ - assistants, - selectedModel: modelId ?? "", - numTotalItems, - numItemsPerPage: NUM_PER_PAGE, - query, - }); -} diff --git a/src/routes/api/conversation/[id]/+server.ts b/src/routes/api/conversation/[id]/+server.ts index d879373b8a7cb340d466d167b9e1b036d0c1d7f3..c2a4dd11c6b9185654b15f327a785cd27c5aecab 100644 --- a/src/routes/api/conversation/[id]/+server.ts +++ b/src/routes/api/conversation/[id]/+server.ts @@ -1,7 +1,6 @@ import { collections } from "$lib/server/database"; import { authCondition } from "$lib/server/auth"; import { z } from "zod"; -import { models } from "$lib/server/models"; import { ObjectId } from "mongodb"; export async function GET({ locals, params }) { @@ -20,19 +19,17 @@ export async function GET({ locals, params }) { title: conv.title, updatedAt: conv.updatedAt, modelId: conv.model, - assistantId: conv.assistantId, messages: conv.messages.map((message) => ({ content: message.content, from: message.from, id: message.id, createdAt: message.createdAt, updatedAt: message.updatedAt, - webSearch: message.webSearch, + // websearch removed files: message.files, updates: message.updates, reasoning: message.reasoning, })), - modelTools: models.find((m) => m.id == conv.model)?.tools ?? false, }; return Response.json(res); } else { diff --git a/src/routes/api/conversations/+server.ts b/src/routes/api/conversations/+server.ts index 5806aa6a370f714d96c68a68d34631af09a1b530..03d09450432b728dbd77e565591a5eaa5a5b2e44 100644 --- a/src/routes/api/conversations/+server.ts +++ b/src/routes/api/conversations/+server.ts @@ -1,5 +1,4 @@ import { collections } from "$lib/server/database"; -import { models } from "$lib/server/models"; import { authCondition } from "$lib/server/auth"; import type { Conversation } from "$lib/types/Conversation"; import { CONV_NUM_PER_PAGE } from "$lib/constants/pagination"; @@ -11,11 +10,10 @@ export async function GET({ locals, url }) { .find({ ...authCondition(locals), }) - .project>({ + .project>({ title: 1, updatedAt: 1, model: 1, - assistantId: 1, }) .sort({ updatedAt: -1 }) .skip(p * CONV_NUM_PER_PAGE) @@ -32,8 +30,6 @@ export async function GET({ locals, url }) { updatedAt: conv.updatedAt, model: conv.model, modelId: conv.model, // legacy param iOS - assistantId: conv.assistantId, - modelTools: models.find((m) => m.id == conv.model)?.tools ?? false, })); return Response.json(res); } else { diff --git a/src/routes/api/models/+server.ts b/src/routes/api/models/+server.ts index d29c0253888b69003868e0529055c1bf5fe15772..6a1d41c495537ba5cc5ea117ed63b59cd973075d 100644 --- a/src/routes/api/models/+server.ts +++ b/src/routes/api/models/+server.ts @@ -8,7 +8,7 @@ export async function GET() { name: model.name, websiteUrl: model.websiteUrl ?? "https://huggingface.co", modelUrl: model.modelUrl ?? "https://huggingface.co", - tokenizer: model.tokenizer, + // tokenizer removed in this build datasetName: model.datasetName, datasetUrl: model.datasetUrl, displayName: model.displayName, @@ -18,7 +18,6 @@ export async function GET() { preprompt: model.preprompt ?? "", multimodal: model.multimodal ?? false, unlisted: model.unlisted ?? false, - tools: model.tools ?? false, hasInferenceAPI: model.hasInferenceAPI ?? false, })); return Response.json(res); diff --git a/src/routes/api/tools/+server.ts b/src/routes/api/tools/+server.ts deleted file mode 100644 index a8695146b08d5beae1e7e8afae02b3ac098ebbdf..0000000000000000000000000000000000000000 --- a/src/routes/api/tools/+server.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { config } from "$lib/server/config"; -import { authCondition, requiresUser } from "$lib/server/auth.js"; -import { collections } from "$lib/server/database.js"; -import { editableToolSchema } from "$lib/server/tools/index.js"; -import { generateSearchTokens } from "$lib/utils/searchTokens.js"; -import { ObjectId } from "mongodb"; -import { ReviewStatus } from "$lib/types/Review.js"; -import { error } from "@sveltejs/kit"; -import { usageLimits } from "$lib/server/usageLimits.js"; - -export async function POST({ request, locals }) { - if (config.COMMUNITY_TOOLS !== "true") { - error(403, "Community tools are not enabled"); - } - const body = await request.json(); - - const parse = editableToolSchema.safeParse(body); - - if (!parse.success) { - // Loop through the errors array and create a custom errors array - const errors = parse.error.errors.map((error) => { - return { - field: error.path[0], - message: error.message, - }; - }); - - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - // can only create tools when logged in, IF login is setup - if (!locals.user && requiresUser) { - const errors = [{ field: "description", message: "Must be logged in. Unauthorized" }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const toolCounts = await collections.tools.countDocuments({ createdById: locals.user?._id }); - - if (usageLimits?.tools && toolCounts > usageLimits.tools) { - const errors = [ - { - field: "description", - message: "You have reached the maximum number of tools. Delete some to continue.", - }, - ]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - if (!locals.user || !authCondition(locals)) { - error(401, "Unauthorized"); - } - - const { insertedId } = await collections.tools.insertOne({ - ...parse.data, - type: "community" as const, - _id: new ObjectId(), - createdById: locals.user?._id, - createdByName: locals.user?.username, - createdAt: new Date(), - updatedAt: new Date(), - last24HoursUseCount: 0, - useCount: 0, - review: ReviewStatus.PRIVATE, - searchTokens: generateSearchTokens(parse.data.displayName), - }); - - return new Response(JSON.stringify({ toolId: insertedId.toString() }), { status: 200 }); -} diff --git a/src/routes/api/tools/[toolId]/+server.ts b/src/routes/api/tools/[toolId]/+server.ts deleted file mode 100644 index 76ffc3b9f62edf51606a6d77c11c924f3e5a2809..0000000000000000000000000000000000000000 --- a/src/routes/api/tools/[toolId]/+server.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { config } from "$lib/server/config"; -import { collections } from "$lib/server/database.js"; -import { toolFromConfigs } from "$lib/server/tools/index.js"; -import { ReviewStatus } from "$lib/types/Review"; -import type { CommunityToolDB } from "$lib/types/Tool.js"; -import { ObjectId } from "mongodb"; -import { editableToolSchema } from "$lib/server/tools/index.js"; -import { generateSearchTokens } from "$lib/utils/searchTokens.js"; -import { error } from "@sveltejs/kit"; -import { requiresUser } from "$lib/server/auth"; - -export async function GET({ params }) { - if (config.COMMUNITY_TOOLS !== "true") { - return new Response("Community tools are not enabled", { status: 403 }); - } - - const toolId = params.toolId; - - try { - const configTool = toolFromConfigs.find((el) => el._id.toString() === toolId); - if (configTool) { - return Response.json({ - _id: toolId, - displayName: configTool.displayName, - color: configTool.color, - icon: configTool.icon, - createdByName: undefined, - }); - } else { - // try community tools - const tool = await collections.tools - .findOne({ _id: new ObjectId(toolId) }) - .then((tool) => - tool - ? { - _id: tool._id.toString(), - displayName: tool.displayName, - color: tool.color, - icon: tool.icon, - createdByName: tool.createdByName, - review: tool.review, - } - : undefined - ); - - if (!tool || tool.review !== ReviewStatus.APPROVED) { - return new Response(`Tool "${toolId}" not found`, { status: 404 }); - } - - return Response.json(tool); - } - } catch (e) { - return new Response(`Tool "${toolId}" not found`, { status: 404 }); - } -} - -export async function PATCH({ request, params, locals }) { - const tool = await collections.tools.findOne({ - _id: new ObjectId(params.toolId), - }); - - if (!tool) { - error(404, "Tool not found"); - } - - if (tool.createdById.toString() !== (locals.user?._id ?? locals.sessionId).toString()) { - error(403, "You are not the creator of this tool"); - } - - // can only create tools when logged in, IF login is setup - if (!locals.user && requiresUser) { - const errors = [{ field: "description", message: "Must be logged in. Unauthorized" }]; - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - const body = await request.json(); - - const parse = editableToolSchema.safeParse(body); - - if (!parse.success) { - // Loop through the errors array and create a custom errors array - const errors = parse.error.errors.map((error) => { - return { - field: error.path[0], - message: error.message, - }; - }); - - return new Response(JSON.stringify({ error: true, errors }), { status: 400 }); - } - - // modify the tool - await collections.tools.updateOne( - { _id: tool._id }, - { - $set: { - ...parse.data, - updatedAt: new Date(), - searchTokens: generateSearchTokens(parse.data.displayName), - }, - } - ); - - return new Response(JSON.stringify({ toolId: tool._id.toString() }), { status: 200 }); -} - -export async function DELETE({ params, locals }) { - const tool = await collections.tools.findOne({ _id: new ObjectId(params.toolId) }); - - if (!tool) { - return new Response("Tool not found", { status: 404 }); - } - - if ( - tool.createdById.toString() !== (locals.user?._id ?? locals.sessionId).toString() && - !locals.isAdmin - ) { - return new Response("You are not the creator of this tool", { status: 403 }); - } - - await collections.tools.deleteOne({ _id: tool._id }); - - // Remove the tool from all users' settings - await collections.settings.updateMany( - { - tools: { $in: [tool._id.toString()] }, - }, - { - $pull: { tools: tool._id.toString() }, - } - ); - - // Remove the tool from all assistants - await collections.assistants.updateMany( - { - tools: { $in: [tool._id.toString()] }, - }, - { - $pull: { tools: tool._id.toString() }, - } - ); - - return new Response("Tool deleted", { status: 200 }); -} diff --git a/src/routes/api/tools/[toolId]/report/+server.ts b/src/routes/api/tools/[toolId]/report/+server.ts deleted file mode 100644 index 8faf3223bd8aa6ff2fa94ad4645b0fbd0b273aa6..0000000000000000000000000000000000000000 --- a/src/routes/api/tools/[toolId]/report/+server.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { base } from "$app/paths"; - -import { collections } from "$lib/server/database"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { z } from "zod"; - -import { config } from "$lib/server/config"; -import { sendSlack } from "$lib/server/sendSlack"; -import type { Tool } from "$lib/types/Tool"; - -export async function POST({ params, request, locals, url }) { - // is there already a report from this user for this model ? - const report = await collections.reports.findOne({ - createdBy: locals.user?._id ?? locals.sessionId, - object: "tool", - contentId: new ObjectId(params.toolId), - }); - - if (report) { - return error(400, "Already reported"); - } - - const { reason } = z.object({ reason: z.string().min(1).max(128) }).parse(await request.json()); - - if (!reason) { - return error(400, "Invalid report reason"); - } - - const { acknowledged } = await collections.reports.insertOne({ - _id: new ObjectId(), - contentId: new ObjectId(params.toolId), - object: "tool", - createdBy: locals.user?._id ?? locals.sessionId, - createdAt: new Date(), - updatedAt: new Date(), - reason, - }); - - if (!acknowledged) { - return error(500, "Failed to report tool"); - } - - if (config.WEBHOOK_URL_REPORT_ASSISTANT) { - const prefixUrl = config.PUBLIC_SHARE_PREFIX || `${config.PUBLIC_ORIGIN || url.origin}${base}`; - const toolUrl = `${prefixUrl}/tools/${params.toolId}`; - - const tool = await collections.tools.findOne>( - { _id: new ObjectId(params.toolId) }, - { projection: { displayName: 1, name: 1 } } - ); - - const username = locals.user?.username; - - await sendSlack( - `🔴 Tool <${toolUrl}|${tool?.displayName ?? tool?.name}> reported by ${ - username ? `` : "non-logged in user" - }.\n\n> ${reason}` - ); - } - - return new Response("Tool reported", { status: 200 }); -} diff --git a/src/routes/api/tools/[toolId]/review/+server.ts b/src/routes/api/tools/[toolId]/review/+server.ts deleted file mode 100644 index cfbcd01100ce7050ab0c68b92752235a377a1e78..0000000000000000000000000000000000000000 --- a/src/routes/api/tools/[toolId]/review/+server.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { collections } from "$lib/server/database"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { base } from "$app/paths"; -import { config } from "$lib/server/config"; -import { ReviewStatus } from "$lib/types/Review"; -import { sendSlack } from "$lib/server/sendSlack"; -import { z } from "zod"; - -const schema = z.object({ - status: z.nativeEnum(ReviewStatus), -}); - -export async function PATCH({ params, request, locals, url }) { - const toolId = params.toolId; - - const { status } = schema.parse(await request.json()); - - if (!toolId) { - return error(400, "Tool ID is required"); - } - - const tool = await collections.tools.findOne({ - _id: new ObjectId(toolId), - }); - - if (!tool) { - return error(404, "Tool not found"); - } - - if ( - !locals.user || - (!locals.isAdmin && tool.createdById.toString() !== locals.user._id.toString()) - ) { - return error(403, "Permission denied"); - } - - // only admins can set the status to APPROVED or DENIED - // if the status is already APPROVED or DENIED, only admins can change it - - if ( - (status === ReviewStatus.APPROVED || - status === ReviewStatus.DENIED || - tool.review === ReviewStatus.APPROVED || - tool.review === ReviewStatus.DENIED) && - !locals.isAdmin - ) { - return error(403, "Permission denied"); - } - - const result = await collections.tools.updateOne({ _id: tool._id }, { $set: { review: status } }); - - if (result.modifiedCount === 0) { - return error(500, "Failed to update review status"); - } - - if (status === ReviewStatus.PENDING) { - const prefixUrl = config.PUBLIC_SHARE_PREFIX || `${config.PUBLIC_ORIGIN || url.origin}${base}`; - const toolUrl = `${prefixUrl}/tools/${toolId}`; - - const username = locals.user?.username; - - await sendSlack( - `🟢🛠️ Tool <${toolUrl}|${tool?.displayName}> requested to be featured by ${ - username ? `` : "non-logged in user" - }.` - ); - } - - return new Response("Review status updated", { status: 200 }); -} diff --git a/src/routes/api/tools/search/+server.ts b/src/routes/api/tools/search/+server.ts deleted file mode 100644 index a3cba817a3ec2e29d7250c42fe0844989f7186e1..0000000000000000000000000000000000000000 --- a/src/routes/api/tools/search/+server.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { config } from "$lib/server/config"; -import { collections } from "$lib/server/database.js"; -import { toolFromConfigs } from "$lib/server/tools/index.js"; -import type { BaseTool, CommunityToolDB } from "$lib/types/Tool.js"; -import { generateQueryTokens, generateSearchTokens } from "$lib/utils/searchTokens.js"; -import type { Filter } from "mongodb"; -import { ReviewStatus } from "$lib/types/Review"; -export async function GET({ url }) { - if (config.COMMUNITY_TOOLS !== "true") { - return new Response("Community tools are not enabled", { status: 403 }); - } - - const query = url.searchParams.get("q")?.trim() ?? null; - const queryTokens = !!query && generateQueryTokens(query); - - const filter: Filter = { - ...(queryTokens && { searchTokens: { $all: queryTokens } }), - review: ReviewStatus.APPROVED, - }; - - const matchingCommunityTools = await collections.tools - .find(filter) - .project>({ - _id: 1, - displayName: 1, - color: 1, - icon: 1, - createdByName: 1, - }) - .sort({ useCount: -1 }) - .limit(5) - .toArray(); - - const matchingConfigTools = toolFromConfigs - .filter((tool) => !tool?.isHidden) - .filter((tool) => tool.name !== "websearch") // filter out websearch tool from config tools since its added separately - .filter((tool) => { - if (queryTokens) { - return generateSearchTokens(tool.displayName).some((token) => - queryTokens.some((queryToken) => queryToken.test(token)) - ); - } - return true; - }) - .map((tool) => ({ - _id: tool._id, - displayName: tool.displayName, - color: tool.color, - icon: tool.icon, - createdByName: undefined, - })); - - const tools = [...matchingConfigTools, ...matchingCommunityTools] satisfies Array< - Pick & { createdByName?: string } - >; - - return Response.json(tools.map((tool) => ({ ...tool, _id: tool._id.toString() })).slice(0, 5)); -} diff --git a/src/routes/api/user/assistants/+server.ts b/src/routes/api/user/assistants/+server.ts deleted file mode 100644 index 8e8b66bf7817114f3901f512b092a5b93e06edf1..0000000000000000000000000000000000000000 --- a/src/routes/api/user/assistants/+server.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { authCondition } from "$lib/server/auth"; -import type { Conversation } from "$lib/types/Conversation"; -import { collections } from "$lib/server/database"; -import { ObjectId } from "mongodb"; - -export async function GET({ locals }) { - if (locals.user?._id || locals.sessionId) { - const settings = await collections.settings.findOne(authCondition(locals)); - - const conversations = await collections.conversations - .find(authCondition(locals)) - .sort({ updatedAt: -1 }) - .project>({ - assistantId: 1, - }) - .limit(300) - .toArray(); - - const userAssistants = settings?.assistants?.map((assistantId) => assistantId.toString()) ?? []; - const userAssistantsSet = new Set(userAssistants); - - const assistantIds = [ - ...userAssistants.map((el) => new ObjectId(el)), - ...(conversations.map((conv) => conv.assistantId).filter((el) => !!el) as ObjectId[]), - ]; - - const assistants = await collections.assistants.find({ _id: { $in: assistantIds } }).toArray(); - - const res = assistants - .filter((el) => userAssistantsSet.has(el._id.toString())) - .map((el) => ({ - ...el, - _id: el._id.toString(), - createdById: undefined, - createdByMe: - el.createdById.toString() === (locals.user?._id ?? locals.sessionId).toString(), - })); - - return Response.json(res); - } else { - return Response.json({ message: "Must have session cookie" }, { status: 401 }); - } -} diff --git a/src/routes/assistant/[assistantId]/+page.svelte b/src/routes/assistant/[assistantId]/+page.svelte deleted file mode 100644 index 2202dd1254b2c04d964be785ba1c9d49877b8bf5..0000000000000000000000000000000000000000 --- a/src/routes/assistant/[assistantId]/+page.svelte +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - createConversation(ev.detail)} - {loading} - currentModel={findCurrentModel([...data.models, ...data.oldModels], data.assistant.modelId)} - assistant={data.assistant} - models={data.models} - bind:files -/> diff --git a/src/routes/assistant/[assistantId]/+page.ts b/src/routes/assistant/[assistantId]/+page.ts deleted file mode 100644 index 1f4f4b851cb308e0cd2db15d76bba34d838b2a55..0000000000000000000000000000000000000000 --- a/src/routes/assistant/[assistantId]/+page.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useAPIClient, handleResponse } from "$lib/APIClient"; - -export async function load({ fetch, params }) { - const client = useAPIClient({ fetch }); - - const data = client.assistants({ id: params.assistantId }).get().then(handleResponse); - - await client.assistants({ id: params.assistantId }).follow.post(); - - return { assistant: await data }; -} diff --git a/src/routes/assistant/[assistantId]/thumbnail.png/+server.ts b/src/routes/assistant/[assistantId]/thumbnail.png/+server.ts deleted file mode 100644 index 3513750d0449f70bc2d4ca865c15c30e5af0f8d3..0000000000000000000000000000000000000000 --- a/src/routes/assistant/[assistantId]/thumbnail.png/+server.ts +++ /dev/null @@ -1,83 +0,0 @@ -import ChatThumbnail from "./ChatThumbnail.svelte"; -import { collections } from "$lib/server/database"; -import { error, type RequestHandler } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { render } from "svelte/server"; - -import { Resvg } from "@resvg/resvg-js"; -import satori from "satori"; -import { html } from "satori-html"; - -import InterRegular from "$lib/server/fonts/Inter-Regular.ttf"; -import InterBold from "$lib/server/fonts/Inter-Bold.ttf"; -import sharp from "sharp"; - -export const GET: RequestHandler = (async ({ params }) => { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.assistantId), - }); - - if (!assistant) { - error(404, "Assistant not found."); - } - - let avatar = ""; - const fileId = collections.bucket.find({ filename: assistant._id.toString() }); - const file = await fileId.next(); - if (file) { - avatar = await (async () => { - const fileStream = collections.bucket.openDownloadStream(file?._id); - - const fileBuffer = await new Promise((resolve, reject) => { - const chunks: Uint8Array[] = []; - fileStream.on("data", (chunk) => chunks.push(chunk)); - fileStream.on("error", reject); - fileStream.on("end", () => resolve(Buffer.concat(chunks))); - }); - - return fileBuffer; - })() - .then(async (buf) => sharp(buf).jpeg().toBuffer()) // convert to jpeg bc satori png is really slow - .then(async (buf) => "data:image/jpeg;base64," + buf.toString("base64")); - } - - const renderedComponent = render(ChatThumbnail, { - props: { - name: assistant.name, - description: assistant.description, - createdByName: assistant.createdByName, - avatar, - }, - }); - - const reactLike = html("" + renderedComponent.body); - - const svg = await satori(reactLike, { - width: 1200, - height: 648, - fonts: [ - { - name: "Inter", - data: InterRegular as unknown as ArrayBuffer, - weight: 500, - }, - { - name: "Inter", - data: InterBold as unknown as ArrayBuffer, - weight: 700, - }, - ], - }); - - const png = new Resvg(svg, { - fitTo: { mode: "original" }, - }) - .render() - .asPng(); - - return new Response(png, { - headers: { - "Content-Type": "image/png", - }, - }); -}) satisfies RequestHandler; diff --git a/src/routes/assistant/[assistantId]/thumbnail.png/ChatThumbnail.svelte b/src/routes/assistant/[assistantId]/thumbnail.png/ChatThumbnail.svelte deleted file mode 100644 index b3b93260c2bcb489467fba45a36dd18cd7b2f9cc..0000000000000000000000000000000000000000 --- a/src/routes/assistant/[assistantId]/thumbnail.png/ChatThumbnail.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - -
    -
    - {#if avatar} - avatar - {/if} -
    -

    - - - {@html logo} - - AI assistant -

    -

    - {name} -

    -

    - {description.slice(0, 160)} - {#if description.length > 160}...{/if} -

    -
    - Start chatting -
    -
    -
    - {#if createdByName} -

    - An AI assistant created by {createdByName} -

    - {/if} -
    diff --git a/src/routes/assistants/+page.svelte b/src/routes/assistants/+page.svelte deleted file mode 100644 index 66860bb33114fe1febe6bcc0e473401842edcef9..0000000000000000000000000000000000000000 --- a/src/routes/assistants/+page.svelte +++ /dev/null @@ -1,348 +0,0 @@ - - - - {#if publicConfig.isHuggingChat} - HuggingChat - Assistants - - - - - - {/if} - - -
    -
    -
    -

    Assistants

    - {#if publicConfig.isHuggingChat} -
    - beta -
    - - - - {/if} -
    -

    Popular assistants made by the community

    -
    - - {#if data.isAdmin} - - {/if} - {#if page.data.loginRequired && !data.user} - - {:else} - - Create new assistant - - {/if} -
    - -
    - {#if assistantsCreator && !createdByMe} -
    - {assistantsCreator}'s Assistants - -
    - {#if publicConfig.isHuggingChat} - View {assistantsCreator} - on HF - {/if} - {:else} - - - Community - - {#if data.user?.username} - {data.user.username} - - {/if} - {/if} -
    - - filterOnName(e.currentTarget.value)} - bind:this={filterInputEl} - maxlength="150" - type="search" - aria-label="Filter assistants by name" - /> -
    - -
    - -
    - {#each data.assistants as assistant (assistant._id)} - {@const hasRag = - assistant?.rag?.allowAllDomains || - !!assistant?.rag?.allowedDomains?.length || - !!assistant?.rag?.allowedLinks?.length || - !!assistant?.dynamicPrompt} - - - {:else} - No assistants found - {/each} -
    - -
    -
    diff --git a/src/routes/assistants/+page.ts b/src/routes/assistants/+page.ts deleted file mode 100644 index 9f8e8f04efaa1fe4cfbe6a00d84de0adb6261ff6..0000000000000000000000000000000000000000 --- a/src/routes/assistants/+page.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useAPIClient, handleResponse } from "$lib/APIClient"; - -export const load = async ({ url, fetch }) => { - const client = useAPIClient({ fetch }); - - const data = client.assistants.search - .get({ query: Object.fromEntries(url.searchParams.entries()) }) - .then(handleResponse); - - return data; -}; diff --git a/src/routes/conversation/+server.ts b/src/routes/conversation/+server.ts index fd0ebc6b83e8575454b9eda9cdd595f980d10388..d024318241796f2f46434b2350d8421c516578c1 100644 --- a/src/routes/conversation/+server.ts +++ b/src/routes/conversation/+server.ts @@ -6,11 +6,9 @@ import { base } from "$app/paths"; import { z } from "zod"; import type { Message } from "$lib/types/Message"; import { models, validateModel } from "$lib/server/models"; -import { defaultEmbeddingModel } from "$lib/server/embeddingModels"; import { v4 } from "uuid"; import { authCondition } from "$lib/server/auth"; import { usageLimits } from "$lib/server/usageLimits"; -import { MetricsServer } from "$lib/server/metrics"; export const POST: RequestHandler = async ({ locals, request }) => { const body = await request.text(); @@ -21,7 +19,6 @@ export const POST: RequestHandler = async ({ locals, request }) => { .object({ fromShare: z.string().optional(), model: validateModel(models), - assistantId: z.string().optional(), preprompt: z.string().optional(), }) .safeParse(JSON.parse(body)); @@ -56,7 +53,6 @@ export const POST: RequestHandler = async ({ locals, request }) => { ]; let rootMessageId: Message["id"] = messages[0].id; - let embeddingModel: string; if (values.fromShare) { const conversation = await collections.sharedConversations.findOne({ @@ -67,31 +63,20 @@ export const POST: RequestHandler = async ({ locals, request }) => { error(404, "Conversation not found"); } - title = conversation.title; + // Strip markers from imported titles + title = conversation.title.replace(/<\/?think>/gi, "").trim(); messages = conversation.messages; rootMessageId = conversation.rootMessageId ?? rootMessageId; values.model = conversation.model; values.preprompt = conversation.preprompt; - values.assistantId = conversation.assistantId?.toString(); - embeddingModel = conversation.embeddingModel; } - embeddingModel ??= model.embeddingModel ?? defaultEmbeddingModel.name; - if (model.unlisted) { error(400, "Can't start a conversation with an unlisted model"); } - // get preprompt from assistant if it exists - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(values.assistantId), - }); - - if (assistant) { - values.preprompt = assistant.preprompt; - } else { - values.preprompt ??= model?.preprompt ?? ""; - } + // use provided preprompt or model preprompt + values.preprompt ??= model?.preprompt ?? ""; if (messages && messages.length > 0 && messages[0].from === "system") { messages[0].content = values.preprompt; @@ -99,22 +84,19 @@ export const POST: RequestHandler = async ({ locals, request }) => { const res = await collections.conversations.insertOne({ _id: new ObjectId(), - title: title || "New Chat", + // Always store sanitized titles + title: (title || "New Chat").replace(/<\/?think>/gi, "").trim(), rootMessageId, messages, model: values.model, preprompt: values.preprompt, - assistantId: values.assistantId ? new ObjectId(values.assistantId) : undefined, createdAt: new Date(), updatedAt: new Date(), userAgent: request.headers.get("User-Agent") ?? undefined, - embeddingModel, ...(locals.user ? { userId: locals.user._id } : { sessionId: locals.sessionId }), ...(values.fromShare ? { meta: { fromShareId: values.fromShare } } : {}), }); - MetricsServer.getMetrics().model.conversationsTotal.inc({ model: values.model }); - return new Response( JSON.stringify({ conversationId: res.insertedId.toString(), diff --git a/src/routes/conversation/[id]/+page.svelte b/src/routes/conversation/[id]/+page.svelte index 825a53ca9dd608576fef7e6b27d1d5261bbd953f..f7036043dd9dec69887d025af0e1006dc5cbaad6 100644 --- a/src/routes/conversation/[id]/+page.svelte +++ b/src/routes/conversation/[id]/+page.svelte @@ -6,10 +6,8 @@ import { page } from "$app/state"; import { beforeNavigate, goto, invalidateAll } from "$app/navigation"; import { base } from "$app/paths"; - import { shareConversation } from "$lib/shareConversation"; import { ERROR_MESSAGES, error } from "$lib/stores/errors"; import { findCurrentModel } from "$lib/utils/models"; - import { webSearchParameters } from "$lib/stores/webSearchParameters"; import type { Message } from "$lib/types/Message"; import { MessageReasoningUpdateType, @@ -28,7 +26,6 @@ import type { TreeNode, TreeId } from "$lib/utils/tree/tree"; import "katex/dist/katex.min.css"; import { updateDebouncer } from "$lib/utils/updates.js"; - import { documentParserToolId } from "$lib/utils/toolIds.js"; let { data = $bindable() } = $props(); @@ -247,16 +244,8 @@ throw new Error("Message to write to not found"); } - // disable websearch if assistant is present - const hasAssistant = !!page.data.assistant; const messageUpdatesAbortController = new AbortController(); - let tools = $settings.tools; - - if (!files.some((file) => file.type.startsWith("application/"))) { - tools = $settings.tools?.filter((tool) => tool !== documentParserToolId); - } - const messageUpdatesIterator = await fetchMessageUpdates( page.params.id, { @@ -265,8 +254,6 @@ messageId, isRetry, isContinue, - webSearch: !hasAssistant && !activeModel.tools && $webSearchParameters.useSearch, - tools, files: isRetry ? userMessage?.files : base64Files, }, messageUpdatesAbortController.signal @@ -351,6 +338,12 @@ reasoningLastUpdate = currentTime; } } + } else if (update.type === MessageUpdateType.RouterMetadata) { + // Update router metadata immediately when received + messageToWriteTo.routerMetadata = { + route: update.route, + model: update.model, + }; } } } catch (err) { @@ -371,32 +364,6 @@ } } - async function voteMessage(score: Message["score"], messageId: string) { - let conversationId = page.params.id; - let oldScore: Message["score"] | undefined; - - // optimistic update to avoid waiting for the server - messages = messages.map((message) => { - if (message.id === messageId) { - oldScore = message.score; - return { ...message, score }; - } - return message; - }); - - try { - await fetch(`${base}/conversation/${conversationId}/message/${messageId}/vote`, { - method: "POST", - body: JSON.stringify({ score }), - }); - } catch { - // revert score on any error - messages = messages.map((message) => { - return message.id !== messageId ? message : { ...message, score: oldScore }; - }); - } - } - onMount(async () => { // only used in case of creating new conversations (from the parent POST endpoint) if ($pendingMessage) { @@ -406,27 +373,27 @@ } }); - async function onMessage(event: CustomEvent) { + async function onMessage(content: string) { if (!data.shared) { - await writeMessage({ prompt: event.detail }); + await writeMessage({ prompt: content }); } else { await convFromShared() .then(async (convId) => { await goto(`${base}/conversation/${convId}`, { invalidateAll: true }); }) - .then(async () => await writeMessage({ prompt: event.detail })) + .then(async () => await writeMessage({ prompt: content })) .finally(() => (loading = false)); } } - async function onRetry(event: CustomEvent<{ id: Message["id"]; content?: string }>) { - const lastMsgId = event.detail.id; + async function onRetry(payload: { id: Message["id"]; content?: string }) { + const lastMsgId = payload.id; messagesPath = createMessagesPath(messages, lastMsgId); if (!data.shared) { await writeMessage({ - prompt: event.detail.content, - messageId: event.detail.id, + prompt: payload.content, + messageId: payload.id, isRetry: true, }); } else { @@ -437,8 +404,8 @@ .then( async () => await writeMessage({ - prompt: event.detail.content, - messageId: event.detail.id, + prompt: payload.content, + messageId: payload.id, isRetry: true, }) ) @@ -446,14 +413,14 @@ } } - async function onShowAlternateMsg(event: CustomEvent<{ id: Message["id"] }>) { - const msgId = event.detail.id; + async function onShowAlternateMsg(payload: { id: Message["id"] }) { + const msgId = payload.id; messagesPath = createMessagesPath(messages, msgId); } - async function onContinue(event: CustomEvent<{ id: Message["id"] }>) { + async function onContinue(payload: { id: Message["id"] }) { if (!data.shared) { - await writeMessage({ messageId: event.detail.id, isContinue: true }); + await writeMessage({ messageId: payload.id, isContinue: true }); } else { await convFromShared() .then(async (convId) => { @@ -462,7 +429,7 @@ .then( async () => await writeMessage({ - messageId: event.detail.id, + messageId: payload.id, isContinue: true, }) ) @@ -476,7 +443,6 @@ messages = data.messages; }); - let activeModel = $derived(findCurrentModel([...data.models, ...data.oldModels], data.model)); // create a linear list of `messagesPath` from `messages` that is a tree of threaded messages let messagesPath = $derived(createMessagesPath(messages)); let messagesAlternatives = $derived(createMessagesAlternatives(messages)); @@ -511,13 +477,11 @@ shared={data.shared} preprompt={data.preprompt} bind:files - on:message={onMessage} - on:retry={onRetry} - on:continue={onContinue} - on:showAlternateMsg={onShowAlternateMsg} - on:vote={(event) => voteMessage(event.detail.score, event.detail.id)} - on:share={() => shareConversation(page.params.id, data.title)} - on:stop={async () => { + onmessage={onMessage} + onretry={onRetry} + oncontinue={onContinue} + onshowAlternateMsg={onShowAlternateMsg} + onstop={async () => { await fetch(`${base}/conversation/${page.params.id}/stop-generating`, { method: "POST", }).then((r) => { @@ -533,6 +497,5 @@ }); }} models={data.models} - currentModel={findCurrentModel([...data.models, ...data.oldModels], data.model)} - assistant={data.assistant} + currentModel={findCurrentModel(data.models, data.oldModels, data.model)} /> diff --git a/src/routes/conversation/[id]/+page.ts b/src/routes/conversation/[id]/+page.ts index 0edc09ad6536f419f5ae968e2ff23e2d4e7a3423..82a6a455ae2f303f6ff507d598a7b4056df3b6d7 100644 --- a/src/routes/conversation/[id]/+page.ts +++ b/src/routes/conversation/[id]/+page.ts @@ -2,10 +2,10 @@ import { useAPIClient, handleResponse } from "$lib/APIClient"; import { UrlDependency } from "$lib/types/UrlDependency"; import { redirect } from "@sveltejs/kit"; -export const load = async ({ params, depends, fetch }) => { +export const load = async ({ params, depends, fetch, url }) => { depends(UrlDependency.Conversation); - const client = useAPIClient({ fetch }); + const client = useAPIClient({ fetch, origin: url.origin }); try { return await client.conversations({ id: params.id }).get().then(handleResponse); diff --git a/src/routes/conversation/[id]/+server.ts b/src/routes/conversation/[id]/+server.ts index 894fdf44c7aef0c27d232ce2411ae3c766c773ca..a234053e8b2eb4913a18afacc8e2f3398dbf9c1c 100644 --- a/src/routes/conversation/[id]/+server.ts +++ b/src/routes/conversation/[id]/+server.ts @@ -1,5 +1,4 @@ import { config } from "$lib/server/config"; -import { startOfHour } from "date-fns"; import { authCondition, requiresUser } from "$lib/server/auth"; import { collections } from "$lib/server/database"; import { models, validModelIdSchema } from "$lib/server/models"; @@ -21,11 +20,9 @@ import { buildSubtree } from "$lib/utils/tree/buildSubtree.js"; import { addChildren } from "$lib/utils/tree/addChildren.js"; import { addSibling } from "$lib/utils/tree/addSibling.js"; import { usageLimits } from "$lib/server/usageLimits"; -import { MetricsServer } from "$lib/server/metrics"; import { textGeneration } from "$lib/server/textGeneration"; import type { TextGenerationContext } from "$lib/server/textGeneration/types"; import { logger } from "$lib/server/logger.js"; -import { documentParserToolId } from "$lib/utils/toolIds.js"; export async function POST({ request, locals, params, getClientAddress }) { const id = z.string().parse(params.id); @@ -152,8 +149,6 @@ export async function POST({ request, locals, params, getClientAddress }) { id: messageId, is_retry: isRetry, is_continue: isContinue, - web_search: webSearch, - tools: toolsPreferences, } = z .object({ id: z.string().uuid().refine(isMessageId).optional(), // parent message id to append to for a normal message, or the message id for a retry/continue @@ -165,8 +160,6 @@ export async function POST({ request, locals, params, getClientAddress }) { ), is_retry: z.optional(z.boolean()), is_continue: z.optional(z.boolean()), - web_search: z.optional(z.boolean()), - tools: z.array(z.string()).optional(), files: z.optional( z.array( z.object({ @@ -196,14 +189,6 @@ export async function POST({ request, locals, params, getClientAddress }) { }) ); - // Check for PDF files in the input - const hasPdfFiles = inputFiles?.some((file) => file.mime === "application/pdf") ?? false; - - // Check for existing PDF files in the conversation - const hasPdfInConversation = - conv.messages?.some((msg) => msg.files?.some((file) => file.mime === "application/pdf")) ?? - false; - if (usageLimits?.messageLength && (newPrompt?.length ?? 0) > usageLimits.messageLength) { error(400, "Message too long."); } @@ -352,23 +337,9 @@ export async function POST({ request, locals, params, getClientAddress }) { if (event.token === "") return; messageToWriteTo.content += event.token; - // add to token total - MetricsServer.getMetrics().model.tokenCountTotal.inc({ model: model?.id }); - - // if this is the first token, add to time to first token if (!lastTokenTimestamp) { - MetricsServer.getMetrics().model.timeToFirstToken.observe( - { model: model?.id }, - Date.now() - promptedAt.getTime() - ); lastTokenTimestamp = new Date(); } - - // add to time per token - MetricsServer.getMetrics().model.timePerOutputToken.observe( - { model: model?.id }, - Date.now() - (lastTokenTimestamp ?? promptedAt).getTime() - ); lastTokenTimestamp = new Date(); } else if ( event.type === MessageUpdateType.Reasoning && @@ -380,7 +351,9 @@ export async function POST({ request, locals, params, getClientAddress }) { // Set the title else if (event.type === MessageUpdateType.Title) { - conv.title = event.title; + // Always strip markers from titles when saving + const sanitizedTitle = event.title.replace(/<\/?think>/gi, "").trim(); + conv.title = sanitizedTitle; await collections.conversations.updateOne( { _id: convId }, { $set: { title: conv?.title, updatedAt: new Date() } } @@ -391,12 +364,6 @@ export async function POST({ request, locals, params, getClientAddress }) { else if (event.type === MessageUpdateType.FinalAnswer) { messageToWriteTo.interrupted = event.interrupted; messageToWriteTo.content = initialMessageContent + event.text; - - // add to latency - MetricsServer.getMetrics().model.latency.observe( - { model: model?.id }, - Date.now() - promptedAt.getTime() - ); } // Add file @@ -407,6 +374,16 @@ export async function POST({ request, locals, params, getClientAddress }) { ]; } + // Store router metadata if this is the virtual router (Omni) + else if (event.type === MessageUpdateType.RouterMetadata) { + if (model?.isRouter) { + messageToWriteTo.routerMetadata = { + route: event.route, + model: event.model, + }; + } + } + // Append to the persistent message updates if it's not a stream update if ( event.type !== MessageUpdateType.Stream && @@ -455,14 +432,15 @@ export async function POST({ request, locals, params, getClientAddress }) { messages: messagesForPrompt, assistant: undefined, isContinue: isContinue ?? false, - webSearch: webSearch ?? false, - toolsPreference: [ - ...(toolsPreferences ?? []), - ...(hasPdfFiles || hasPdfInConversation ? [documentParserToolId] : []), // Add document parser tool if PDF files are present - ], promptedAt, ip: getClientAddress(), username: locals.user?.username, + // Force-enable multimodal if user settings say so for this model + forceMultimodal: Boolean( + (await collections.settings.findOne(authCondition(locals)))?.multimodalOverrides?.[ + model.id + ] + ), }; // run the text generation and send updates to the client for await (const event of textGeneration(ctx)) await update(event); @@ -504,16 +482,6 @@ export async function POST({ request, locals, params, getClientAddress }) { }, }); - if (conv.assistantId) { - await collections.assistantStats.updateOne( - { assistantId: conv.assistantId, "date.at": startOfHour(new Date()), "date.span": "hour" }, - { $inc: { count: 1 } }, - { upsert: true } - ); - } - - const metrics = MetricsServer.getMetrics(); - metrics.model.messagesTotal.inc({ model: model?.id }); // Todo: maybe we should wait for the message to be saved before ending the response - in case of errors return new Response(stream, { headers: { @@ -558,9 +526,11 @@ export async function PATCH({ request, locals, params }) { error(404, "Conversation not found"); } - // Only include defined values in the update + // Only include defined values in the update, with title sanitized const updateValues = { - ...(values.title !== undefined && { title: values.title }), + ...(values.title !== undefined && { + title: values.title.replace(/<\/?think>/gi, "").trim(), + }), ...(values.model !== undefined && { model: values.model }), }; diff --git a/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts b/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts index b43b6f257188f14fdde22a41fa70477b672a9809..23c6d1dc7104c22f7717f95bedfb45ba54579f71 100644 --- a/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts +++ b/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts @@ -36,13 +36,6 @@ export async function GET({ params, locals }) { error(404, "Conversation model not found"); } - let assistant; - if (conv.assistantId) { - assistant = await collections.assistants.findOne({ - _id: new ObjectId(conv.assistantId), - }); - } - const messagesUpTo = buildSubtree(conv, messageId); const prompt = await buildPrompt({ @@ -57,10 +50,8 @@ export async function GET({ params, locals }) { return Response.json({ prompt, model: model.name, - assistant: assistant?.name, parameters: { ...model.parameters, - ...(assistant?.generateSettings || {}), return_full_text: false, }, messages: messagesUpTo.map((msg) => ({ @@ -69,9 +60,7 @@ export async function GET({ params, locals }) { createdAt: msg.createdAt, updatedAt: msg.updatedAt, reasoning: msg.reasoning, - updates: msg.updates?.filter( - (u) => (u.type === "webSearch" && u.subtype === "sources") || u.type === "title" - ), + updates: msg.updates?.filter((u) => u.type === "title"), files: msg.files, })), }); diff --git a/src/routes/conversation/[id]/message/[messageId]/vote/+server.ts b/src/routes/conversation/[id]/message/[messageId]/vote/+server.ts deleted file mode 100644 index eb6ada6b7b86e3ec55d857c7fc267545368485ea..0000000000000000000000000000000000000000 --- a/src/routes/conversation/[id]/message/[messageId]/vote/+server.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { authCondition } from "$lib/server/auth"; -import { collections } from "$lib/server/database"; -import { MetricsServer } from "$lib/server/metrics.js"; -import { error } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; -import { z } from "zod"; - -export async function POST({ params, request, locals }) { - const { score } = z - .object({ - score: z.number().int().min(-1).max(1), - }) - .parse(await request.json()); - const conversationId = new ObjectId(params.id); - const messageId = params.messageId; - - // aggregate votes per model in order to detect model performance degradation - const model = await collections.conversations - .findOne( - { - _id: conversationId, - ...authCondition(locals), - }, - { projection: { model: 1 } } - ) - .then((c) => c?.model); - - if (model) { - if (score === 1) { - MetricsServer.getMetrics().model.votesPositive.inc({ model }); - } else { - MetricsServer.getMetrics().model.votesNegative.inc({ model }); - } - } - - const document = await collections.conversations.updateOne( - { - _id: conversationId, - ...authCondition(locals), - "messages.id": messageId, - }, - { - ...(score !== 0 - ? { - $set: { - "messages.$.score": score, - }, - } - : { $unset: { "messages.$.score": "" } }), - } - ); - - if (!document.matchedCount) { - error(404, "Message not found"); - } - - return new Response(); -} diff --git a/src/routes/conversation/[id]/share/+server.ts b/src/routes/conversation/[id]/share/+server.ts index 3997a050809db3f9fabfce54034b9795d685c0df..f15bd510561a2e05b9f449cd4972528f2ab2fa7d 100644 --- a/src/routes/conversation/[id]/share/+server.ts +++ b/src/routes/conversation/[id]/share/+server.ts @@ -38,9 +38,7 @@ export async function POST({ params, locals }) { messages: conversation.messages, title: conversation.title, model: conversation.model, - embeddingModel: conversation.embeddingModel, preprompt: conversation.preprompt, - assistantId: conversation.assistantId, }; await collections.sharedConversations.insertOne(shared); diff --git a/src/routes/login/callback/+server.ts b/src/routes/login/callback/+server.ts index 849c9492f287cbeb3aab6d40873c5d35407c1a9f..0872a88e4f77b19069ddf3304664f5114bb1f5d3 100644 --- a/src/routes/login/callback/+server.ts +++ b/src/routes/login/callback/+server.ts @@ -6,17 +6,23 @@ import { config } from "$lib/server/config"; import JSON5 from "json5"; import { updateUser } from "./updateUser.js"; +const sanitizeJSONEnv = (val: string, fallback: string) => { + const raw = (val ?? "").trim(); + const unquoted = raw.startsWith("`") && raw.endsWith("`") ? raw.slice(1, -1) : raw; + return unquoted || fallback; +}; + const allowedUserEmails = z .array(z.string().email()) .optional() .default([]) - .parse(JSON5.parse(config.ALLOWED_USER_EMAILS)); + .parse(JSON5.parse(sanitizeJSONEnv(config.ALLOWED_USER_EMAILS, "[]"))); const allowedUserDomains = z .array(z.string().regex(/\.\w+$/)) // Contains at least a dot .optional() .default([]) - .parse(JSON5.parse(config.ALLOWED_USER_DOMAINS)); + .parse(JSON5.parse(sanitizeJSONEnv(config.ALLOWED_USER_DOMAINS, "[]"))); export async function GET({ url, locals, cookies, request, getClientAddress }) { const { error: errorName, error_description: errorDescription } = z diff --git a/src/routes/login/callback/updateUser.spec.ts b/src/routes/login/callback/updateUser.spec.ts index 8125c8eff8b88a612aacabd87d37c96f34b14c30..5552472ce28612ad1322386a1dea334fd6c389d5 100644 --- a/src/routes/login/callback/updateUser.spec.ts +++ b/src/routes/login/callback/updateUser.spec.ts @@ -6,7 +6,6 @@ import { ObjectId } from "mongodb"; import { DEFAULT_SETTINGS } from "$lib/types/Settings"; import { defaultModel } from "$lib/server/models"; import { findUser } from "$lib/server/auth"; -import { defaultEmbeddingModel } from "$lib/server/embeddingModels"; const userData = { preferred_username: "new-username", @@ -48,7 +47,7 @@ const insertRandomConversations = async (count: number) => { title: "random title", messages: [], model: defaultModel.id, - embeddingModel: defaultEmbeddingModel.id, + // embedding model removed in this build createdAt: new Date(), updatedAt: new Date(), sessionId: locals.sessionId, @@ -101,7 +100,6 @@ describe("login", () => { userId: user?._id, updatedAt: expect.any(Date), createdAt: expect.any(Date), - ethicsModalAcceptedAt: expect.any(Date), ...DEFAULT_SETTINGS, }); @@ -111,7 +109,6 @@ describe("login", () => { it("should migrate pre-existing settings for pre-existing user", async () => { const { insertedId } = await collections.settings.insertOne({ sessionId: locals.sessionId, - ethicsModalAcceptedAt: new Date(), updatedAt: new Date(), createdAt: new Date(), ...DEFAULT_SETTINGS, @@ -133,7 +130,6 @@ describe("login", () => { userId: user?._id, updatedAt: expect.any(Date), createdAt: expect.any(Date), - ethicsModalAcceptedAt: expect.any(Date), ...DEFAULT_SETTINGS, shareConversationsWithModelAuthors: false, }); diff --git a/src/routes/login/callback/updateUser.ts b/src/routes/login/callback/updateUser.ts index d1e37222d8c1bcc7e0c1b34f3815420dc349422c..a13683a8699e49c768fb879cdc23fc971af7794d 100644 --- a/src/routes/login/callback/updateUser.ts +++ b/src/routes/login/callback/updateUser.ts @@ -179,7 +179,6 @@ export async function updateUser(params: { // if no settings found for user, create default settings await collections.settings.insertOne({ userId, - ethicsModalAcceptedAt: new Date(), updatedAt: new Date(), createdAt: new Date(), ...DEFAULT_SETTINGS, diff --git a/src/routes/models/+page.svelte b/src/routes/models/+page.svelte index 302f36a004f5ffbe46f326bace754db7fdd2587d..94593ec9e57ee8f1523591478e5fdd8066e1bd07 100644 --- a/src/routes/models/+page.svelte +++ b/src/routes/models/+page.svelte @@ -6,8 +6,7 @@ import { page } from "$app/state"; import CarbonHelpFilled from "~icons/carbon/help-filled"; - import CarbonTools from "~icons/carbon/tools"; - import CarbonImage from "~icons/carbon/image"; + import CarbonView from "~icons/carbon/view"; import { useSettingsStore } from "$lib/stores/settings"; interface Props { data: PageData; @@ -18,6 +17,11 @@ const settings = useSettingsStore(); const publicConfig = usePublicConfig(); + + // Local filter state for model search (hyphen/space insensitive) + let modelFilter = $state(""); + const normalize = (s: string) => s.toLowerCase().replace(/[^a-z0-9]+/g, " "); + let queryTokens = $derived(normalize(modelFilter).trim().split(/\s+/).filter(Boolean)); @@ -46,23 +50,34 @@ {/if}

    All models available on {publicConfig.PUBLIC_APP_NAME}

    -
    - {#each data.models.filter((el) => !el.unlisted) as model, index (model.id)} -
    + +
    + {#each data.models + .filter((el) => !el.unlisted) + .filter((el) => { + const haystack = normalize(`${el.id} ${el.name ?? ""} ${el.displayName ?? ""}`); + return queryTokens.every((q) => haystack.includes(q)); + }) as model, index (model.id)} + -
    {#if model.logoUrl} {model.displayName} logo @@ -73,24 +88,14 @@ >
    {/if}
    - {#if model.tools} - - - - {/if} - {#if model.multimodal} + {#if $settings.multimodalOverrides?.[model.id] ?? model.multimodal} - + {/if} {#if model.reasoning} @@ -116,11 +121,11 @@ {/if} {#if model.id === $settings.activeModel} Active - {:else if index === 0} + {:else if index === 0 && model.id === "omni"} @@ -132,10 +137,10 @@ {model.displayName} - + {model.description || "-"} -
    + {/each}
    diff --git a/src/routes/models/[...model]/+page.svelte b/src/routes/models/[...model]/+page.svelte index 0c19c9abf5a1b74daf9a20cbcf5e4df2e1653a16..afca141122311111c9be8c986e009079ae2d952f 100644 --- a/src/routes/models/[...model]/+page.svelte +++ b/src/routes/models/[...model]/+page.svelte @@ -80,9 +80,9 @@ createConversation(ev.detail)} + onmessage={(message) => createConversation(message)} {loading} - currentModel={findCurrentModel([...data.models, ...data.oldModels], modelId)} + currentModel={findCurrentModel(data.models, data.oldModels, modelId)} models={data.models} bind:files /> diff --git a/src/routes/models/[...model]/thumbnail.png/+server.ts b/src/routes/models/[...model]/thumbnail.png/+server.ts index 092b94dfd769e1da26e3b510ff96997841d1a91c..2718d9a5bdb71c65b9d0f1bc305ede50bc9a2b51 100644 --- a/src/routes/models/[...model]/thumbnail.png/+server.ts +++ b/src/routes/models/[...model]/thumbnail.png/+server.ts @@ -24,7 +24,11 @@ export const GET: RequestHandler = (async ({ params }) => { }, }); - const reactLike = html("" + renderedComponent.body); + // satori-html returns a VNode (React-like). satori's TS types expect ReactNode, + // so cast here to satisfy the compiler without pulling in React types. + const reactLike = html( + "" + renderedComponent.body + ) as unknown as never; const svg = await satori(reactLike, { width: 1200, @@ -49,7 +53,8 @@ export const GET: RequestHandler = (async ({ params }) => { .render() .asPng(); - return new Response(png, { + // Return a Uint8Array so BodyInit matches cleanly without generics mismatch + return new Response(new Uint8Array(png), { headers: { "Content-Type": "image/png", }, diff --git a/src/routes/settings/(nav)/+layout.svelte b/src/routes/settings/(nav)/+layout.svelte index 86f5bc804da3013e48eaf5ef61d9d9292a38c912..efe0bb20f5b3814bbaa3238bdf4174f0bd453b76 100644 --- a/src/routes/settings/(nav)/+layout.svelte +++ b/src/routes/settings/(nav)/+layout.svelte @@ -1,25 +1,21 @@
    {#if showContent && browser} @@ -87,12 +108,12 @@ goto(`${base}/settings`); }} > - + {/if} -

    - Settings -

    +

    Settings

    {#if !(showContent && browser && !isDesktop(window))}

    Models

    - {#each data.models.filter((el) => !el.unlisted) as model} + +
    + +
    + + {#each data.models + .filter((el) => !el.unlisted) + .filter((el) => { + const haystack = normalize(`${el.id} ${el.name ?? ""} ${el.displayName ?? ""}`); + return queryTokens.every((q) => haystack.includes(q)); + }) as model} {/each} - {#if data.enableAssistants} -

    - Assistants -

    - -

    - My Assistants -

    - - {#each data.assistants.filter((assistant) => assistant.createdByMe) as assistant} - - {/each} - {#if !data.loginEnabled || (data.loginEnabled && !!data.user)} - - {/if} - - -

    - Other Assistants -

    - - {#each data.assistants.filter((assistant) => !assistant.createdByMe) as assistant} -
    - -
    - -
    -
    - {/each} - - {/if} -
    {/if} {#if showContent}
    {@render children?.()}
    diff --git a/src/routes/settings/(nav)/+server.ts b/src/routes/settings/(nav)/+server.ts index 4ca6177b213e9163ef70c012189253e93d1d8e4b..3222cb58d3ab12f1317a2a3cad92a6f49937b535 100644 --- a/src/routes/settings/(nav)/+server.ts +++ b/src/routes/settings/(nav)/+server.ts @@ -2,50 +2,31 @@ import { collections } from "$lib/server/database"; import { z } from "zod"; import { authCondition } from "$lib/server/auth"; import { DEFAULT_SETTINGS, type SettingsEditable } from "$lib/types/Settings"; -import { toolFromConfigs } from "$lib/server/tools/index.js"; -import { ObjectId } from "mongodb"; export async function POST({ request, locals }) { const body = await request.json(); - const { ethicsModalAccepted, ...settings } = z + const { welcomeModalSeen, ...settings } = z .object({ shareConversationsWithModelAuthors: z .boolean() .default(DEFAULT_SETTINGS.shareConversationsWithModelAuthors), - hideEmojiOnSidebar: z.boolean().default(DEFAULT_SETTINGS.hideEmojiOnSidebar), - ethicsModalAccepted: z.boolean().optional(), + welcomeModalSeen: z.boolean().optional(), activeModel: z.string().default(DEFAULT_SETTINGS.activeModel), customPrompts: z.record(z.string()).default({}), - tools: z.array(z.string()).optional(), + multimodalOverrides: z.record(z.boolean()).default({}), disableStream: z.boolean().default(false), directPaste: z.boolean().default(false), + hidePromptExamples: z.record(z.boolean()).default({}), }) .parse(body) satisfies SettingsEditable; - // make sure all tools exist - // either in db or in config - if (settings.tools) { - const newTools = [ - ...(await collections.tools - .find({ _id: { $in: settings.tools.map((toolId) => new ObjectId(toolId)) } }) - .project({ _id: 1 }) - .toArray() - .then((tools) => tools.map((tool) => tool._id.toString()))), - ...toolFromConfigs - .filter((el) => (settings?.tools ?? []).includes(el._id.toString())) - .map((el) => el._id.toString()), - ]; - - settings.tools = newTools; - } - await collections.settings.updateOne( authCondition(locals), { $set: { ...settings, - ...(ethicsModalAccepted && { ethicsModalAcceptedAt: new Date() }), + ...(welcomeModalSeen && { welcomeModalSeenAt: new Date() }), updatedAt: new Date(), }, $setOnInsert: { diff --git a/src/routes/settings/(nav)/[...model]/+page.svelte b/src/routes/settings/(nav)/[...model]/+page.svelte index a59f1bf02cb7eb00c7b9df3eb4f33e2c800fe01c..f274ebb8f52eb22e03601cd2fa20e2dbba4e4bb0 100644 --- a/src/routes/settings/(nav)/[...model]/+page.svelte +++ b/src/routes/settings/(nav)/[...model]/+page.svelte @@ -3,20 +3,23 @@ import { base } from "$app/paths"; import type { BackendModel } from "$lib/server/models"; + import IconOmni from "$lib/components/icons/IconOmni.svelte"; import { useSettingsStore } from "$lib/stores/settings"; import CopyToClipBoardBtn from "$lib/components/CopyToClipBoardBtn.svelte"; - import TokensCounter from "$lib/components/TokensCounter.svelte"; import CarbonArrowUpRight from "~icons/carbon/arrow-up-right"; - import CarbonLink from "~icons/carbon/link"; + import CarbonCopy from "~icons/carbon/copy"; import CarbonChat from "~icons/carbon/chat"; import CarbonCode from "~icons/carbon/code"; import { goto } from "$app/navigation"; import { usePublicConfig } from "$lib/utils/PublicConfig.svelte"; + import Switch from "$lib/components/Switch.svelte"; const publicConfig = usePublicConfig(); const settings = useSettingsStore(); + type RouterProvider = { provider: string } & Record; + $effect(() => { if ($settings.customPrompts[page.params.model] === undefined) { $settings.customPrompts = { @@ -33,28 +36,74 @@ ); let model = $derived(page.data.models.find((el: BackendModel) => el.id === page.params.model)); + let providerList: RouterProvider[] = $derived((model?.providers ?? []) as RouterProvider[]); + + // Initialize multimodal override for this model if not set yet + $effect(() => { + if (!$settings.multimodalOverrides) { + $settings.multimodalOverrides = {}; + } + const modelId = page.params.model; + if ($settings.multimodalOverrides[modelId] === undefined && model) { + // Default to the model's advertised capability + $settings.multimodalOverrides = { + ...$settings.multimodalOverrides, + [modelId]: !!model.multimodal, + }; + } + }); + + // Ensure hidePromptExamples has an entry for this model so the switch can bind safely + $effect(() => { + if (!$settings.hidePromptExamples) { + $settings.hidePromptExamples = {}; + } + const modelId = page.params.model; + if ($settings.hidePromptExamples[modelId] === undefined) { + $settings.hidePromptExamples = { + ...$settings.hidePromptExamples, + [modelId]: false, + }; + } + });
    -
    -

    - {page.params.model} +
    +

    + {model.displayName}

    {#if model.description} -

    +

    {model.description}

    {/if}
    -
    + + - -
    + {#if model?.isRouter} +

    + Omni routes your messages to the best underlying model + depending on your request. +

    + {/if}
    -

    System Prompt

    +

    System Prompt

    {#if hasCustomPreprompt} {/if}
    + - {#if model.tokenizer && $settings.customPrompts[page.params.model]} - + +
    +
    +
    +
    +
    + Supports image inputs (multimodal) +
    +

    + Enable image uploads and send images to this model. +

    +
    + +
    + + {#if model?.isRouter} +
    +
    +
    + Hide prompt examples +
    +

    + Hide the prompt suggestions above the chat input. +

    +
    + +
    + {/if} +
    +
    + + {#if model.providers?.length} +
    +
    +
    + Providers serving this model +
    +

    + Your requests for this model will be routed through one of the available providers. +

    +
    +
      + {#each providerList as prov, i (prov.provider || i)} +
    • + + {#if prov.provider} + {prov.provider} logo + {/if} + {prov.provider} + +
    • + {/each} +
    +
    {/if} +
    diff --git a/src/routes/settings/(nav)/application/+page.svelte b/src/routes/settings/(nav)/application/+page.svelte index 4aa9d1454b5a22fac0c4a72c52a8b3e71cd7a64b..850d3e4a651c2618ad36e8988bd1620e08966a42 100644 --- a/src/routes/settings/(nav)/application/+page.svelte +++ b/src/routes/settings/(nav)/application/+page.svelte @@ -10,23 +10,53 @@ import { base } from "$app/paths"; import { page } from "$app/state"; import { usePublicConfig } from "$lib/utils/PublicConfig.svelte"; - import { useAPIClient } from "$lib/APIClient"; + import { useAPIClient, handleResponse } from "$lib/APIClient"; + import { onMount } from "svelte"; + import { browser } from "$app/environment"; + import { getThemePreference, setTheme, type ThemePreference } from "$lib/switchTheme"; const publicConfig = usePublicConfig(); let settings = useSettingsStore(); const client = useAPIClient(); + + let OPENAI_BASE_URL: string | null = null; + onMount(async () => { + try { + const cfg = await client.debug.config.get().then(handleResponse); + OPENAI_BASE_URL = (cfg as { OPENAI_BASE_URL?: string }).OPENAI_BASE_URL || null; + } catch (e) { + // ignore if debug endpoint is unavailable + } + }); + + let themePref: ThemePreference = browser ? getThemePreference() : "system"; -
    -

    Application Settings

    +
    +

    + Application Settings +

    + + {#if OPENAI_BASE_URL !== null} +
    + API Base URL: + {OPENAI_BASE_URL} +
    + {/if} {#if !!publicConfig.PUBLIC_COMMIT_SHA} -
    +
    Latest deployment {publicConfig.PUBLIC_COMMIT_SHA.slice(0, 7)} {/if} {#if page.data.isAdmin} -

    You are an admin.

    +

    + Admin mode +

    {/if} -
    - {#if publicConfig.PUBLIC_APP_DATA_SHARING === "1"} - +
    +
    +
    + {#if publicConfig.PUBLIC_APP_DATA_SHARING === "1"} +
    +
    +
    + Share with model authors +
    +

    + Sharing your data helps improve open models over time. +

    +
    + +
    + {/if} -

    - Sharing your data will help improve the training data and make open models better over time. -

    - {/if} - +
    +
    +
    + Disable streaming tokens +
    +

    + Show responses only when complete. +

    +
    + +
    - +
    +
    +
    + Paste text directly +
    +

    + Paste long text directly into chat instead of a file. +

    +
    + +
    - +
    -
    +
    Share your feedback on HuggingChat {#if publicConfig.isHuggingChat} About & Privacy {/if} @@ -112,7 +200,7 @@ }); }} type="submit" - class="flex items-center underline decoration-gray-300 underline-offset-2 hover:decoration-gray-700" + class="flex items-center underline decoration-red-200 underline-offset-2 hover:decoration-red-500 dark:decoration-red-900 dark:hover:decoration-red-700" >Delete all conversations
    diff --git a/src/routes/settings/(nav)/assistants/[assistantId]/+page.svelte b/src/routes/settings/(nav)/assistants/[assistantId]/+page.svelte deleted file mode 100644 index 0c6a97fffb2ae45a587db6773f0eed1b9ba3aa9b..0000000000000000000000000000000000000000 --- a/src/routes/settings/(nav)/assistants/[assistantId]/+page.svelte +++ /dev/null @@ -1,418 +0,0 @@ - - -{#if displayReportModal} - (displayReportModal = false)} - reportUrl={`${base}/api/assistant/${assistant?._id}/report`} - /> -{/if} -
    -
    -
    - {#if assistant?.avatar} - Avatar - {:else} -
    - {assistant?.name[0]} -
    - {/if} -
    - -
    -
    -

    - {assistant?.name} -

    - - {#if hasRag} - - - - {/if} - public -
    - - {#if assistant?.description} -

    - {assistant.description} -

    - {/if} - -

    - Model: {assistant?.modelId} - Created by - - {assistant?.createdByName} - -

    -
    -
    - -
    - {#if assistant?.createdByMe} - Edit - - { - fetch(`${base}/api/assistant/${assistant?._id}`, { - method: "DELETE", - }).then((r) => { - if (r.ok) { - goto(`${base}/settings/assistants`, { invalidateAll: true }); - } else { - console.error(r); - $error = r.statusText; - } - }); - }} - > - - - {:else} -
    { - fetch(`${base}/api/assistant/${assistant?._id}/subscribe`, { - method: "DELETE", - }).then((r) => { - if (r.ok) { - goto(`${base}/settings/assistants`, { invalidateAll: true }); - } else { - console.error(r); - $error = r.statusText; - } - }); - }} - > - -
    - - {#if !assistant?.reported} - - {:else} - - {/if} - {/if} - {#if data?.isAdmin} - {assistant?.review?.toLocaleUpperCase()} - - {#if !assistant?.createdByMe} -
    { - fetch(`${base}/api/assistant/${assistant?._id}`, { - method: "DELETE", - }).then((r) => { - if (r.ok) { - goto(`${base}/settings/assistants`, { invalidateAll: true }); - } else { - console.error(r); - $error = r.statusText; - } - }); - }} - > - -
    - {/if} - {#if assistant?.review === ReviewStatus.PRIVATE} -
    setFeatured(ReviewStatus.APPROVED)}> - -
    - {/if} - {#if assistant?.review === ReviewStatus.PENDING} -
    setFeatured(ReviewStatus.APPROVED)}> - -
    -
    setFeatured(ReviewStatus.DENIED)}> - -
    - {/if} - {#if assistant?.review === ReviewStatus.APPROVED || assistant?.review === ReviewStatus.DENIED} -
    setFeatured(ReviewStatus.PRIVATE)}> - -
    - {/if} - {/if} - {#if assistant?.createdByMe && assistant?.review === ReviewStatus.PRIVATE} -
    { - const confirmed = confirm( - "Are you sure you want to request this assistant to be featured? Make sure you have tried the assistant and that it works as expected. " - ); - - if (!confirmed) { - return; - } - - setFeatured(ReviewStatus.PENDING); - }} - > - -
    - {/if} -
    -
    -
    - -
    -

    Direct URL

    - -

    Share this link for people to use your assistant.

    - -
    - - -
    - Copy -
    -
    -
    -
    - - -
    -

    System Instructions

    -
    - {#if assistant?.dynamicPrompt} - {#each prepromptTags as tag} - {#if (tag.startsWith("{{") && tag.endsWith("}}") && (tag.includes("get=") || tag.includes("post=") || tag.includes("url="))) || tag.includes("today")} - {@const url = tag.match(/(?:get|post|url)=(.*?)}}/)?.[1] ?? ""} - - {tag} - {:else} - {tag} - {/if} - {/each} - {:else} - {assistant?.preprompt} - {/if} -
    - - {#if assistant?.tools?.length} -
    -
    - - - -

    Tools

    -
    -

    - This Assistant has access to the following tools: -

    -
      - {#each assistant.tools as tool} - - {/each} -
    -
    - {/if} - {#if hasRag} -
    -
    - - - -

    Internet Access

    -
    - {#if assistant?.rag?.allowAllDomains} -

    - This Assistant uses Web Search to find information on Internet. -

    - {:else if !!assistant?.rag?.allowedDomains && assistant?.rag?.allowedDomains.length} -

    - This Assistant can use Web Search on the following domains: -

    -
      - {#each assistant?.rag?.allowedDomains as domain} -
    • - {domain} -
    • - {/each} -
    - {:else if !!assistant?.rag?.allowedLinks && assistant?.rag?.allowedLinks.length} -

    This Assistant can browse the following links:

    -
      - {#each assistant?.rag?.allowedLinks as link} -
    • - {link} -
    • - {/each} -
    - {/if} - {#if assistant?.dynamicPrompt} -

    - This Assistant has dynamic prompts enabled and can make requests to external services. -

    - {/if} -
    - {/if} -
    -
    diff --git a/src/routes/settings/(nav)/assistants/[assistantId]/ReportModal.svelte b/src/routes/settings/(nav)/assistants/[assistantId]/ReportModal.svelte deleted file mode 100644 index 3ce4766044d118febcf6df11da41f12656f36e2c..0000000000000000000000000000000000000000 --- a/src/routes/settings/(nav)/assistants/[assistantId]/ReportModal.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - - -
    { - fetch(`${reportUrl}`, { - method: "POST", - body: JSON.stringify({ reason }), - }).then(() => { - dispatch("close"); - invalidateAll(); - }); - }} - class="w-full min-w-64 p-4" - > - Report content - -

    - Please provide a brief description of why you are reporting this content. -

    - - - -
    - - - -
    -
    -
    diff --git a/src/routes/settings/(nav)/assistants/[assistantId]/avatar.jpg/+server.ts b/src/routes/settings/(nav)/assistants/[assistantId]/avatar.jpg/+server.ts deleted file mode 100644 index 7258dc16673a67d20689da8c970164a12c7d0f71..0000000000000000000000000000000000000000 --- a/src/routes/settings/(nav)/assistants/[assistantId]/avatar.jpg/+server.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { collections } from "$lib/server/database"; -import { error, type RequestHandler } from "@sveltejs/kit"; -import { ObjectId } from "mongodb"; - -export const GET: RequestHandler = async ({ params }) => { - const assistant = await collections.assistants.findOne({ - _id: new ObjectId(params.assistantId), - }); - - if (!assistant) { - error(404, "No assistant found"); - } - - if (!assistant.avatar) { - error(404, "No avatar found"); - } - - const fileId = collections.bucket.find({ filename: assistant._id.toString() }); - - const content = await fileId.next().then(async (file) => { - if (!file?._id) { - error(404, "Avatar not found"); - } - - const fileStream = collections.bucket.openDownloadStream(file?._id); - - const fileBuffer = await new Promise((resolve, reject) => { - const chunks: Uint8Array[] = []; - fileStream.on("data", (chunk) => chunks.push(chunk)); - fileStream.on("error", reject); - fileStream.on("end", () => resolve(Buffer.concat(chunks))); - }); - - return fileBuffer; - }); - - return new Response(content, { - headers: { - "Content-Type": "image/jpeg", - "Content-Security-Policy": - "default-src 'none'; script-src 'none'; style-src 'none'; sandbox;", - }, - }); -}; diff --git a/src/routes/settings/(nav)/assistants/[assistantId]/edit/+page.svelte b/src/routes/settings/(nav)/assistants/[assistantId]/edit/+page.svelte deleted file mode 100644 index 1b0ac21b3a129c79602ac268469c9fae4a7b4144..0000000000000000000000000000000000000000 --- a/src/routes/settings/(nav)/assistants/[assistantId]/edit/+page.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/src/routes/settings/(nav)/assistants/new/+page.svelte b/src/routes/settings/(nav)/assistants/new/+page.svelte deleted file mode 100644 index b6f29a85c732f80fd50d2cde4062aef1dccc82d4..0000000000000000000000000000000000000000 --- a/src/routes/settings/(nav)/assistants/new/+page.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/routes/settings/+layout.svelte b/src/routes/settings/+layout.svelte index a548043553171a7d558c76c534c48fe0c07f1985..14d82106b461eb3d4259895abda78fbb73a86655 100644 --- a/src/routes/settings/+layout.svelte +++ b/src/routes/settings/+layout.svelte @@ -24,15 +24,16 @@ goto(previousPage)} - width="h-[95dvh] w-[90dvw] pb-0 overflow-hidden rounded-2xl bg-white shadow-2xl outline-none sm:h-[95dvh] xl:w-[1200px] 2xl:h-[75dvh]" + onclose={() => goto(previousPage)} + disableFly={true} + width="border dark:border-gray-700 h-[95dvh] w-[90dvw] pb-0 overflow-hidden rounded-2xl bg-white shadow-2xl outline-none dark:bg-gray-800 dark:text-gray-200 sm:h-[95dvh] xl:w-[1200px] xl:h-[70dvh]" > {@render children?.()} {#if $settings.recentlySaved}
    - + Saved
    {/if} diff --git a/src/routes/settings/+layout.ts b/src/routes/settings/+layout.ts deleted file mode 100644 index ea15c8df3b203da6d3201d5acc8810870ebd78e5..0000000000000000000000000000000000000000 --- a/src/routes/settings/+layout.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useAPIClient, handleResponse } from "$lib/APIClient"; - -export const load = async ({ parent, fetch }) => { - const client = useAPIClient({ fetch }); - - const reports = await client.user.reports.get().then(handleResponse); - - return { - assistants: (await parent().then((data) => data.assistants)).map((el) => ({ - ...el, - reported: reports.some( - (r) => r.contentId.toString() === el._id.toString() && r.object === "assistant" - ), - })), - }; -}; diff --git a/src/routes/tools/+layout.svelte b/src/routes/tools/+layout.svelte deleted file mode 100644 index 09c492c154f6909114dc728b2ef489d9f3a43d48..0000000000000000000000000000000000000000 --- a/src/routes/tools/+layout.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - - {#if publicConfig.isHuggingChat} - HuggingChat - Tools - - - - - - {/if} - - -{@render children?.()} diff --git a/src/routes/tools/+layout.ts b/src/routes/tools/+layout.ts deleted file mode 100644 index 40ff7f32b065b693a2f5e1ccfdfd64480b20db4a..0000000000000000000000000000000000000000 --- a/src/routes/tools/+layout.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { base } from "$app/paths"; -import { redirect } from "@sveltejs/kit"; - -export async function load({ parent }) { - const { enableCommunityTools } = await parent(); - - if (enableCommunityTools) { - return {}; - } - - redirect(302, `${base}/`); -} diff --git a/src/routes/tools/+page.svelte b/src/routes/tools/+page.svelte deleted file mode 100644 index 3c091e89e9eb738f4337d9221840b03648bfcb29..0000000000000000000000000000000000000000 --- a/src/routes/tools/+page.svelte +++ /dev/null @@ -1,345 +0,0 @@ - - -
    -
    -
    -

    Tools

    - {#if publicConfig.isHuggingChat} -
    - beta -
    - - - - {/if} -
    -

    Popular tools made by the community

    -

    - This feature is experimental. Consider - sharing your feedback with us! -

    -
    - {#if data.isAdmin} - - {/if} - {#if page.data.loginRequired && !data.user} - - {:else} - - Create new tool - - {/if} -
    - -
    - {#if toolsCreator && !createdByMe} -
    - {toolsCreator}'s tools - -
    - {#if publicConfig.isHuggingChat} - View {toolsCreator} - on HF - {/if} - {:else} - - - Active ({page.data.settings?.tools?.length}) - - - - Community - - {#if data.user?.username} - {data.user.username} - - {/if} - {/if} -
    - - filterOnName(e.currentTarget.value)} - bind:this={filterInputEl} - maxlength="150" - type="search" - aria-label="Filter tools by name" - /> -
    - -
    - - {#if !currentModelSupportTools} -
    - You are currently not using a model that supports tools. Activate one - here. -
    - {/if} - -
    - {#each tools as tool} - {@const isActive = (page.data.settings?.tools ?? []).includes(tool._id.toString())} - {@const isOfficial = tool.type === "config"} -
    goto(`${base}/tools/${tool._id.toString()}`)} - onkeydown={(e) => e.key === "Enter" && goto(`${base}/tools/${tool._id.toString()}`)} - role="button" - tabindex="0" - class="relative flex flex-row items-center gap-4 overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 text-center shadow hover:bg-gray-50 hover:shadow-inner dark:bg-gray-950/20 dark:hover:bg-gray-950/40 max-sm:px-4 sm:h-24 {!isOfficial && - tool.review !== ReviewStatus.APPROVED - ? ' border-red-500/30' - : 'dark:border-gray-800/70'}" - class:!border-blue-600={isActive} - > - {#key tool.color + tool.icon} - - {/key} -
    - - - {tool.displayName} - - {#if isActive} - Active - {/if} - - - {tool.baseUrl ?? "Internal tool"} - - -

    - {tool.description} -

    - - {#if !isOfficial && tool.type === "community"} -

    - Added by { - e.stopPropagation(); - bubble("click"); - }} - > - {tool.createdByName} - - - {#if tool.useCount === 1} - 1 run - {:else} - {tool.useCount} runs - {/if} -

    - {:else} -

    - HuggingChat official tool -

    - {/if} -
    -
    - {:else} - {#if activeOnly} - You don't have any active tools. - {:else} - No tools found - {/if} - {/each} -
    - - -
    -
    diff --git a/src/routes/tools/+page.ts b/src/routes/tools/+page.ts deleted file mode 100644 index f47928e3302f4491532d3274c947595dac47d75a..0000000000000000000000000000000000000000 --- a/src/routes/tools/+page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { handleResponse, useAPIClient } from "$lib/APIClient"; - -export const load = async ({ url, fetch }) => { - const client = useAPIClient({ fetch }); - - return client.tools.search - .get({ query: Object.fromEntries(url.searchParams.entries()) }) - .then(handleResponse); -}; diff --git a/src/routes/tools/ToolEdit.svelte b/src/routes/tools/ToolEdit.svelte deleted file mode 100644 index f62c9ab66e7a1bf7d892a0028ed26b70dd5f972f..0000000000000000000000000000000000000000 --- a/src/routes/tools/ToolEdit.svelte +++ /dev/null @@ -1,636 +0,0 @@ - - -
    { - e.preventDefault(); - formLoading = true; - errors = []; - - try { - const body = JSON.stringify(editableTool); - let response: Response; - - if (page.params.toolId) { - response = await fetch(`${base}/api/tools/${page.params.toolId}`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body, - }); - } else { - response = await fetch(`${base}/api/tools`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body, - }); - } - - if (response.ok) { - const { toolId } = await response.json(); - goto(`${base}/tools/${toolId}`, { invalidateAll: true }); - } else if (response.status === 400) { - const data = await response.json(); - errors = data.errors; - } else { - $errorStore = response.statusText; - } - } catch (e) { - $errorStore = (e as Error).message; - } finally { - formLoading = false; - } - }} -> - {#if tool} -

    - {readonly ? "View" : "Edit"} Tool: {tool.displayName} -

    - {#if !readonly} -

    - Modifying an existing tool will propagate the changes to all users. -

    - {/if} - {:else} -

    Create new tool

    -

    - Create and share your own tools. All tools are public -

    - {/if} - -
    -
    -
    - - -
    -
    - {#key editableTool.color + editableTool.icon} - - {/key} -
    - - - - -
    - - - - -

    - Tools allows models that support them to use external application directly via function - calling. Tools must use Hugging Face Gradio Spaces as we detect the input and output types - automatically from the Gradio API. For GPU intensive tool consider using a ZeroGPU Space. -

    -
    -
    -
    -
    -

    Functions

    - {#if editableTool.baseUrl} -

    Choose functions that can be called in your tool.

    - {:else} -

    Start by specifying a Hugging Face Space URL.

    - {/if} - - {#if editableTool.baseUrl} - {#await client["spaces-config"].get({ query: { space: spaceUrl } }).then(handleResponse)} -

    Loading...

    - {:then api} -
    - {#each Object.keys(api["named_endpoints"] ?? {}) as name} - - {/each} -
    - - {#if editableTool.endpoint && api["named_endpoints"][editableTool.endpoint] && !APIloading} - {@const endpoint = api["named_endpoints"][editableTool.endpoint]} -
    -
    -
    - {editableTool.endpoint} - - -
    - -
    -

    Arguments

    -

    - Choose parameters that can be passed to your tool. -

    -
    - -

    - {getError("inputs")} -

    - - {#each editableTool.inputs as input, inputIdx} - {@const parameter = endpoint.parameters.find( - (parameter) => parameter.parameter_name === input.name - )} - -
    -
    - {input.name} - {parameter?.python_type.type} - {#if parameter?.description} -

    - {parameter.description} -

    - {/if} -
    - - - -
    -
    -
    - - {#if input.paramType === "required" || input.paramType === "optional"} - - {/if} - {#if input.paramType === "optional" || input.paramType === "fixed"} - {@const isOptional = input.paramType === "optional"} -
    -
    - {isOptional ? "Default value" : "Value"} -

    - {#if isOptional} - The tool will use this value by default but the model can specify a - different one. - {:else} - The tool will use this value and it cannot be changed. - {/if} -

    -
    - {#if input.paramType === "optional"} - - {:else} - - {/if} -
    - {/if} - {#if input.type === "file"} - - {/if} - -
    - {/each} - -
    -
    -

    Output options

    -

    - Choose what value your tool will return and how -

    -
    - - - - -
    -
    -
    - {:else if APIloading} -

    Loading API...

    - {:else if !api["named_endpoints"]} -

    - No endpoints found in this space. Try another one. -

    - {/if} - {:catch rejected} -

    {JSON.parse(rejected.message).value}

    - {/await} - {/if} -
    -
    - - {#if !readonly} - - {/if} -
    -
    -
    -
    diff --git a/src/routes/tools/ToolInputComponent.svelte b/src/routes/tools/ToolInputComponent.svelte deleted file mode 100644 index c643ba10a7b84f4e97d76c5efceb5ccc99e01257..0000000000000000000000000000000000000000 --- a/src/routes/tools/ToolInputComponent.svelte +++ /dev/null @@ -1,100 +0,0 @@ - - -{#if type === "str" && typeof innerValue === "string"} - -{:else if type === "int" && typeof innerValue === "number"} - { - const value = e.currentTarget.value; - if (value === "" || isNaN(parseInt(value))) { - innerValue = previousValue; - e.currentTarget.value = previousValue.toString(); - return; - } else { - innerValue = parseFloat(value); - previousValue = innerValue; - } - }} - value={innerValue} - /> -{:else if type === "float" && typeof innerValue === "number"} - { - const value = e.currentTarget.value; - if (value === "" || isNaN(parseFloat(value))) { - innerValue = previousValue; - e.currentTarget.value = previousValue.toString(); - return; - } else { - innerValue = parseFloat(value); - previousValue = innerValue; - } - }} - value={innerValue} - /> -{:else if type === "bool" && typeof innerValue === "boolean"} - - -{:else if type.startsWith("Literal[") && typeof innerValue === "string"} - {@const options = type - .slice(8, -1) - .split(",") - .map((option) => option.trim().replaceAll("'", ""))} - -{:else} - {innerValue}-{typeof innerValue} -{/if} diff --git a/src/routes/tools/[toolId]/+layout.ts b/src/routes/tools/[toolId]/+layout.ts deleted file mode 100644 index dfc75c0642caf9a45cede8e57af195f00cdfc316..0000000000000000000000000000000000000000 --- a/src/routes/tools/[toolId]/+layout.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useAPIClient, handleResponse } from "$lib/APIClient"; - -export const load = async ({ params, fetch }) => { - const client = useAPIClient({ fetch }); - - const data = client - .tools({ - id: params.toolId, - }) - .get() - .then(handleResponse); - - return { tool: await data }; -}; diff --git a/src/routes/tools/[toolId]/+page.svelte b/src/routes/tools/[toolId]/+page.svelte deleted file mode 100644 index 2b51f60c600ee80c2fdb4f471912c4286a1d6bf9..0000000000000000000000000000000000000000 --- a/src/routes/tools/[toolId]/+page.svelte +++ /dev/null @@ -1,337 +0,0 @@ - - -{#if displayReportModal} - (displayReportModal = false)} - reportUrl={`${base}/api/tools/${data.tool?._id}/report`} - /> -{/if} - - goto(previousPage)} width="min-w-xl" closeButton> -
    -
    -
    -
    - {#key data.tool.color + data.tool.icon} - - {/key} -
    - -
    -
    -

    - {data.tool.displayName} -

    - public -
    - - {#if data.tool?.baseUrl} - {#if data.tool.baseUrl.startsWith("https://")} -

    - {data.tool.baseUrl} -

    - {:else} - - {data.tool.baseUrl} - - {/if} - {/if} - - {#if data.tool.type === "community"} -

    - Added by - - {data.tool?.createdByName} - - - {#if data.tool.useCount === 1} - 1 run - {:else} - {data.tool.useCount} runs - {/if} -

    - {/if} - -
    -
    - {#if currentModelSupportTools} - - {:else} - - {/if} -
    - {#if data.tool?.createdByMe} - Edit - -
    { - fetch(`${base}/api/tools/${data.tool?._id}`, { - method: "DELETE", - }).then((r) => { - if (r.ok) { - goto(`${base}/tools`, { invalidateAll: true }); - } else { - console.error(r); - $error = r.statusText; - } - }); - }} - > - -
    - {:else if !!data.tool?.baseUrl} - - View spec - - - {#if !data.tool?.reported} - - {:else} - - {/if} - {/if} - {#if data?.isAdmin} - {data.tool?.review?.toLocaleUpperCase()} - - {#if !data.tool?.createdByMe} -
    { - fetch(`${base}/api/tools/${data.tool?._id}`, { - method: "DELETE", - }).then((r) => { - if (r.ok) { - goto(`${base}/tools`, { invalidateAll: true }); - } else { - console.error(r); - $error = r.statusText; - } - }); - }} - > - -
    - {/if} - {#if data.tool?.review === ReviewStatus.PRIVATE} -
    setFeatured(ReviewStatus.APPROVED)}> - -
    - {/if} - {#if data.tool?.review === ReviewStatus.PENDING} -
    setFeatured(ReviewStatus.APPROVED)}> - -
    -
    setFeatured(ReviewStatus.DENIED)}> - -
    - {/if} - {#if data.tool?.review === ReviewStatus.APPROVED || data.tool?.review === ReviewStatus.DENIED} -
    setFeatured(ReviewStatus.PRIVATE)}> - -
    - {/if} - {/if} - {#if data.tool?.createdByMe && data.tool?.review === ReviewStatus.PRIVATE} -
    { - const confirmed = confirm( - "Are you sure you want to request this tool to be featured? Make sure you have tried the tool and that it works as expected. We will review your request once submitted." - ); - - if (!confirmed) { - return; - } - - setFeatured(ReviewStatus.PENDING); - }} - > - -
    - {/if} -
    -
    -
    - {#if !currentModelSupportTools} - - You are currently not using a model that supports tools. Activate one - here. - - {:else} -

    - Tools are applications that the model can choose to call while you are chatting with it. -

    - {/if} - {#if data.tool.description} -
    -

    Description

    -

    {data.tool.description}

    -
    - {/if} - -
    -

    Direct URL

    - -

    Share this link with people to use your tool.

    -
    -
    - -
    - -
    - Copy -
    -
    -
    -
    -
    -
    -
    -
    diff --git a/src/routes/tools/[toolId]/edit/+page.svelte b/src/routes/tools/[toolId]/edit/+page.svelte deleted file mode 100644 index 3391d0d28ea8a03725e1448c382814058cbde19a..0000000000000000000000000000000000000000 --- a/src/routes/tools/[toolId]/edit/+page.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - window.history.back()} - width="h-[95dvh] w-[90dvw] overflow-hidden rounded-2xl bg-white shadow-2xl outline-none sm:h-[85dvh] xl:w-[1200px] 2xl:h-[75dvh]" - closeButton -> - { - window.history.back(); - }} - /> - diff --git a/src/routes/tools/new/+page.svelte b/src/routes/tools/new/+page.svelte deleted file mode 100644 index 2aedd25649af88021b6bd844a82c920c31641395..0000000000000000000000000000000000000000 --- a/src/routes/tools/new/+page.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - window.history.back()} - width="h-[95dvh] w-[90dvw] overflow-hidden rounded-2xl bg-white shadow-2xl outline-none sm:h-[85dvh] xl:w-[1200px] 2xl:h-[75dvh]" -> - window.history.back()} /> - diff --git a/src/styles/main.css b/src/styles/main.css index 55a970baaa96e3c7a8158937c7f5c49c90a52010..0a1b8c99d676314219d27d4aa3c04e3ce1e4cc03 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -10,7 +10,7 @@ } .active-model { - @apply border-blue-500 bg-blue-500/5 hover:bg-blue-500/10; + @apply border-black dark:border-white; } .file-hoverable { @@ -27,9 +27,38 @@ } @layer utilities { + /* your existing utilities */ .scrollbar-custom { @apply scrollbar-thin scrollbar-track-transparent scrollbar-thumb-black/10 scrollbar-thumb-rounded-full scrollbar-w-1 hover:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/10 dark:hover:scrollbar-thumb-white/20; } + + /* Rounded top/bottom caps for vertical scrollbars (Chrome/Edge/Safari) */ + .scrollbar-custom::-webkit-scrollbar-track { + @apply rounded-full bg-clip-padding; /* clip bg to padding so caps look round */ + /* space for the end caps — tweak with Tailwind spacing */ + border-top: theme("spacing.2") solid transparent; /* 0.5rem */ + border-bottom: theme("spacing.2") solid transparent; /* 0.5rem */ + } + + /* Rounded left/right caps for horizontal scrollbars */ + .scrollbar-custom::-webkit-scrollbar-track:horizontal { + @apply rounded-full bg-clip-padding; + border-left: theme("spacing.2") solid transparent; + border-right: theme("spacing.2") solid transparent; + border-top-width: 0; + border-bottom-width: 0; + } + + /* .scrollbar-custom { + @apply scrollbar-thin scrollbar-track-transparent scrollbar-thumb-black/10 scrollbar-thumb-rounded-full scrollbar-w-1 hover:scrollbar-thumb-black/20 dark:scrollbar-thumb-white/10 dark:hover:scrollbar-thumb-white/20; + } */ + .prose hr { + @apply my-4; + } + + .prose strong { + @apply font-medium; + } } .katex-display { diff --git a/static/chatui/apple-touch-icon.png b/static/chatui/apple-touch-icon.png index 8d739ac80519f3a3ef84410759f8f5daa553a2a2..5df34e0eee864ad0a7d576cccc7924fed0c79db2 100644 --- a/static/chatui/apple-touch-icon.png +++ b/static/chatui/apple-touch-icon.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38ce30784eebfed8f3ddb6759cb95685a8c2b00f3a93b2d13d8358e7c5e3d0e4 -size 1609 +oid sha256:6739ca5eac1ed5ca09d2c50d662a406384072fd509aa7c743ca5be128d839ffa +size 2849 diff --git a/static/chatui/favicon.ico b/static/chatui/favicon.ico index 6038067546406ed9a8b5c0449888129f1c8eb3e7..7310d2fe68f8e6424bdb92850bbc269daa4e43e3 100644 Binary files a/static/chatui/favicon.ico and b/static/chatui/favicon.ico differ diff --git a/static/chatui/favicon.svg b/static/chatui/favicon.svg index 197865e59972001414c32b31fd2eef45d5c5d1c7..72d11947262a4e26c1852022148a3e70c18799a7 100644 --- a/static/chatui/favicon.svg +++ b/static/chatui/favicon.svg @@ -1,3 +1,3 @@ - + diff --git a/static/chatui/icon-128x128.png b/static/chatui/icon-128x128.png index 653cce8ca4f55a2133cf3308b46bd7e3efad419f..e8ffe715ce962044f132586f5bb956b121aaa5e4 100644 --- a/static/chatui/icon-128x128.png +++ b/static/chatui/icon-128x128.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc1cebb3ff19349040c8b41b81a52817a749cd7631e5409cbf7db0c680c64a18 -size 1179 +oid sha256:fc47b7adf57a3a1d3d3c7f6d76a3bd49d99e68b37670c97d66223d75c406d3c3 +size 1960 diff --git a/static/chatui/icon-144x144.png b/static/chatui/icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..607c130a85d144130336121cff65400fa7ea82dd --- /dev/null +++ b/static/chatui/icon-144x144.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c71bf2caee62e69f18476c6e22e9c5eba40d84ba3cf7624f1a874e02a1fb4b8f +size 2268 diff --git a/static/chatui/icon-192x192.png b/static/chatui/icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..e61fdc343a18bda0fb0f8ff5b5329818cf7ff722 --- /dev/null +++ b/static/chatui/icon-192x192.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7fd5bd45c6d3e385ba07207f516bd26a75fca7f17184dc6a944a2d904630434 +size 3037 diff --git a/static/chatui/icon-256x256.png b/static/chatui/icon-256x256.png index e35962db6cc045ed6d40ff9588a1c5437c0a8a0b..262e9e50967d738447f1347b540cad0c6aa9b8aa 100644 --- a/static/chatui/icon-256x256.png +++ b/static/chatui/icon-256x256.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bc6dcb0af8a7acf4e9135e632589f86dfc1b4cff3105a352fc58dddf5575589 -size 2316 +oid sha256:1f368793378ef910d9347a0a711138dc305b897328203113723c5bd59a56e198 +size 4111 diff --git a/static/chatui/icon-36x36.png b/static/chatui/icon-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..28968ef320529aa196144de2be2b886a8bb81056 --- /dev/null +++ b/static/chatui/icon-36x36.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3302f1b13b3ff0657d68b34b13371117e2365b050a7642cfc0765b7ba4ab2432 +size 707 diff --git a/static/chatui/icon-48x48.png b/static/chatui/icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..f503e6a6bc4eb532669e81b5437ad16dc328c9c3 --- /dev/null +++ b/static/chatui/icon-48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:529015c2d10a821845fca90d03184520c79f68e8c461c32510d05e1306189e39 +size 869 diff --git a/static/chatui/icon-512x512.png b/static/chatui/icon-512x512.png index d91e3cf057473e813c8c8cd4fcc6334cc88fa796..01febb23235710a585cd04811c82017e4477437b 100644 --- a/static/chatui/icon-512x512.png +++ b/static/chatui/icon-512x512.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba23f927ad462e43bd6b0c3a20c6acafb8b333bb10cca7dfdd21bcdc364addd2 -size 4808 +oid sha256:c8e4c3fe80f19c00570798ef46b4d6b91f547f7a8585fc984ec7ce0bb1946dcb +size 6352 diff --git a/static/chatui/icon-72x72.png b/static/chatui/icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5d65259e0f04130d808caa895679d3e1c00882 --- /dev/null +++ b/static/chatui/icon-72x72.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d897ce0b9701d4b24401c1ad9d0edb64cc503d5c1e8fd9c723c70519411e8593 +size 1167 diff --git a/static/chatui/icon-96x96.png b/static/chatui/icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..0c92165fb835ba87ac6433e59915615844214698 --- /dev/null +++ b/static/chatui/icon-96x96.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74763fc7782084ad46fc0d1a4a42c293dd666c7002081aea14db1b3e95c3efc3 +size 1489 diff --git a/static/chatui/icon.svg b/static/chatui/icon.svg index 197865e59972001414c32b31fd2eef45d5c5d1c7..72d11947262a4e26c1852022148a3e70c18799a7 100644 --- a/static/chatui/icon.svg +++ b/static/chatui/icon.svg @@ -1,3 +1,3 @@ - + diff --git a/static/chatui/logo.svg b/static/chatui/logo.svg index 73c4c5f74129e827d85c0ce51c9091ae9c4d0bfa..8fb1e74dc919175b14a07eb53f7ad2c8490db60f 100644 --- a/static/chatui/logo.svg +++ b/static/chatui/logo.svg @@ -1,6 +1,3 @@ - - + + diff --git a/static/chatui/manifest.json b/static/chatui/manifest.json index 7b2cd63572d3ac55b0f8adb70db1c2fb76b4e316..4e4fa1dda4d589167054382333f537e10986690f 100644 --- a/static/chatui/manifest.json +++ b/static/chatui/manifest.json @@ -1,22 +1,52 @@ { "background_color": "#ffffff", - "name": "Chat UI", - "short_name": "Chat UI", + "name": "ChatUI", + "short_name": "ChatUI", "display": "standalone", - "start_url": "/", + "start_url": "/chat", "icons": [ { - "src": "/chatui/icon-128x128.png", + "src": "/chat/chatui/icon-36x36.png", + "sizes": "36x36", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-48x48.png", + "sizes": "48x48", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { - "src": "/chatui/icon-256x256.png", + "src": "/chat/chatui/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/chat/chatui/icon-256x256.png", "sizes": "256x256", "type": "image/png" }, { - "src": "/chatui/icon-512x512.png", + "src": "/chat/chatui/icon-512x512.png", "sizes": "512x512", "type": "image/png" } diff --git a/static/huggingchat/favicon.ico b/static/huggingchat/favicon.ico index 8b6ffd928f6e7734ce06e7560f690c0e9e20447a..8360ec6177fd82c2b296a1e447df889fefd34ae2 100644 Binary files a/static/huggingchat/favicon.ico and b/static/huggingchat/favicon.ico differ diff --git a/static/huggingchat/favicon.svg b/static/huggingchat/favicon.svg index 8311a549f98d44cd6f03e883e141b3b86abca7d0..c79e09a8f5d38fb23f9b8109b83a0d80cadc6464 100644 --- a/static/huggingchat/favicon.svg +++ b/static/huggingchat/favicon.svg @@ -1,7 +1,4 @@ - - - - - + + diff --git a/static/huggingchat/icon.svg b/static/huggingchat/icon.svg index abffd8f2bf0ab11e43f370753e32ee8d2b24e5a3..65353d2b5d2c6fc7e6ae58c2aa8803c1edba5414 100644 --- a/static/huggingchat/icon.svg +++ b/static/huggingchat/icon.svg @@ -1,7 +1,4 @@ - - - - - + + diff --git a/static/huggingchat/logo.svg b/static/huggingchat/logo.svg index 49765f64684f6d2465b0e4cf6ecf8017638f8429..c79e09a8f5d38fb23f9b8109b83a0d80cadc6464 100644 --- a/static/huggingchat/logo.svg +++ b/static/huggingchat/logo.svg @@ -1,14 +1,4 @@ - - - - + + + diff --git a/static/huggingchat/providers/cerebras.svg b/static/huggingchat/providers/cerebras.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b49f39828cedd2f71d3316cd8c054930360e281 --- /dev/null +++ b/static/huggingchat/providers/cerebras.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/cohere.svg b/static/huggingchat/providers/cohere.svg new file mode 100644 index 0000000000000000000000000000000000000000..2b7bdf3e94b1f5e5ee992030867528799bb295fc --- /dev/null +++ b/static/huggingchat/providers/cohere.svg @@ -0,0 +1,6 @@ + + diff --git a/static/huggingchat/providers/featherless-ai.svg b/static/huggingchat/providers/featherless-ai.svg new file mode 100644 index 0000000000000000000000000000000000000000..71a3e2dfea52287529a1953703415e8e91a41953 --- /dev/null +++ b/static/huggingchat/providers/featherless-ai.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/fireworks-ai.svg b/static/huggingchat/providers/fireworks-ai.svg new file mode 100644 index 0000000000000000000000000000000000000000..a186e00279a348c6a0698ee8fbe620f86808dfc1 --- /dev/null +++ b/static/huggingchat/providers/fireworks-ai.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/groq.svg b/static/huggingchat/providers/groq.svg new file mode 100644 index 0000000000000000000000000000000000000000..292f7f1617c6fed6ad3434d196214583cd73dd94 --- /dev/null +++ b/static/huggingchat/providers/groq.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/hf-inference.svg b/static/huggingchat/providers/hf-inference.svg new file mode 100644 index 0000000000000000000000000000000000000000..1574634335434e74f63dea11ccdd3eec7ee6f9e3 --- /dev/null +++ b/static/huggingchat/providers/hf-inference.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/hyperbolic.svg b/static/huggingchat/providers/hyperbolic.svg new file mode 100644 index 0000000000000000000000000000000000000000..75c10375887b41a8045f2fdc6448d2dc4ab5b56d --- /dev/null +++ b/static/huggingchat/providers/hyperbolic.svg @@ -0,0 +1,8 @@ + + diff --git a/static/huggingchat/providers/nebius.svg b/static/huggingchat/providers/nebius.svg new file mode 100644 index 0000000000000000000000000000000000000000..071f68afa03c9620366a5bd8a8d20e303be2ad8e --- /dev/null +++ b/static/huggingchat/providers/nebius.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/novita.svg b/static/huggingchat/providers/novita.svg new file mode 100644 index 0000000000000000000000000000000000000000..6e31ea68f40764e87ec27930ddbda439c7b8b821 --- /dev/null +++ b/static/huggingchat/providers/novita.svg @@ -0,0 +1,5 @@ + + diff --git a/static/huggingchat/providers/nscale.svg b/static/huggingchat/providers/nscale.svg new file mode 100644 index 0000000000000000000000000000000000000000..24fff802adda0ddfa8331070bf45de04bc40e452 --- /dev/null +++ b/static/huggingchat/providers/nscale.svg @@ -0,0 +1,7 @@ + + diff --git a/static/huggingchat/providers/sambanova.svg b/static/huggingchat/providers/sambanova.svg new file mode 100644 index 0000000000000000000000000000000000000000..99616318871f8692a7364f4e58bf2ba1459124a2 --- /dev/null +++ b/static/huggingchat/providers/sambanova.svg @@ -0,0 +1,6 @@ + + diff --git a/static/huggingchat/providers/together.svg b/static/huggingchat/providers/together.svg new file mode 100644 index 0000000000000000000000000000000000000000..3d73d5069ad4767b7ea8147bab0605b268470621 --- /dev/null +++ b/static/huggingchat/providers/together.svg @@ -0,0 +1,13 @@ + + diff --git a/static/huggingchat/routes.chat.json b/static/huggingchat/routes.chat.json new file mode 100644 index 0000000000000000000000000000000000000000..2f206119cf3e0ff4969f708ea2c5f21575550670 --- /dev/null +++ b/static/huggingchat/routes.chat.json @@ -0,0 +1,220 @@ +[ + { + "name": "job_app_docs", + "description": "Create ATS‑ready resumes and cover letters aligned to a job posting.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": [ + "deepseek-ai/DeepSeek-V3.1", + "moonshotai/Kimi-K2-Instruct-0905", + "zai-org/GLM-4.5" + ] + }, + { + "name": "email_writing", + "description": "Draft or revise emails with clear tone and a specific CTA.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "google/gemma-3-27b-it"] + }, + { + "name": "social_media_copy", + "description": "Write platform‑specific social captions and short posts for engagement.", + "primary_model": "deepseek-ai/DeepSeek-V3.1", + "fallback_models": ["moonshotai/Kimi-K2-Instruct-0905", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + }, + { + "name": "editing_rewrite", + "description": "Lightly proofread and rephrase text for tone, length, and clarity.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "google/gemma-3-27b-it", "zai-org/GLM-4.5"] + }, + { + "name": "qa_explanations", + "description": "Provide concise answers and plain‑language explanations.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "meta-llama/Llama-3.3-70B-Instruct"] + }, + { + "name": "technical_explanation", + "description": "Explain complex technical topics step‑by‑step with worked examples.", + "primary_model": "deepseek-ai/DeepSeek-R1-0528", + "fallback_models": ["Qwen/QwQ-32B", "moonshotai/Kimi-K2-Instruct-0905"] + }, + { + "name": "essay_writing", + "description": "Plan and write essays from outline to draft; citations on request.", + "primary_model": "Qwen/Qwen3-235B-A22B-Thinking-2507", + "fallback_models": ["deepseek-ai/DeepSeek-R1-0528", "deepseek-ai/DeepSeek-V3.1"] + }, + { + "name": "summarization", + "description": "Condense documents into an abstract, key points, and action items.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": [ + "deepseek-ai/DeepSeek-V3.1", + "meta-llama/Llama-4-Maverick-17B-128E-Instruct" + ] + }, + { + "name": "translation", + "description": "Translate between languages with register and terminology control.", + "primary_model": "CohereLabs/command-a-translate-08-2025", + "fallback_models": ["CohereLabs/aya-expanse-32b", "google/gemma-3-27b-it"] + }, + { + "name": "language_tutoring", + "description": "Interactive language practice with conversation, grammar, vocab, and feedback.", + "primary_model": "CohereLabs/aya-expanse-32b", + "fallback_models": [ + "CohereLabs/aya-expanse-8b", + "google/gemma-3-27b-it", + "meta-llama/Llama-3.3-70B-Instruct" + ] + }, + { + "name": "formal_proof", + "description": "Produce Lean 4 proofs with tactic scripts and subgoals.", + "primary_model": "deepseek-ai/DeepSeek-Prover-V2-671B", + "fallback_models": ["deepseek-ai/DeepSeek-R1-0528", "Qwen/QwQ-32B"] + }, + { + "name": "software_architecture_design", + "description": "Design architectures: views, APIs, data models, and scalability trade‑offs.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "meta-llama/Llama-3.1-405B-Instruct"] + }, + { + "name": "agentic_orchestration", + "description": "Plan and execute tool/API calls with schemas, retries, and recovery.", + "primary_model": "openai/gpt-oss-120b", + "fallback_models": ["zai-org/GLM-4.5", "deepseek-ai/DeepSeek-V3.1"] + }, + { + "name": "code_generation", + "description": "Generate new code, tests, and scaffolds from specs.", + "primary_model": "Qwen/Qwen3-Coder-480B-A35B-Instruct", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "Qwen/Qwen3-Coder-30B-A3B-Instruct"] + }, + { + "name": "frontend_ui", + "description": "Build accessible, responsive UI components and pages.", + "primary_model": "deepseek-ai/DeepSeek-R1-0528", + "fallback_models": ["Qwen/Qwen3-Coder-480B-A35B-Instruct", "zai-org/GLM-4.5"] + }, + { + "name": "code_maintenance", + "description": "Fix bugs and refactor code; add tests.", + "primary_model": "Qwen/Qwen3-Coder-480B-A35B-Instruct", + "fallback_models": [ + "deepseek-ai/DeepSeek-V3.1", + "meta-llama/Llama-4-Maverick-17B-128E-Instruct" + ] + }, + { + "name": "code_review_docs", + "description": "Explain code and write docs, READMEs, and examples.", + "primary_model": "deepseek-ai/DeepSeek-V3.1", + "fallback_models": ["meta-llama/Llama-3.3-70B-Instruct", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + }, + { + "name": "terminal_cli", + "description": "Solve Linux shell tasks with safe, idempotent commands.", + "primary_model": "zai-org/GLM-4.5", + "fallback_models": ["meta-llama/Llama-4-Maverick-17B-128E-Instruct", "Qwen/Qwen3-32B"] + }, + { + "name": "travel_planning", + "description": "Research trips and craft day‑by‑day itineraries with logistics.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": [ + "deepseek-ai/DeepSeek-V3.1", + "meta-llama/Llama-4-Maverick-17B-128E-Instruct" + ] + }, + { + "name": "shopping_recommendations", + "description": "Compare products and recommend ranked picks with rationale.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["zai-org/GLM-4.5", "deepseek-ai/DeepSeek-V3.1"] + }, + { + "name": "meal_planning", + "description": "Create meal plans and recipes by diet, budget, and time.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "google/gemma-3-27b-it"] + }, + { + "name": "decision_support", + "description": "Score options against criteria and recommend a choice.", + "primary_model": "deepseek-ai/DeepSeek-R1-0528", + "fallback_models": ["Qwen/Qwen3-235B-A22B-Thinking-2507", "deepseek-ai/DeepSeek-V3.1"] + }, + { + "name": "career_coaching", + "description": "Guide job search, skill gaps, interviews, and negotiation.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["meta-llama/Llama-3.3-70B-Instruct", "deepseek-ai/DeepSeek-V3.1"] + }, + { + "name": "personal_finance", + "description": "Build budgets, savings plans, and simple tracking schemas.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "Qwen/Qwen3-235B-A22B-Thinking-2507"] + }, + { + "name": "health_wellness_info", + "description": "Provide general health, fitness, sleep, and nutrition information.", + "primary_model": "aaditya/Llama3-OpenBioLLM-70B", + "fallback_models": ["Qwen/Qwen3-235B-A22B-Instruct-2507", "google/gemma-3-27b-it"] + }, + { + "name": "brainstorming_ideas", + "description": "Generate many creative ideas, then help narrow choices.", + "primary_model": "deepseek-ai/DeepSeek-V3.1", + "fallback_models": ["NousResearch/Hermes-4-70B", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + }, + { + "name": "creative_writing", + "description": "Write fiction, poems, jokes, or scripts with style control.", + "primary_model": "moonshotai/Kimi-K2-Instruct-0905", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "meta-llama/Llama-3.3-70B-Instruct"] + }, + { + "name": "interactive_roleplay", + "description": "Run in‑character text adventures and persistent role‑play.", + "primary_model": "NousResearch/Hermes-4-70B", + "fallback_models": ["moonshotai/Kimi-K2-Instruct-0905", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + }, + { + "name": "character_impersonation", + "description": "Act and imitate fictional character voices or invented personas consistently.", + "primary_model": "NousResearch/Hermes-4-70B", + "fallback_models": ["moonshotai/Kimi-K2-Instruct-0905", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + }, + { + "name": "casual_conversation", + "description": "Engage in friendly and open‑ended casual chat.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": ["moonshotai/Kimi-K2-Instruct-0905", "google/gemma-3-27b-it"] + }, + { + "name": "emotional_support", + "description": "Provide compassionate listening and gentle guidance for emotional well-being.", + "primary_model": "Qwen/Qwen3-235B-A22B-Instruct-2507", + "fallback_models": [ + "meta-llama/Llama-4-Maverick-17B-128E-Instruct", + "deepseek-ai/DeepSeek-V3.1" + ] + }, + { + "name": "learning_tutor", + "description": "Teach concepts with step-by-step explanations, examples, and practice.", + "primary_model": "deepseek-ai/DeepSeek-V3.1", + "fallback_models": ["Qwen/Qwen3-235B-A22B-Thinking-2507", "deepseek-ai/DeepSeek-R1-0528"] + }, + { + "name": "structured_data", + "description": "Extract structured JSON from text.", + "primary_model": "zai-org/GLM-4.5", + "fallback_models": ["deepseek-ai/DeepSeek-V3.1", "Qwen/Qwen3-235B-A22B-Instruct-2507"] + } +] diff --git a/svelte.config.js b/svelte.config.js index 98902ccdd033107a22435471ecc3529f61c46712..b4ebc14e503b02315dbfa24d37fcf6ac87fb592d 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -3,7 +3,7 @@ import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; import dotenv from "dotenv"; import { execSync } from "child_process"; -dotenv.config({ path: "./.env.local" }); +dotenv.config({ path: "./.env.local", override: true }); dotenv.config({ path: "./.env" }); function getCurrentCommitSHA() { diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 86884397e45eba930b6088af647be68a8e6b9efc..4cb306418414ade372386c95e516463ff37d79c5 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -2,7 +2,7 @@ const defaultTheme = require("tailwindcss/defaultTheme"); const colors = require("tailwindcss/colors"); /** @type {import('tailwindcss').Config} */ -export default { +module.exports = { darkMode: "class", mode: "jit", content: ["./src/**/*.{html,js,svelte,ts}"], @@ -10,6 +10,13 @@ export default { extend: { colors: { primary: colors[process.env.PUBLIC_APP_COLOR], + gray: { + 600: "#323843", + 700: "#252a33", + 800: "#1b1f27", + 900: "#12151c", + 950: "#07090d", + }, }, fontSize: { xxs: "0.625rem", diff --git a/vite.config.ts b/vite.config.ts index 1cf97135ff3d66a8e636fbe27fa23c3936ae3ba8..36e1ef948d385837c4bab7aa3584cce4eef21f9a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -91,8 +91,15 @@ export default defineConfig({ loadTTFAsArrayBuffer(), ...(shouldCopyLlama ? [copyLlamaFiles()] : []), ], + // Allow external access via ngrok tunnel host + server: { + // Allow any ngrok-free.app subdomain (dynamic tunnels) + // See Vite server.allowedHosts: string[] | true + // Using leading dot matches subdomains per Vite's host check logic + allowedHosts: ["huggingface.ngrok.io"], + }, optimizeDeps: { - include: ["uuid", "@huggingface/transformers", "sharp", "@gradio/client", "clsx"], + include: ["uuid", "sharp", "@gradio/client", "clsx"], }, test: { workspace: [