diff --git a/.github/workflows/ci-production.yml b/.github/workflows/ci-production.yml deleted file mode 100644 index 0d0a0a152..000000000 --- a/.github/workflows/ci-production.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Jan CI Production - -on: - push: - tags: ['v*.*.*'] - -env: - REGISTRY: ghcr.io - HASURA_WORKER_IMAGE_NAME: ${{ github.repository }}/worker - WEB_CLIENT_IMAGE_NAME: ${{ github.repository }}/web-client - -jobs: - build-docker-image: - runs-on: ubuntu-latest - environment: production - permissions: - contents: read - packages: write - steps: - - name: Getting the repo - uses: actions/checkout@v3 - - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Get tag - id: tag - uses: dawidd6/action-get-tag@v1 - - # Build and docker image for app-backend worker - - name: Build docker image for app-backend worker - run: | - cd ./app-backend/worker - docker build -t ${{ env.REGISTRY }}/${{ env.HASURA_WORKER_IMAGE_NAME }}:${{ steps.tag.outputs.tag }} . - docker push ${{ env.REGISTRY }}/${{ env.HASURA_WORKER_IMAGE_NAME }}:${{ steps.tag.outputs.tag }} - - # Get .env for FE - - name: Get .env file for build time - run: cd ./web-client && base64 -d <<< "$ENV_FILE_BASE64" > .env - shell: bash - env: - ENV_FILE_BASE64: ${{ secrets.ENV_FILE_BASE64 }} - - # Build and push docker for web client - - name: Build docker image for web-client - run: | - cd ./web-client - docker build -t ${{ env.REGISTRY }}/${{ env.WEB_CLIENT_IMAGE_NAME }}:${{ steps.tag.outputs.tag }} . - docker push ${{ env.REGISTRY }}/${{ env.WEB_CLIENT_IMAGE_NAME }}:${{ steps.tag.outputs.tag }} diff --git a/.github/workflows/ci-staging.yml b/.github/workflows/ci-staging.yml deleted file mode 100644 index 5f42cef4b..000000000 --- a/.github/workflows/ci-staging.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Jan CI Staging -on: - push: - branches: - - stag - paths: - - 'app-backend/worker/**' # hasura worker source code - - 'web-client/**' # web client source code - -env: - REGISTRY: ghcr.io - HASURA_WORKER_IMAGE_NAME: ${{ github.repository }}/worker - WEB_CLIENT_IMAGE_NAME: ${{ github.repository }}/web-client - -jobs: - build-docker-image: - runs-on: ubuntu-latest - environment: staging - permissions: - contents: read - packages: write - steps: - - name: Getting the repo - uses: actions/checkout@v3 - - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y.%m.%d')" - - # Build docker image for app-backend worker - - name: Build docker image for app-backend worker - if: ${{ contains(github.event.head_commit.added, 'app-backend/worker/') }} - run: | - cd ./app-backend/worker - docker build -t ${{ env.REGISTRY }}/${{ env.HASURA_WORKER_IMAGE_NAME }}:staging-${{ steps.date.outputs.date }}.${{github.run_number}} . - docker push ${{ env.REGISTRY }}/${{ env.HASURA_WORKER_IMAGE_NAME }}:staging-${{ steps.date.outputs.date }}.${{github.run_number}} - - # Get .env for FE - - name: Get .env file for build time - run: cd ./web-client && base64 -d <<< "$ENV_FILE_BASE64" > .env - shell: bash - env: - ENV_FILE_BASE64: ${{ secrets.ENV_FILE_BASE64 }} - - # Build and push docker for web client - - name: Build docker image for web-client - if: ${{ contains(github.event.head_commit.added, 'web-client/') }} - run: | - cd ./web-client - docker build -t ${{ env.REGISTRY }}/${{ env.WEB_CLIENT_IMAGE_NAME }}:staging-${{ steps.date.outputs.date }}.${{github.run_number}} . - docker push ${{ env.REGISTRY }}/${{ env.WEB_CLIENT_IMAGE_NAME }}:staging-${{ steps.date.outputs.date }}.${{github.run_number}} diff --git a/.github/workflows/macos-build-app.yml b/.github/workflows/macos-build-app.yml new file mode 100644 index 000000000..0977d1a6f --- /dev/null +++ b/.github/workflows/macos-build-app.yml @@ -0,0 +1,50 @@ +name: Jan Build MacOS App + +on: + push: + tags: ['v*.*.*'] + +jobs: + build-macos-app: + runs-on: macos-latest + + permissions: + contents: write + steps: + - name: Getting the repo + uses: actions/checkout@v3 + + - name: Installing node + uses: actions/setup-node@v1 + with: + node-version: 20 + + - name: Install jq + uses: dcarbone/install-jq-action@v2.0.1 + + - name: Get tag + id: tag + uses: dawidd6/action-get-tag@v1 + + - name: Update app version base on tag + run: | + if [[ ! "${VERSION_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Tag is not valid!" + exit 1 + fi + jq --arg version "${VERSION_TAG#v}" '.version = $version' electron/package.json > /tmp/package.json + mv /tmp/package.json electron/package.json + env: + VERSION_TAG: ${{ steps.tag.outputs.tag }} + + - name: Install yarn dependencies + run: | + yarn install + yarn build:plugins + + - name: Build and publish app + run: | + yarn build:publish + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.gitignore b/.gitignore index c74d4ba9e..2fd305c0d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,11 @@ # Jan inference models/** error.log -app/electron/core/*/node_modules -app/electron/core/*/dist -app/electron/core/*/package-lock.json +node_modules +package-lock.json *.tgz -app/yarn.lock -app/dist +yarn.lock +dist +build +.DS_Store +electron/renderer diff --git a/KC.md b/KC.md deleted file mode 100644 index 3773e241b..000000000 --- a/KC.md +++ /dev/null @@ -1,28 +0,0 @@ -# Configuring Keycloak theme -Jan comes with a default theme for Keycloak. Extended from [Keywind](https://github.com/lukin/keywind) - -## Select keywind as theme -1. Navigate to http://localhost:8088/admin -2. Sign in with below credentials -``` -username: admin -password: admin -``` -3. Select `hasura` from the top left dropdown box -![Screenshot 2023-09-06 at 15 10 53](https://github.com/janhq/jan/assets/10397206/5e3cf99b-7cd6-43ff-a003-e66aedd8c850) - -4. Select `Realm settings` on left navigation bar and open tab `Themes` -![Screenshot 2023-09-06 at 15 14 05](https://github.com/janhq/jan/assets/10397206/3256b5c4-e3e7-48ef-9c5e-f720b5beeaa8) - -5. On `Login theme` open the drop down box and select `keywind` -![Screenshot 2023-09-06 at 15 15 28](https://github.com/janhq/jan/assets/10397206/c52ba743-d978-4963-9311-cf84b4bb5389) - -6. Save - -**That's it!** - -Open your web browser and navigate to `http://localhost:3000` to access Jan web application. Proceed to `Login` on the top right. - -You should expect the theme as below. If it's does not, try to clear the cache from your browser. - -![Screenshot 2023-09-06 at 15 29 09](https://github.com/janhq/jan/assets/10397206/a80a32e7-633f-4109-90fa-ec223c9d3b17) diff --git a/README.md b/README.md index 2cc915e2c..682be7ca9 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,14 @@ > ⚠️ **Jan is currently in Development**: Expect breaking changes and bugs! -Jan lets you run AI on your own hardware, and with 1-click installs for the latest models. Easy-to-use yet powerful, with helpful tools to monitor and manage software-hardware performance. +Jan lets you run AI on your own hardware, with helpful tools to manage models and monitor your hardware performance. -Jan runs on a wide variety of hardware. We run on consumer-grade GPUs and Mac Minis, as well as datacenter-grade DGX H100 clusters. +In the background, Jan runs [Nitro](https://nitro.jan.ai), a C++ inference engine. It runs various model formats (GGUF/TensorRT) on various hardware (Mac M1/M2/Intel, Windows, Linux, and datacenter-grade Nvidia GPUs) with optional GPU acceleration. -Jan can be run as a server or cloud-native application for enterprise. We offer enterprise plugins for LDAP integration and Audit Logs. Contact us at [hello@jan.ai](mailto:hello@jan.ai) for more details. +> See the Nitro codebase at https://nitro.jan.ai. -Jan is free, [open core](https://en.wikipedia.org/wiki/Open-core_model), and Sustainable Use Licensed. + + ## Demo @@ -34,208 +35,122 @@ Jan is free, [open core](https://en.wikipedia.org/wiki/Open-core_model), and Sus Jan Web GIF

-## Features +## Quicklinks -**Self-Hosted AI** -- [x] Self-hosted Llama2 and LLMs -- [ ] Self-hosted StableDiffusion and Controlnet -- [ ] 1-click installs for Models (coming soon) +- Developer documentation: https://jan.ai/docs (Work in Progress) +- Desktop app: Download at https://jan.ai/ +- Mobile app shell: Download via [App Store](https://apps.apple.com/us/app/jan-on-device-ai-cloud-ais/id6449664703) | [Android](https://play.google.com/store/apps/details?id=com.jan.ai) +- Nitro (C++ AI Engine): https://nitro.jan.ai -**3rd-party AIs** -- [ ] Connect to ChatGPT, Claude via API Key (coming soon) -- [ ] Security policy engine for 3rd-party AIs (coming soon) -- [ ] Pre-flight PII and Sensitive Data checks (coming soon) +## Plugins -**Multi-Device** -- [x] Web App -- [ ] Jan Mobile support for custom Jan server (in progress) -- [ ] Cloud deployments (coming soon) +Jan supports core & 3rd party extensions: -**Organization Tools** -- [x] Multi-user support -- [ ] Audit and Usage logs (coming soon) -- [ ] Compliance and Audit policy (coming soon) +- [x] **LLM chat**: Self-hosted Llama2 and LLMs +- [x] **Model Manager**: 1-click to install, swap, and delete models +- [x] **Storage**: Optionally store your conversation history and other data in SQLite/your storage of choice +- [ ] **3rd-party AIs**: Connect to ChatGPT, Claude via API Key (in progress) +- [ ] **Cross device support**: Mobile & Web support for custom shared servers (in progress) +- [ ] **File retrieval**: User can upload private and run a vectorDB (planned) +- [ ] **Multi-user support**: Share a single server across a team/friends (planned) +- [ ] **Compliance**: Auditing and flagging features (planned) -**Hardware Support** +## Hardware Support -- [x] Nvidia GPUs -- [x] Apple Silicon (in progress) -- [x] CPU support via llama.cpp -- [ ] Nvidia GPUs using TensorRT (in progress) +Nitro provides both CPU and GPU support, via [llama.cpp](https://github.com/ggerganov/llama.cpp) and [TensorRT](https://github.com/NVIDIA/TensorRT), respectively. -## Documentation +- [x] Nvidia GPUs (accelerated) +- [x] Apple M-series (accelerated) +- [x] Linux DEB +- [x] Windows x64 -👋 https://docs.jan.ai (Work in Progress) +Not supported yet: Apple Intel, Linux RPM, Windows x86|ARM64, AMD ROCm -## Installation +> See [developer docs](https://docs.jan.ai/docs/) for detailed installation instructions. -> ⚠️ **Jan is currently in Development**: Expect breaking changes and bugs! +## Installation and Usage -### Step 1: Install Docker +### Pre-requisites +- node >= 20.0.0 +- yarn >= 1.22.0 -Jan is currently packaged as a Docker Compose application. +### Use as complete suite (in progress) +### For interactive development -- Docker ([Installation Instructions](https://docs.docker.com/get-docker/)) -- Docker Compose ([Installation Instructions](https://docs.docker.com/compose/install/)) +Note: This instruction is tested on MacOS only. -### Step 2: Clone Repo +1. **Clone the Repository:** -```bash -git clone https://github.com/janhq/jan.git -cd jan + ``` + git clone https://github.com/janhq/jan + git checkout feature/hackathon-refactor-jan-into-electron-app + cd jan + ``` + +2. **Install dependencies:** + + ``` + yarn install + + # Packing base plugins + yarn build:plugins + ``` + +4. **Run development and Using Jan Desktop** + + ``` + yarn dev + ``` + This will start the development server and open the desktop app. + In this step, there are a few notification about installing base plugin, just click `OK` and `Next` to continue. + +### For production build + + ```bash + # Do step 1 and 2 in previous section + git clone https://github.com/janhq/jan + cd jan + yarn install + yarn build:plugins + + # Build the app + yarn build + ``` + + This will build the app MacOS m1/m2 for production (with code signing already done) and put the result in `dist` folder. + + + +## Contributing + +Contributions are welcome! Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file + +```sh +# From the root, run: +yarn install + +yarn build:plugins + +yarn dev ``` -### Step 3: Configure `.env` +> See [developer docs]() for guidelines on how to contribute to this project. -We provide a sample `.env` file that you can use to get started. +## License -```shell -cp sample.env .env -``` +Jan is free, [open core](https://en.wikipedia.org/wiki/Open-core_model), and Sustainable Use Licensed. -You will need to set the following `.env` variables +## Acknowledgements -```shell -# TODO: Document .env variables -``` - -### Step 4: Install Models - -> Note: These step will change soon as we will be switching to [Nitro](https://github.com/janhq/nitro), an Accelerated Inference Server written in C++ - -#### Step 4.1: Install Mamba - -> For complete Mambaforge installation instructions, see [miniforge repo](https://github.com/conda-forge/miniforge) - -Install Mamba to handle native python binding (which can yield better performance on Mac M/ NVIDIA) - -```bash -curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-$(uname)-$(uname -m).sh" -bash Mambaforge-$(uname)-$(uname -m).sh -rm Mambaforge-$(uname)-$(uname -m).sh - -# Create environment -conda create -n jan python=3.9.16 -conda activate jan -``` - -Uninstall any previous versions of `llama-cpp-python` -```bash -pip uninstall llama-cpp-python -y -``` - -#### Step 4.2: Install `llama-cpp-python` - -> Note: This step will change soon once [Nitro](https://github.com/janhq/nitro) (our accelerated inference server written in C++) is released - -- On Mac - -```bash -# See https://github.com/abetlen/llama-cpp-python/blob/main/docs/install/macos.md -CMAKE_ARGS="-DLLAMA_METAL=on" FORCE_CMAKE=1 pip install -U llama-cpp-python --no-cache-dir -pip install 'llama-cpp-python[server]' -``` - -- On Linux with NVIDIA GPU Hardware Acceleration - -```bash -# See https://github.com/abetlen/llama-cpp-python#installation-with-hardware-acceleration -CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install llama-cpp-python -pip install 'llama-cpp-python[server]' -``` - -- On Linux with Intel/ AMD CPU (support for AVX-2/ AVX-512) - -```bash -CMAKE_ARGS="-DLLAMA_BLAS=ON -DLLAMA_BLAS_VENDOR=OpenBLAS" FORCE_CMAKE=1 pip install llama-cpp-python -pip install 'llama-cpp-python[server]' -``` - -We recommend that Llama2-7B (4-bit quantized) as a basic model to get started. - -You will need to download the models to the `models` folder at root level. - -```shell -# Downloads model (~4gb) -# Download time depends on your internet connection and HuggingFace's bandwidth -# In this part, please head over to any source contains `.gguf` format model - https://huggingface.co/models?search=gguf -wget https://huggingface.co/TheBloke/Llama-2-7B-GGUF/resolve/main/llama-2-7b.Q4_0.gguf -P models -``` - -- Run the model in host machine -```bash -# Please change the value of --model key as your corresponding model path -# The --n_gpu_layers 1 means using acclerator (can be Metal on Mac, NVIDIA GPU on on linux with NVIDIA GPU) -# This service will run at `http://localhost:8000` in host level -# The backend service inside docker compose will connect to this service by using `http://host.docker.internal:8000` -python3 -m llama_cpp.server --model models/llama-2-7b.Q4_0.gguf --n_gpu_layers 1 -``` - -### Step 5: `docker compose up` - -Jan utilizes Docker Compose to run all services: - -```shell -docker compose up -d # Detached mode -``` - -The table below summarizes the services and their respective URLs and credentials. - -| Service | Container Name | URL and Port | Credentials | -| ------------------------------------------------ | -------------------- | --------------------- | ---------------------------------------------------------------------------------- | -| Jan Web | jan-web-* | http://localhost:3000 | Set in `conf/keycloak_conf/example-realm.json`
- Default Username / Password | -| [Hasura](https://hasura.io) (Backend) | jan-graphql-engine-* | http://localhost:8080 | Set in `conf/sample.env_app-backend`
- `HASURA_GRAPHQL_ADMIN_SECRET` | -| [Keycloak](https://www.keycloak.org/) (Identity) | jan-keycloak-* | http://localhost:8088 | Set in `.env`
- `KEYCLOAK_ADMIN`
- `KEYCLOAK_ADMIN_PASSWORD` | | -| PostgresDB | jan-postgres-* | http://localhost:5432 | Set in `.env` | - -### Step 6: Configure Keycloak - -- [ ] Refactor [Keycloak Instructions](KC.md) into main README.md -- [ ] Changing login theme - -### Step 7: Use Jan - -- Launch the web application via `http://localhost:3000`. -- Login with default user (username: `username`, password: `password`) - -### Step 8: Deploying to Production - -- [ ] TODO - -## About Jan - -Jan is a commercial company with a [Fair Code](https://faircode.io/) business model. This means that while we are open-source and can used for free, we require commercial licenses for specific use cases (e.g. hosting Jan as a service). - -We are a team of engineers passionate about AI, productivity and the future of work. We are funded through consulting contracts and enterprise licenses. Feel free to reach out to us! - -### Repo Structure - -Jan comprises of several repositories: - -| Repo | Purpose | -| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Jan](https://github.com/janhq/jan) | AI Platform to run AI in the enterprise. Easy-to-use for users, and packed with useful organizational and compliance features. | -| [Jan Mobile](https://github.com/janhq/jan-react-native) | Mobile App that can be pointed to a custom Jan server. | -| [Nitro](https://github.com/janhq/nitro) | Inference Engine that runs AI on different types of hardware. Offers popular API formats (e.g. OpenAI, Clipdrop). Written in C++ for blazing fast performance | - -### Architecture - -Jan builds on top of several open-source projects: +Jan builds on top of other open-source projects: +- [llama.cpp](https://github.com/ggerganov/llama.cpp) +- [TensorRT](https://github.com/NVIDIA/TensorRT) - [Keycloak Community](https://github.com/keycloak/keycloak) (Apache-2.0) -- [Hasura Community Edition](https://github.com/hasura/graphql-engine) (Apache-2.0) -We may re-evaluate this in the future, given different customer requirements. +## Contact - -### Contributing - -Contributions are welcome! Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute to this project. - -Please note that Jan intends to build a sustainable business that can provide high quality jobs to its contributors. If you are excited about our mission and vision, please contact us to explore opportunities. - -### Contact - -- For support: please file a Github ticket -- For questions: join our Discord [here](https://discord.gg/FTk2MvZwJH) -- For long form inquiries: please email hello@jan.ai +- Bugs & requests: file a Github ticket +- For discussion: join our Discord [here](https://discord.gg/FTk2MvZwJH) +- For business inquiries: email hello@jan.ai +- For jobs: please email hr@jan.ai diff --git a/app-backend/.gitignore b/app-backend/.gitignore deleted file mode 100644 index 4caef3e61..000000000 --- a/app-backend/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -.env -.env_postgresql -worker/node_modules/.mf diff --git a/app-backend/README.md b/app-backend/README.md deleted file mode 100644 index 0c693253b..000000000 --- a/app-backend/README.md +++ /dev/null @@ -1,59 +0,0 @@ -## Jan Backend - -A Hasura Data API Platform designed to provide APIs for client interaction with the Language Model (LLM) through chat or the generation of art using Stable Diffusion. It is encapsulated within a Docker container for easy local deployment - -## Quickstart -1. Run docker up - -```bash -docker compose up -``` - -2. Install [HasuraCLI](https://hasura.io/docs/latest/hasura-cli/overview/) - -3. Open Hasura Console - -```bash -cd hasura && hasura console -``` - -4. Apply Migration - -```bash -hasura migrate apply -``` - -5. Apply Metadata - -```bash -hasura metadata apply -``` - -6. Apply seeds - -```bash -hasura seed apply -``` - -## Hasura One Click Deploy -Use this URL to deploy this app to Hasura Cloud - -[![Hasura Deploy](https://hasura.io/deploy-button.svg)](https://cloud.hasura.io/deploy?github_repo=https://github.com/janhq/app-backend/&hasura_dir=/hasura) - -[One-click deploy docs](https://hasura.io/docs/latest/getting-started/getting-started-cloud/) - -## Modify schema & model -[Hasura Tutorials](https://hasura.io/docs/latest/resources/tutorials/index/) - -## Events & Workers - -Serverless function (Cloudflare worker) to stream llm message & update - -Readmore about Hasura Events here: -> https://hasura.io/docs/latest/event-triggers/serverless/ - -## Deploy Worker -```bash -npx wrangler deploy -``` -[Cloudflare Worker Guide](https://developers.cloudflare.com/workers/get-started/guide/) \ No newline at end of file diff --git a/app-backend/docker-compose.yml b/app-backend/docker-compose.yml deleted file mode 100644 index 5f60468e0..000000000 --- a/app-backend/docker-compose.yml +++ /dev/null @@ -1,52 +0,0 @@ -version: "3.6" -services: - postgres: - image: postgres:13 - restart: always - volumes: - - db_data:/var/lib/postgresql/data - env_file: - - .env_postgresql - graphql-engine: - image: hasura/graphql-engine:v2.31.0.cli-migrations-v3 - ports: - - "8080:8080" - restart: always - env_file: - - .env - volumes: - - ./hasura/migrations:/migrations - - ./hasura/metadata:/metadata - depends_on: - data-connector-agent: - condition: service_healthy - - data-connector-agent: - image: hasura/graphql-data-connector:v2.31.0 - restart: always - ports: - - 8081:8081 - environment: - QUARKUS_LOG_LEVEL: ERROR # FATAL, ERROR, WARN, INFO, DEBUG, TRACE - ## https://quarkus.io/guides/opentelemetry#configuration-reference - QUARKUS_OPENTELEMETRY_ENABLED: "false" - ## QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_ENDPOINT: http://jaeger:4317 - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8081/api/v1/athena/health"] - interval: 5s - timeout: 10s - retries: 5 - start_period: 5s - worker: - build: - context: ./worker - dockerfile: ./Dockerfile - restart: always - environment: - - "NODE_ENV=development" - volumes: - - ./worker:/worker - ports: - - "8787:8787" -volumes: - db_data: diff --git a/app-backend/hasura/config.yaml b/app-backend/hasura/config.yaml deleted file mode 100644 index d13faa054..000000000 --- a/app-backend/hasura/config.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: 3 -endpoint: http://localhost:8080 -admin_secret: myadminsecretkey -metadata_directory: metadata -actions: - kind: synchronous - handler_webhook_baseurl: http://localhost:3000 diff --git a/app-backend/hasura/metadata/actions.graphql b/app-backend/hasura/metadata/actions.graphql deleted file mode 100644 index 4b8328f43..000000000 --- a/app-backend/hasura/metadata/actions.graphql +++ /dev/null @@ -1,20 +0,0 @@ -type Mutation { - imageGeneration( - input: ImageGenerationInput! - ): ImageGenerationOutput -} - -input ImageGenerationInput { - prompt: String! - neg_prompt: String! - model: String! - seed: Int! - steps: Int! - width: Int! - height: Int! -} - -type ImageGenerationOutput { - url: String! -} - diff --git a/app-backend/hasura/metadata/actions.yaml b/app-backend/hasura/metadata/actions.yaml deleted file mode 100644 index 2b1580711..000000000 --- a/app-backend/hasura/metadata/actions.yaml +++ /dev/null @@ -1,33 +0,0 @@ -actions: - - name: imageGeneration - definition: - kind: synchronous - handler: '{{HASURA_ACTION_STABLE_DIFFUSION_URL}}' - timeout: 1800 - request_transform: - body: - action: transform - template: |- - { - "prompt": {{$body.input.input.prompt}}, - "neg_prompt": {{$body.input.input.neg_prompt}}, - "unet_model": {{$body.input.input.model}}, - "seed": {{$body.input.input.seed}}, - "steps": {{$body.input.input.steps}}, - "width": {{$body.input.input.width}}, - "height": {{$body.input.input.height}} - } - method: POST - query_params: {} - template_engine: Kriti - url: '{{$base_url}}/inferences/txt2img' - version: 2 - permissions: - - role: user -custom_types: - enums: [] - input_objects: - - name: ImageGenerationInput - objects: - - name: ImageGenerationOutput - scalars: [] diff --git a/app-backend/hasura/metadata/allow_list.yaml b/app-backend/hasura/metadata/allow_list.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/allow_list.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/api_limits.yaml b/app-backend/hasura/metadata/api_limits.yaml deleted file mode 100644 index 0967ef424..000000000 --- a/app-backend/hasura/metadata/api_limits.yaml +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/app-backend/hasura/metadata/backend_configs.yaml b/app-backend/hasura/metadata/backend_configs.yaml deleted file mode 100644 index 1266c8d5c..000000000 --- a/app-backend/hasura/metadata/backend_configs.yaml +++ /dev/null @@ -1,11 +0,0 @@ -dataconnector: - athena: - uri: http://data-connector-agent:8081/api/v1/athena - mariadb: - uri: http://data-connector-agent:8081/api/v1/mariadb - mysql8: - uri: http://data-connector-agent:8081/api/v1/mysql - oracle: - uri: http://data-connector-agent:8081/api/v1/oracle - snowflake: - uri: http://data-connector-agent:8081/api/v1/snowflake diff --git a/app-backend/hasura/metadata/cron_triggers.yaml b/app-backend/hasura/metadata/cron_triggers.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/cron_triggers.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/databases/databases.yaml b/app-backend/hasura/metadata/databases/databases.yaml deleted file mode 100644 index b420475e7..000000000 --- a/app-backend/hasura/metadata/databases/databases.yaml +++ /dev/null @@ -1,9 +0,0 @@ -- name: jandb - kind: postgres - configuration: - connection_info: - database_url: - from_env: PG_DATABASE_URL - isolation_level: read-committed - use_prepared_statements: false - tables: "!include jandb/tables/tables.yaml" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_collection_products.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_collection_products.yaml deleted file mode 100644 index 955361aed..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_collection_products.yaml +++ /dev/null @@ -1,43 +0,0 @@ -table: - name: collection_products - schema: public -array_relationships: - - name: collections - using: - manual_configuration: - column_mapping: - collection_id: id - insertion_order: null - remote_table: - name: collections - schema: public - - name: products - using: - manual_configuration: - column_mapping: - product_id: id - insertion_order: null - remote_table: - name: products - schema: public -select_permissions: - - role: public - permission: - columns: - - created_at - - updated_at - - collection_id - - id - - product_id - filter: {} - comment: "" - - role: user - permission: - columns: - - created_at - - updated_at - - collection_id - - id - - product_id - filter: {} - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_collections.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_collections.yaml deleted file mode 100644 index c84847f1c..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_collections.yaml +++ /dev/null @@ -1,36 +0,0 @@ -table: - name: collections - schema: public -array_relationships: - - name: collection_products - using: - manual_configuration: - column_mapping: - id: collection_id - insertion_order: null - remote_table: - name: collection_products - schema: public -select_permissions: - - role: public - permission: - columns: - - slug - - description - - name - - created_at - - updated_at - - id - filter: {} - comment: "" - - role: user - permission: - columns: - - slug - - description - - name - - created_at - - updated_at - - id - filter: {} - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_conversations.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_conversations.yaml deleted file mode 100644 index 41637a39b..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_conversations.yaml +++ /dev/null @@ -1,68 +0,0 @@ -table: - name: conversations - schema: public -object_relationships: - - name: conversation_product - using: - manual_configuration: - column_mapping: - product_id: id - insertion_order: null - remote_table: - name: products - schema: public -array_relationships: - - name: conversation_messages - using: - manual_configuration: - column_mapping: - id: conversation_id - insertion_order: null - remote_table: - name: messages - schema: public -insert_permissions: - - role: user - permission: - check: - user_id: - _eq: X-Hasura-User-Id - columns: - - last_image_url - - last_text_message - - product_id - - user_id - comment: "" -select_permissions: - - role: user - permission: - columns: - - last_image_url - - last_text_message - - user_id - - created_at - - updated_at - - id - - product_id - filter: - user_id: - _eq: X-Hasura-User-Id - comment: "" -update_permissions: - - role: user - permission: - columns: - - last_image_url - - last_text_message - filter: - user_id: - _eq: X-Hasura-User-Id - check: null - comment: "" -delete_permissions: - - role: user - permission: - filter: - user_id: - _eq: X-Hasura-User-Id - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_message_medias.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_message_medias.yaml deleted file mode 100644 index 1f223b01a..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_message_medias.yaml +++ /dev/null @@ -1,68 +0,0 @@ -table: - name: message_medias - schema: public -object_relationships: - - name: media_message - using: - manual_configuration: - column_mapping: - message_id: id - insertion_order: null - remote_table: - name: messages - schema: public -insert_permissions: - - role: user - permission: - check: - media_message: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - columns: - - media_url - - message_id - - mime_type - comment: "" -select_permissions: - - role: user - permission: - columns: - - mime_type - - media_url - - created_at - - updated_at - - id - - message_id - filter: - media_message: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - comment: "" -update_permissions: - - role: user - permission: - columns: - - mime_type - - media_url - - created_at - - updated_at - - id - - message_id - filter: - media_message: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - check: null - comment: "" -delete_permissions: - - role: user - permission: - filter: - media_message: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_messages.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_messages.yaml deleted file mode 100644 index eb0d06b79..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_messages.yaml +++ /dev/null @@ -1,86 +0,0 @@ -table: - name: messages - schema: public -object_relationships: - - name: message_conversation - using: - manual_configuration: - column_mapping: - conversation_id: id - insertion_order: null - remote_table: - name: conversations - schema: public -array_relationships: - - name: message_medias - using: - manual_configuration: - column_mapping: - id: message_id - insertion_order: null - remote_table: - name: message_medias - schema: public -insert_permissions: - - role: user - permission: - check: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - columns: - - content - - conversation_id - - message_sender_type - - message_type - - prompt_cache - - sender - - sender_avatar_url - - sender_name - - status - comment: "" -select_permissions: - - role: user - permission: - columns: - - content - - conversation_id - - created_at - - id - - message_sender_type - - message_type - - sender - - sender_avatar_url - - sender_name - - status - - updated_at - filter: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - comment: "" -update_permissions: - - role: user - permission: - columns: - - content - - message_sender_type - - message_type - - sender - - sender_avatar_url - - sender_name - - status - filter: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - check: null - comment: "" -delete_permissions: - - role: user - permission: - filter: - message_conversation: - user_id: - _eq: X-Hasura-User-Id - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_product_prompts.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_product_prompts.yaml deleted file mode 100644 index 8a0f9e90b..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_product_prompts.yaml +++ /dev/null @@ -1,43 +0,0 @@ -table: - name: product_prompts - schema: public -array_relationships: - - name: products - using: - manual_configuration: - column_mapping: - product_id: id - insertion_order: null - remote_table: - name: products - schema: public - - name: prompts - using: - manual_configuration: - column_mapping: - prompt_id: id - insertion_order: null - remote_table: - name: prompts - schema: public -select_permissions: - - role: public - permission: - columns: - - created_at - - updated_at - - id - - product_id - - prompt_id - filter: {} - comment: "" - - role: user - permission: - columns: - - created_at - - updated_at - - id - - product_id - - prompt_id - filter: {} - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_products.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_products.yaml deleted file mode 100644 index f38873115..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_products.yaml +++ /dev/null @@ -1,65 +0,0 @@ -table: - name: products - schema: public -array_relationships: - - name: product_collections - using: - manual_configuration: - column_mapping: - id: product_id - insertion_order: null - remote_table: - name: collection_products - schema: public - - name: product_prompts - using: - manual_configuration: - column_mapping: - id: product_id - insertion_order: null - remote_table: - name: product_prompts - schema: public -select_permissions: - - role: public - permission: - columns: - - nsfw - - slug - - inputs - - outputs - - author - - description - - greeting - - image_url - - long_description - - name - - source_url - - technical_description - - version - - created_at - - updated_at - - id - filter: {} - comment: "" - - role: user - permission: - columns: - - nsfw - - slug - - inputs - - outputs - - author - - description - - greeting - - image_url - - long_description - - name - - source_url - - technical_description - - version - - created_at - - updated_at - - id - filter: {} - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/public_prompts.yaml b/app-backend/hasura/metadata/databases/jandb/tables/public_prompts.yaml deleted file mode 100644 index 81cb8aadb..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/public_prompts.yaml +++ /dev/null @@ -1,36 +0,0 @@ -table: - name: prompts - schema: public -array_relationships: - - name: prompt_products - using: - manual_configuration: - column_mapping: - id: prompt_id - insertion_order: null - remote_table: - name: product_prompts - schema: public -select_permissions: - - role: public - permission: - columns: - - slug - - content - - image_url - - created_at - - updated_at - - id - filter: {} - comment: "" - - role: user - permission: - columns: - - slug - - content - - image_url - - created_at - - updated_at - - id - filter: {} - comment: "" diff --git a/app-backend/hasura/metadata/databases/jandb/tables/tables.yaml b/app-backend/hasura/metadata/databases/jandb/tables/tables.yaml deleted file mode 100644 index f541617f9..000000000 --- a/app-backend/hasura/metadata/databases/jandb/tables/tables.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- "!include public_collection_products.yaml" -- "!include public_collections.yaml" -- "!include public_conversations.yaml" -- "!include public_message_medias.yaml" -- "!include public_messages.yaml" -- "!include public_product_prompts.yaml" -- "!include public_products.yaml" -- "!include public_prompts.yaml" diff --git a/app-backend/hasura/metadata/graphql_schema_introspection.yaml b/app-backend/hasura/metadata/graphql_schema_introspection.yaml deleted file mode 100644 index 61a4dcac2..000000000 --- a/app-backend/hasura/metadata/graphql_schema_introspection.yaml +++ /dev/null @@ -1 +0,0 @@ -disabled_for_roles: [] diff --git a/app-backend/hasura/metadata/inherited_roles.yaml b/app-backend/hasura/metadata/inherited_roles.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/inherited_roles.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/metrics_config.yaml b/app-backend/hasura/metadata/metrics_config.yaml deleted file mode 100644 index 0967ef424..000000000 --- a/app-backend/hasura/metadata/metrics_config.yaml +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/app-backend/hasura/metadata/network.yaml b/app-backend/hasura/metadata/network.yaml deleted file mode 100644 index 0967ef424..000000000 --- a/app-backend/hasura/metadata/network.yaml +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/app-backend/hasura/metadata/opentelemetry.yaml b/app-backend/hasura/metadata/opentelemetry.yaml deleted file mode 100644 index 0967ef424..000000000 --- a/app-backend/hasura/metadata/opentelemetry.yaml +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/app-backend/hasura/metadata/query_collections.yaml b/app-backend/hasura/metadata/query_collections.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/query_collections.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/remote_schemas.yaml b/app-backend/hasura/metadata/remote_schemas.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/remote_schemas.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/rest_endpoints.yaml b/app-backend/hasura/metadata/rest_endpoints.yaml deleted file mode 100644 index fe51488c7..000000000 --- a/app-backend/hasura/metadata/rest_endpoints.yaml +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/app-backend/hasura/metadata/version.yaml b/app-backend/hasura/metadata/version.yaml deleted file mode 100644 index 0a70affa4..000000000 --- a/app-backend/hasura/metadata/version.yaml +++ /dev/null @@ -1 +0,0 @@ -version: 3 diff --git a/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/down.sql b/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/down.sql deleted file mode 100644 index df0f0d344..000000000 --- a/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."collections"; diff --git a/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/up.sql b/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/up.sql deleted file mode 100644 index fec2cb55d..000000000 --- a/app-backend/hasura/migrations/jandb/1692603657609_create_table_public_collections/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."collections" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "slug" varchar NOT NULL, "name" text NOT NULL, "description" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , UNIQUE ("slug")); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_collections_updated_at" -BEFORE UPDATE ON "public"."collections" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_collections_updated_at" ON "public"."collections" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/down.sql b/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/down.sql deleted file mode 100644 index 3b41d9305..000000000 --- a/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."products"; diff --git a/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/up.sql b/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/up.sql deleted file mode 100644 index 038926bb7..000000000 --- a/app-backend/hasura/migrations/jandb/1692603899157_create_table_public_products/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."products" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "slug" varchar NOT NULL, "name" text NOT NULL, "description" text, "image_url" text, "long_description" text, "technical_description" text, "author" text, "version" text, "source_url" text, "nsfw" boolean NOT NULL DEFAULT true, "greeting" text, "inputs" jsonb, "outputs" jsonb, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , UNIQUE ("slug")); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_products_updated_at" -BEFORE UPDATE ON "public"."products" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_products_updated_at" ON "public"."products" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/down.sql b/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/down.sql deleted file mode 100644 index 74f77626e..000000000 --- a/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."prompts"; diff --git a/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/up.sql b/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/up.sql deleted file mode 100644 index 7f444c43b..000000000 --- a/app-backend/hasura/migrations/jandb/1692603954223_create_table_public_prompts/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."prompts" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "slug" varchar NOT NULL, "content" text, "image_url" text, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , UNIQUE ("slug")); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_prompts_updated_at" -BEFORE UPDATE ON "public"."prompts" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_prompts_updated_at" ON "public"."prompts" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/down.sql b/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/down.sql deleted file mode 100644 index 53839d4c2..000000000 --- a/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."conversations"; diff --git a/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/up.sql b/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/up.sql deleted file mode 100644 index 5df679bf7..000000000 --- a/app-backend/hasura/migrations/jandb/1692604164229_create_table_public_conversations/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."conversations" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "product_id" uuid NOT NULL, "user_id" Text NOT NULL, "last_image_url" text, "last_text_message" text, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") ); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_conversations_updated_at" -BEFORE UPDATE ON "public"."conversations" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_conversations_updated_at" ON "public"."conversations" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/down.sql b/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/down.sql deleted file mode 100644 index eae375db7..000000000 --- a/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."messages"; diff --git a/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/up.sql b/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/up.sql deleted file mode 100644 index e9645e75d..000000000 --- a/app-backend/hasura/migrations/jandb/1692604250751_create_table_public_messages/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."messages" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "conversation_id" uuid NOT NULL, "message_type" varchar, "message_sender_type" varchar, "sender" text NOT NULL, "sender_name" text, "sender_avatar_url" text, "content" text, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") ); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_messages_updated_at" -BEFORE UPDATE ON "public"."messages" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_messages_updated_at" ON "public"."messages" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/down.sql b/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/down.sql deleted file mode 100644 index dfec07a82..000000000 --- a/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."message_medias"; diff --git a/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/up.sql b/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/up.sql deleted file mode 100644 index 8b82699b9..000000000 --- a/app-backend/hasura/migrations/jandb/1692604354631_create_table_public_message_medias/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."message_medias" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "message_id" uuid NOT NULL, "media_url" text, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "mime_type" varchar, PRIMARY KEY ("id") ); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_message_medias_updated_at" -BEFORE UPDATE ON "public"."message_medias" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_message_medias_updated_at" ON "public"."message_medias" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/down.sql b/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/down.sql deleted file mode 100644 index f2b37e379..000000000 --- a/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."collection_products"; diff --git a/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/up.sql b/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/up.sql deleted file mode 100644 index 16ebe6b43..000000000 --- a/app-backend/hasura/migrations/jandb/1692604743434_create_table_public_collection_products/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."collection_products" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "collection_id" uuid NOT NULL, "product_id" uuid NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , UNIQUE ("collection_id", "product_id")); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_collection_products_updated_at" -BEFORE UPDATE ON "public"."collection_products" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_collection_products_updated_at" ON "public"."collection_products" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/down.sql b/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/down.sql deleted file mode 100644 index 34881bd4d..000000000 --- a/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "public"."product_prompts"; diff --git a/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/up.sql b/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/up.sql deleted file mode 100644 index b8bc3a57d..000000000 --- a/app-backend/hasura/migrations/jandb/1692604794719_create_table_public_product_prompts/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE TABLE "public"."product_prompts" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "product_id" uuid NOT NULL, "prompt_id" uuid NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , UNIQUE ("product_id", "prompt_id")); -CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"() -RETURNS TRIGGER AS $$ -DECLARE - _new record; -BEGIN - _new := NEW; - _new."updated_at" = NOW(); - RETURN _new; -END; -$$ LANGUAGE plpgsql; -CREATE TRIGGER "set_public_product_prompts_updated_at" -BEFORE UPDATE ON "public"."product_prompts" -FOR EACH ROW -EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"(); -COMMENT ON TRIGGER "set_public_product_prompts_updated_at" ON "public"."product_prompts" -IS 'trigger to set value of column "updated_at" to current timestamp on row update'; -CREATE EXTENSION IF NOT EXISTS pgcrypto; diff --git a/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/down.sql b/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/down.sql deleted file mode 100644 index 49b450db6..000000000 --- a/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table "public"."collection_products" drop constraint "collection_products_collection_id_fkey"; diff --git a/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/up.sql b/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/up.sql deleted file mode 100644 index 29ee8b76b..000000000 --- a/app-backend/hasura/migrations/jandb/1692605865437_set_fk_public_collection_products_collection_id/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -alter table "public"."collection_products" - add constraint "collection_products_collection_id_fkey" - foreign key ("collection_id") - references "public"."collections" - ("id") on update cascade on delete cascade; diff --git a/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/down.sql b/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/down.sql deleted file mode 100644 index 1ca809d97..000000000 --- a/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table "public"."collection_products" drop constraint "collection_products_product_id_fkey"; diff --git a/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/up.sql b/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/up.sql deleted file mode 100644 index ef8457ce6..000000000 --- a/app-backend/hasura/migrations/jandb/1692605887650_set_fk_public_collection_products_product_id/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -alter table "public"."collection_products" - add constraint "collection_products_product_id_fkey" - foreign key ("product_id") - references "public"."products" - ("id") on update cascade on delete cascade; diff --git a/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/down.sql b/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/down.sql deleted file mode 100644 index 7d02924bb..000000000 --- a/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table "public"."messages" drop column "status"; diff --git a/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/up.sql b/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/up.sql deleted file mode 100644 index 428bf5b74..000000000 --- a/app-backend/hasura/migrations/jandb/1692885821205_alter_table_public_messages_add_column_status/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table "public"."messages" add column "status" varchar - null default 'ready'; diff --git a/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/down.sql b/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/down.sql deleted file mode 100644 index 29b407049..000000000 --- a/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/down.sql +++ /dev/null @@ -1 +0,0 @@ -alter table "public"."messages" drop column "prompt_cache"; \ No newline at end of file diff --git a/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/up.sql b/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/up.sql deleted file mode 100644 index ea23f42ed..000000000 --- a/app-backend/hasura/migrations/jandb/1692891470212_alter_table_public_messages_add_column_prompt_cache/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table "public"."messages" add column "prompt_cache" jsonb - null; diff --git a/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/down.sql b/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/down.sql deleted file mode 100644 index b72b858da..000000000 --- a/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/down.sql +++ /dev/null @@ -1 +0,0 @@ --- DO NOTHING WITH DATA MIGRATION DOWN diff --git a/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/up.sql b/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/up.sql deleted file mode 100644 index 7804caef7..000000000 --- a/app-backend/hasura/migrations/jandb/1694417935572_insert_products_migration/up.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO public.products ("slug", "name", "nsfw", "image_url", "description", "long_description", "technical_description", "author", "version", "source_url", "inputs", "outputs", "greeting") VALUES -('llama2', 'Llama-2-7B-Chat', 't', 'https://static-assets.jan.ai/llama2.jpg','Llama 2 is Meta`s open source large language model (LLM)', 'Llama 2 is a collection of pretrained and fine-tuned generative text models ranging in scale from 7 billion to 70 billion parameters. This is the repository for the 7B pretrained model. Links to other models can be found in the index at the bottom.', 'Meta developed and publicly released the Llama 2 family of large language models (LLMs), a collection of pretrained and fine-tuned generative text models ranging in scale from 7 billion to 70 billion parameters. Our fine-tuned LLMs, called Llama-2-Chat, are optimized for dialogue use cases. Llama-2-Chat models outperform open-source chat models on most benchmarks we tested, and in our human evaluations for helpfulness and safety, are on par with some popular closed-source models like ChatGPT and PaLM.', 'Meta', 'Llama2-7B-GGML', 'https://huggingface.co/TheBloke/airoboros-13B-gpt4-1.4-GGML', '{"body": [{"name": "messages", "type": "array", "items": [{"type": "object", "properties": [{"name": "role", "type": "string", "example": "system", "description": "Defines the role of the message."}, {"name": "content", "type": "string", "example": "Hello, world!", "description": "Contains the content of the message."}]}], "description": "An array of messages, each containing a role and content. The latest message is always at the end of the array."}, {"name": "stream", "type": "boolean", "example": true, "description": "Indicates whether the client wants to keep the connection open for streaming."}, {"name": "max_tokens", "type": "integer", "example": 500, "description": "Defines the maximum number of tokens that the client wants to receive."}], "slug": "llm", "headers": {"accept": "text/event-stream", "content-type": "application/json"}}', '{"slug": "llm", "type": "object", "properties": [{"name": "id", "type": "string", "example": "chatcmpl-4c4e5eb5-bf53-4dbc-9136-1cf69fc5fd7c", "description": "The unique identifier of the chat completion chunk."}, {"name": "model", "type": "string", "example": "gpt-3.5-turbo", "description": "The name of the GPT model used to generate the completion."}, {"name": "created", "type": "integer", "example": 1692169988, "description": "The Unix timestamp representing the time when the completion was generated."}, {"name": "object", "type": "string", "example": "chat.completion.chunk", "description": "A string indicating the type of the chat completion chunk."}, {"name": "choices", "type": "array", "items": [{"type": "object", "properties": [{"name": "index", "type": "integer", "example": 0, "description": "The index of the choice made by the GPT model."}, {"name": "delta", "type": "object", "properties": [{"name": "content", "type": "string", "example": "What", "description": "The content generated by the GPT model."}], "description": "A JSON object containing the content generated by the GPT model."}, {"name": "finish_reason", "type": "string", "example": null, "description": "A string indicating why the GPT model stopped generating content."}]}], "description": "An array containing the choices made by the GPT model to generate the completion."}], "description": "A JSON object representing a chat completion chunk."}', '👋I’m a versatile AI trained on a wide range of topics, here to answer your questions about the universe. What are you curious about today?') -ON CONFLICT (slug) DO NOTHING; diff --git a/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/down.sql b/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/down.sql deleted file mode 100644 index a089fbbf6..000000000 --- a/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/down.sql +++ /dev/null @@ -1 +0,0 @@ --- DO NOTHING WITH DATA MIGRATION DOWN \ No newline at end of file diff --git a/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/up.sql b/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/up.sql deleted file mode 100644 index de5d10f45..000000000 --- a/app-backend/hasura/migrations/jandb/1694417949946_insert_collections_migration/up.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO public.collections ("slug", "name", "description") VALUES -('conversational', 'Conversational', 'Converse with these models and get answers.') -ON CONFLICT (slug) DO NOTHING; diff --git a/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/down.sql b/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/down.sql deleted file mode 100644 index a089fbbf6..000000000 --- a/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/down.sql +++ /dev/null @@ -1 +0,0 @@ --- DO NOTHING WITH DATA MIGRATION DOWN \ No newline at end of file diff --git a/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/up.sql b/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/up.sql deleted file mode 100644 index c0c28cc8b..000000000 --- a/app-backend/hasura/migrations/jandb/1694417968422_insert_collection_products_migration/up.sql +++ /dev/null @@ -1,4 +0,0 @@ -INSERT INTO public.collection_products (collection_id, product_id) -SELECT (SELECT id FROM public.collections WHERE slug = 'conversational') AS collection_id, id AS product_id -FROM public.products -WHERE slug IN ('llama2') ON CONFLICT (collection_id, product_id) DO NOTHING; diff --git a/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/down.sql b/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/down.sql deleted file mode 100644 index a089fbbf6..000000000 --- a/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/down.sql +++ /dev/null @@ -1 +0,0 @@ --- DO NOTHING WITH DATA MIGRATION DOWN \ No newline at end of file diff --git a/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/up.sql b/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/up.sql deleted file mode 100644 index acf4ae014..000000000 --- a/app-backend/hasura/migrations/jandb/1694417980224_insert_prompts_migration/up.sql +++ /dev/null @@ -1,8 +0,0 @@ -INSERT INTO public.prompts ("slug", "content", "image_url") VALUES -('conversational-ai-future', 'What are possible developments for AI technology in the next decade?', ''), -('conversational-managing-stress', 'What are some tips for managing stress?', ''), -('conversational-postapoc-robot', 'Let''s role play. You are a robot in a post-apocalyptic world.', ''), -('conversational-python-pytorch', 'What is the difference between Python and Pytorch?', ''), -('conversational-quadratic-equation', 'Can you explain how to solve a quadratic equation?', ''), -('conversational-roman-history', 'What is the history of the Roman Empire?', '') -ON CONFLICT (slug) DO NOTHING; diff --git a/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/down.sql b/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/down.sql deleted file mode 100644 index a089fbbf6..000000000 --- a/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/down.sql +++ /dev/null @@ -1 +0,0 @@ --- DO NOTHING WITH DATA MIGRATION DOWN \ No newline at end of file diff --git a/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/up.sql b/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/up.sql deleted file mode 100644 index 6d3206ce5..000000000 --- a/app-backend/hasura/migrations/jandb/1694417991834_insert_product_prompts_migration/up.sql +++ /dev/null @@ -1,9 +0,0 @@ -INSERT INTO public.product_prompts (product_id, prompt_id) -SELECT p.id AS product_id, r.id AS prompt_id -FROM public.products p -JOIN public.prompts r -ON (p.id - IN (SELECT x.id FROM public.products x INNER JOIN public.collection_products y ON x.id = y.product_id - INNER JOIN public.collections z ON y.collection_id = z.id - WHERE z.slug = 'conversational')) -WHERE r.image_url IS NULL OR r.image_url = '' ON CONFLICT (product_id, prompt_id) DO NOTHING; diff --git a/app-backend/sample.env b/app-backend/sample.env deleted file mode 100644 index 9a7b438f1..000000000 --- a/app-backend/sample.env +++ /dev/null @@ -1,23 +0,0 @@ -## postgres database to store Hasura metadata -HASURA_GRAPHQL_METADATA_DATABASE_URL=postgres://postgres:postgrespassword@postgres:5432/postgres -## this env var can be used to add the above postgres database to Hasura as a data source. this can be removed/updated based on your needs -PG_DATABASE_URL=postgres://postgres:postgrespassword@postgres:5432/postgres -## enable the console served by server -HASURA_GRAPHQL_ENABLE_CONSOLE="true" # set to "false" to disable console -## enable debugging mode. It is recommended to disable this in production -HASURA_GRAPHQL_DEV_MODE="true" -HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup, http-log, webhook-log, websocket-log, query-log -## uncomment next line to run console offline (i.e load console assets from server instead of CDN) -# HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets -## uncomment next line to set an admin secret -HASURA_GRAPHQL_ADMIN_SECRET=myadminsecretkey -HASURA_GRAPHQL_UNAUTHORIZED_ROLE="public" -HASURA_GRAPHQL_METADATA_DEFAULTS='{"backend_configs":{"dataconnector":{"athena":{"uri":"http://data-connector-agent:8081/api/v1/athena"},"mariadb":{"uri":"http://data-connector-agent:8081/api/v1/mariadb"},"mysql8":{"uri":"http://data-connector-agent:8081/api/v1/mysql"},"oracle":{"uri":"http://data-connector-agent:8081/api/v1/oracle"},"snowflake":{"uri":"http://data-connector-agent:8081/api/v1/snowflake"}}}}' -HASURA_GRAPHQL_JWT_SECRET={"type": "RS256", "key": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"} - -# Environment variable for auto migrate -HASURA_GRAPHQL_MIGRATIONS_DIR=/migrations -HASURA_GRAPHQL_METADATA_DIR=/metadata -HASURA_GRAPHQL_ENABLE_CONSOLE='true' -HASURA_ACTION_STABLE_DIFFUSION_URL=http://sd:8000 -HASURA_EVENTS_HOOK_URL="http://worker:8787" \ No newline at end of file diff --git a/app-backend/sample.env_postgresql b/app-backend/sample.env_postgresql deleted file mode 100644 index 39aa93db5..000000000 --- a/app-backend/sample.env_postgresql +++ /dev/null @@ -1 +0,0 @@ -POSTGRES_PASSWORD=postgrespassword \ No newline at end of file diff --git a/app/README.md b/app/README.md deleted file mode 100644 index 1d0245dae..000000000 --- a/app/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# App - -Jan Desktop is an Electron application designed to allow users to interact with the Language Model (LLM) through chat or create art using Stable Diffusion. - -## Features - -- Chat with the Language Model: Engage in interactive conversations with the Language Model. Ask questions, seek information, or simply have a chat. - -- Generate Art with Stable Diffusion: Utilize the power of Stable Diffusion to generate unique and captivating pieces of art. Experiment with various parameters to achieve desired results. - -## Installation and Usage - -### Pre-requisites -- node >= 20.0.0 -- yarn >= 1.22.0 - -### Use as complete suite (in progress) - -### For interactive development - -Note: This instruction is tested on MacOS only. - -1. **Clone the Repository:** - - ``` - git clone https://github.com/janhq/jan - git checkout feature/hackathon-refactor-jan-into-electron-app - cd jan/app - ``` - -2. **Install dependencies:** - - ``` - yarn install - ``` - -3. **Download Model and copy to userdata directory** (this is a hacky step, will be remove in future versions) - - ``` - # Determining the path to save model with /Users//Library/Application Support/jan-web/ - mkdir /Users//Library/Application Support/jan-web - - # Now download the model to correct location by running command - wget -O /Users//Library/Application Support/jan-web/llama-2-7b-chat.gguf.q4_0.bin https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_0.gguf - ``` - -4. **Run development and Using Jan Desktop** - - ``` - yarn electron:start - ``` - This will start the development server and open the desktop app. - In this step, there are a few notification about installing base plugin, just click `OK` and `Next` to continue. - ![](./images/jan-desktop-dev-instruction-1.png) - ![](./images/jan-desktop-dev-instruction-2.png) - ![](./images/jan-desktop-dev-instruction-3.png) - - After that, you can use Jan Desktop as normal. - ![](./images/jan-desktop-dev-instruction-4.png) - ![](./images/jan-desktop-dev-instruction-5.png) - ![](./images/jan-desktop-dev-instruction-6.png) - -### For production build - - ```bash - # Do step 1 and 2 in previous section - git clone https://github.com/janhq/jan - git checkout feature/hackathon-refactor-jan-into-electron-app - cd jan/app - yarn install - - # Build the app - yarn electron:build:all - ``` - - This will build the app MacOS m1/m2 for production (with code signing already done) and put the result in `dist` folder. - -## Configuration - -TO DO - -## Dependencies - -TO DO - -## Contributing - -Contributions are welcome! If you find a bug or have suggestions for improvements, feel free to open an issue or submit a pull request on the [GitHub repository](https://github.com/janhq/jan). - -## License - -This project is licensed under the Fair-code License - see the [License](https://faircode.io/#licenses) for more details. - ---- - -Feel free to reach out [Discord](https://jan.ai/discord) if you have any questions or need further assistance. Happy coding with Jan Web and exploring the capabilities of the Language Model and Stable Diffusion! 🚀🎨🤖 \ No newline at end of file diff --git a/app/app/_components/ChatContainer/index.tsx b/app/app/_components/ChatContainer/index.tsx deleted file mode 100644 index 84fa8f5c2..000000000 --- a/app/app/_components/ChatContainer/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import ModelDetailSideBar from "../ModelDetailSideBar"; -import ProductOverview from "../ProductOverview"; -import { useAtomValue } from "jotai"; -import { - getActiveConvoIdAtom, - showingProductDetailAtom, -} from "@/_helpers/JotaiWrapper"; -import { ReactNode } from "react"; -import ModelManagement from "../ModelManagement"; - -type Props = { - children: ReactNode; -}; - -export default function ChatContainer({ children }: Props) { - const activeConvoId = useAtomValue(getActiveConvoIdAtom); - // const showingProductDetail = useAtomValue(showingProductDetailAtom); - - if (!activeConvoId) { - // return ; - return ; - } - - return ( -
- {children} - {/* {showingProductDetail ? : null} */} -
- ); -} diff --git a/app/app/_components/DownloadModelCard/index.tsx b/app/app/_components/DownloadModelCard/index.tsx deleted file mode 100644 index dd8f2e594..000000000 --- a/app/app/_components/DownloadModelCard/index.tsx +++ /dev/null @@ -1,81 +0,0 @@ -"use client"; - -import DownloadModelContent from "../DownloadModelContent"; -import ModelDownloadButton from "../ModelDownloadButton"; -import ModelDownloadingButton from "../ModelDownloadingButton"; -import ViewModelDetailButton from "../ViewModelDetailButton"; - -type Props = { - name: string; - type: string; - author: string; - description: string; - isRecommend: boolean; - storage: number; - installed?: boolean; - required?: string; - downloading?: boolean; - total?: number; - transferred?: number; - onInitClick?: () => void; - onDeleteClick?: () => void; - onDownloadClick?: () => void; -}; - -const DownloadModelCard: React.FC = ({ - author, - description, - isRecommend, - name, - storage, - type, - installed = false, - required, - downloading = false, - total = 0, - transferred = 0, - onInitClick, - onDeleteClick, - onDownloadClick, -}) => { - const handleViewDetails = () => {}; - - let downloadButton = null; - if (!installed) { - downloadButton = downloading ? ( -
- onDownloadClick?.()} /> -
- ) : ( -
- -
- ); - } else { - downloadButton = ( -
- - -
- ); - } - - return ( -
-
- - {downloadButton} -
- -
- ); -}; - -export default DownloadModelCard; diff --git a/app/app/_components/LeftContainer/index.tsx b/app/app/_components/LeftContainer/index.tsx deleted file mode 100644 index 69f4c6aab..000000000 --- a/app/app/_components/LeftContainer/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client"; - -import { useAtomValue } from "jotai"; -import AdvancedPrompt from "../AdvancedPrompt"; -import CompactSideBar from "../CompactSideBar"; -import LeftSidebar from "../LeftSidebar"; -import { showingAdvancedPromptAtom } from "@/_helpers/JotaiWrapper"; - -const LeftContainer: React.FC = () => { - const isShowingAdvPrompt = useAtomValue(showingAdvancedPromptAtom); - - if (isShowingAdvPrompt) { - return ( -
- - -
- ); - } - - return ; -}; - -export default LeftContainer; diff --git a/app/app/_components/ModelListContainer/index.tsx b/app/app/_components/ModelListContainer/index.tsx deleted file mode 100644 index a681a765c..000000000 --- a/app/app/_components/ModelListContainer/index.tsx +++ /dev/null @@ -1,136 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import DownloadModelCard from "../DownloadModelCard"; -import { executeSerial } from "@/_services/pluginService"; -import { ModelManagementService } from "../../../shared/coreService"; -import { useAtomValue } from "jotai"; -import { modelDownloadStateAtom } from "@/_helpers/JotaiWrapper"; - -const ModelListContainer: React.FC = () => { - const [downloadedModels, setDownloadedModels] = useState([]); - const downloadState = useAtomValue(modelDownloadStateAtom); - const DownloadedModel = { - title: "Downloaded Model", - data: [ - { - name: "Llama 2 7B Chat - GGML", - type: "7B", - author: "The Bloke", - description: - "Primary intended uses The primary use of LLaMA is research on large language models, including: exploring potential applications such as question answering, natural language understanding or reading comprehension, understanding capabilities and limitations of current language models, and developing techniques to improve those, evaluating and mitigating biases, risks, toxic and harmful content generations, hallucinations.", - isRecommend: true, - storage: 3780, - default: true, - }, - ], - }; - - const BrowseAvailableModels = { - title: "Browse Available Models", - data: [ - { - name: "Llama 2 7B Chat - GGML", - type: "7B", - author: "The Bloke", - description: - "Primary intended uses The primary use of LLaMA is research on large language models, including: exploring potential applications such as question answering, natural language understanding or reading comprehension, understanding capabilities and limitations of current language models, and developing techniques to improve those, evaluating and mitigating biases, risks, toxic and harmful content generations, hallucinations.", - isRecommend: true, - storage: 3780, - default: true, - }, - ], - }; - - useEffect(() => { - const getDownloadedModels = async () => { - const modelNames = await executeSerial( - ModelManagementService.GET_DOWNLOADED_MODELS, - ); - setDownloadedModels(modelNames); - }; - getDownloadedModels(); - }, []); - - const onDeleteClick = async () => { - // TODO: for now we only support 1 model - if (downloadedModels?.length < 1) { - return; - } - console.log(downloadedModels[0]); - const pathArray = downloadedModels[0].split("/"); - const modelName = pathArray[pathArray.length - 1]; - console.log(`Prepare to delete ${modelName}`); - // setShow(true); // TODO: later - await executeSerial(ModelManagementService.DELETE_MODEL, modelName); - - setDownloadedModels([]); - }; - - const initModel = async () => { - const product = { - name: "LLama 2 7B Chat", - fileName: "llama-2-7b-chat.gguf.q4_0.bin", - downloadUrl: - "https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_0.gguf", - }; - await executeSerial(ModelManagementService.INIT_MODEL, product); - }; - - const onDownloadClick = async () => { - const url = - "https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_0.gguf"; - await executeSerial(ModelManagementService.DOWNLOAD_MODEL, url); - }; - - return ( -
-
- - {downloadedModels?.length > 0 && - DownloadedModel.data.map((item, index) => ( - <DownloadModelCard - key={index} - {...item} - installed={true} - onInitClick={initModel} - onDeleteClick={onDeleteClick} - /> - ))} - </div> - <div className="pb-5 flex flex-col gap-2"> - {downloadedModels.length === 0 && ( - <> - <Title title={BrowseAvailableModels.title} /> - {BrowseAvailableModels.data.map((item, index) => ( - <DownloadModelCard - key={index} - {...item} - downloading={downloadState == null} - total={downloadState?.size.total ?? 0} - transferred={downloadState?.size.transferred ?? 0} - onDownloadClick={onDownloadClick} - /> - ))} - </> - )} - </div> - </div> - ); -}; - -type Props = { - title: string; -}; - -const Title: React.FC<Props> = ({ title }) => { - return ( - <div className="flex gap-[10px]"> - <span className="font-semibold text-xl leading-[25px] tracking-[-0.4px]"> - {title} - </span> - </div> - ); -}; - -export default ModelListContainer; diff --git a/app/app/_components/Preferences.tsx b/app/app/_components/Preferences.tsx deleted file mode 100644 index 46938a916..000000000 --- a/app/app/_components/Preferences.tsx +++ /dev/null @@ -1,286 +0,0 @@ -"use client"; -import { useEffect, useRef, useState } from "react"; -import { - setup, - plugins, - extensionPoints, - activationPoints, -} from "../../electron/core/plugin-manager/execution/index"; - -import { - ChartPieIcon, - CommandLineIcon, - HomeIcon, - PlayIcon, -} from "@heroicons/react/24/outline"; - -import { MagnifyingGlassIcon } from "@heroicons/react/20/solid"; -import classNames from "classnames"; -import Link from "next/link"; -const navigation = [ - { name: "Plugin Manager", href: "#", icon: ChartPieIcon, current: true }, -]; - -/* eslint-disable @next/next/no-sync-scripts */ -export const Preferences = () => { - const [search, setSearch] = useState<string>(""); - const [activePlugins, setActivePlugins] = useState<any[]>([]); - - const preferenceRef = useRef(null); - useEffect(() => { - async function setupPE() { - // Enable activation point management - setup({ - //@ts-ignore - importer: (plugin) => - import(/* webpackIgnore: true */ plugin).catch((err) => { - console.log(err); - }), - }); - - // Register all active plugins with their activation points - await plugins.registerActive(); - } - - const activePlugins = async () => { - const plgs = await plugins.getActive(); - setActivePlugins(plgs); - // Activate alls - setTimeout(async () => { - await activationPoints.trigger("init"); - if (extensionPoints.get("experimentComponent")) { - const components = await Promise.all( - extensionPoints.execute("experimentComponent") - ); - components.forEach((e) => { - if (preferenceRef.current) { - // @ts-ignore - preferenceRef.current.appendChild(e); - } - }); - } - }, 500); - }; - setupPE().then(() => activePlugins()); - }, []); - - // Install a new plugin on clicking the install button - const install = async (e: any) => { - e.preventDefault(); - //@ts-ignore - const pluginFile = new FormData(e.target).get("plugin-file").path; - - // Send the filename of the to be installed plugin - // to the main process for installation - const installed = await plugins.install([pluginFile]); - if (typeof window !== "undefined") { - window.location.reload(); - } - }; - - // Uninstall a plugin on clicking uninstall - const uninstall = async (name: string) => { - //@ts-ignore - - // Send the filename of the to be uninstalled plugin - // to the main process for removal - //@ts-ignore - const res = await plugins.uninstall([name]); - console.log( - res - ? "Plugin successfully uninstalled" - : "Plugin could not be uninstalled" - ); - }; - - // Update all plugins on clicking update plugins - const update = async (plugin: string) => { - if (typeof window !== "undefined") { - // @ts-ignore - await window.pluggableElectronIpc.update([plugin], true); - } - // plugins.update(active.map((plg) => plg.name)); - }; - - return ( - <div className="w-full h-screen overflow-scroll"> - {/* Static sidebar for desktop */} - <div className="fixed inset-y-0 z-50 flex w-72 flex-col"> - {/* Sidebar component, swap this element with another sidebar if you like */} - <div className="flex grow flex-col gap-y-5 overflow-y-auto bg-gray-900 px-6 pb-4"> - <div className="flex h-16 shrink-0 items-center"> - <Link href="/"> - <img - className="h-8 w-auto" - src="icons/app_icon.svg" - alt="Your Company" - /> - </Link> - </div> - <nav className="flex flex-1 flex-col"> - <ul role="list" className="flex flex-1 flex-col gap-y-7"> - <li> - <ul role="list" className="-mx-2 space-y-1"> - {navigation.map((item) => ( - <li key={item.name}> - <a - href={item.href} - className={classNames( - item.current - ? "bg-gray-800 text-white" - : "text-gray-400 hover:text-white hover:bg-gray-800", - "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold" - )} - > - <item.icon - className="h-6 w-6 shrink-0" - aria-hidden="true" - /> - {item.name} - </a> - </li> - ))} - </ul> - </li> - - <li className="mt-auto"> - <a - href="/" - className="group -mx-2 flex gap-x-3 rounded-md p-2 text-sm font-semibold leading-6 text-gray-400 hover:bg-gray-800 hover:text-white" - > - <HomeIcon className="h-6 w-6 shrink-0" aria-hidden="true" /> - Home - </a> - </li> - </ul> - </nav> - </div> - </div> - - <div className="pl-72 w-full"> - <div className="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-gray-200 bg-white shadow-sm sm:gap-x-6 sm:px-6 px-8"> - {/* Separator */} - <div className="h-6 w-px bg-gray-900/10 hidden" aria-hidden="true" /> - - <div className="flex flex-1 self-stretch gap-x-6"> - <form className="relative flex flex-1" action="#" method="GET"> - <label htmlFor="search-field" className="sr-only"> - Search - </label> - <MagnifyingGlassIcon - className="pointer-events-none absolute inset-y-0 left-0 h-full w-5 text-gray-400" - aria-hidden="true" - /> - <input - defaultValue={search} - onChange={(e) => setSearch(e.target.value)} - id="search-field" - className="block h-full w-full border-0 py-0 pl-8 pr-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm" - placeholder="Search..." - type="search" - name="search" - /> - </form> - </div> - </div> - - <main className="py-5"> - <div className="sm:px-6 px-8"> - {/* Content */} - <div className="flex flex-row items-center my-4"> - <ChartPieIcon width={30} /> - Install Plugin - </div> - <form id="plugin-file" onSubmit={install}> - <div className="flex flex-row items-center space-x-10"> - <div className="flex items-center justify-center w-[300px]"> - <label className="flex flex-col items-center justify-center w-full border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600"> - <div className="flex flex-col items-center justify-center pt-5 pb-6"> - <p className="mb-2 text-sm text-gray-500 dark:text-gray-400"> - <span className="font-semibold">Click to upload</span>{" "} - or drag and drop - </p> - <p className="text-xs text-gray-500 dark:text-gray-400"> - TGZ (MAX 50MB) - </p> - </div> - <input - id="dropzone-file" - name="plugin-file" - type="file" - className="hidden" - required - /> - </label> - </div> - <button - type="submit" - className="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" - > - Install Plugin - </button> - </div> - </form> - - <div className="flex flex-row items-center my-4"> - <CommandLineIcon width={30} /> - Installed Plugins - </div> - <div className="flex flex-wrap"> - {activePlugins - .filter( - (e) => - search.trim() === "" || - e.name.toLowerCase().includes(search.toLowerCase()) - ) - .map((e) => ( - <div key={e.name} className="m-2"> - <a - href="#" - className="block max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700" - > - <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"> - {e.name} - </h5> - <p className="font-normal text-gray-700 dark:text-gray-400"> - Activation: {e.activationPoints} - </p> - <p className="font-normal text-gray-700 dark:text-gray-400"> - Url: {e.url} - </p> - <div className="flex flex-row space-x-5"> - <button - type="submit" - onClick={() => { - uninstall(e.name); - }} - className="mt-5 rounded-md bg-red-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600" - > - Uninstall - </button> - <button - type="submit" - onClick={() => { - update(e.name); - }} - className="mt-5 rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" - > - Update - </button> - </div> - </a> - </div> - ))} - </div> - <div className="flex flex-row items-center my-4"> - <PlayIcon width={30} /> - Test Plugins - </div> - <div className="h-full w-full" ref={preferenceRef}></div> - {/* Content */} - </div> - </main> - </div> - </div> - ); -}; diff --git a/app/app/_components/SidebarMenu/index.tsx b/app/app/_components/SidebarMenu/index.tsx deleted file mode 100644 index a852596f3..000000000 --- a/app/app/_components/SidebarMenu/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import Image from "next/image"; -import Link from "next/link"; - -const SidebarMenu: React.FC = () => { - const menu = [ - { - name: "Chat History", - icon: "ClipboardList", - url: "#", - }, - { - name: "Explore Models", - icon: "Search_gray", - url: "#", - }, - { - name: "My Models", - icon: "ViewGrid", - url: "#", - }, - { - name: "Settings", - icon: "Cog", - url: "/settings", - }, - ]; - - return ( - <div className="flex-1 flex flex-col justify-end"> - <div className="text-gray-500 text-xs font-semibold py-2 pl-2 pr-3"> - Your Configurations - </div> - {menu.map((item, index) => ( - <div key={index} className="py-2 pl-2 pr-3"> - <Link - href={item.url} - className="flex items-center gap-3 text-base text-gray-600" - > - <Image - src={`icons/${item.icon}.svg`} - width={24} - height={24} - alt="" - /> - {item.name} - </Link> - </div> - ))} - </div> - ); -}; - -export default SidebarMenu; diff --git a/app/app/_components/SystemStatus/index.tsx b/app/app/_components/SystemStatus/index.tsx deleted file mode 100644 index 7b6f371f4..000000000 --- a/app/app/_components/SystemStatus/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -type Props = { - name: string; - total: number; - value: number; -}; - -const SystemItem: React.FC<Props> = ({ name, total, value }) => { - return ( - <div className="border-l border-gray-200 flex gap-2 pl-4"> - <div className="flex gap-[10px] p-1 bg-gray-100 text-gray-600 text-[11px] leading-[13px]"> - {name} - </div> - <span className="text-gray-500 text-sm"> - {toGigabytes(value)} / {toGigabytes(total)}{" "} - {((value / total) * 100).toFixed(2)} % - </span> - </div> - ); -}; - -const toGigabytes = (input: number) => { - return input > 1000 ? input / 1000 + "GB" : input + "MB"; -}; - -export default SystemItem; diff --git a/app/app/_components/WelcomeContainer/index.tsx b/app/app/_components/WelcomeContainer/index.tsx deleted file mode 100644 index f8e043dcc..000000000 --- a/app/app/_components/WelcomeContainer/index.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import Image from "next/image"; -import SystemStatus from "../SystemStatus"; -import { SidebarButton } from "../SidebarButton"; - -const Welcome: React.FC = () => { - const data = { - name: "LlaMa 2 - Hermes 7B (Q4_K_M)", - type: "7B", - author: "Architecture Llama", - description: - "Primary intended uses The primary use of LLaMA is research on large language models, including: exploring potential applications such as question answering, natural language understanding or reading comprehension, understanding capabilities and limitations of current language models, and developing techniques to improve those, evaluating and mitigating biases, risks, toxic and harmful content generations, hallucinations.", - isRecommend: true, - storage: 3780, - required: "8GB+ RAM", - }; - const system = [ - { - name: "GPU", - value: 782.2, - total: 14000, - }, - { - name: "RAM", - value: 5100, - total: 14000, - }, - { - name: "STORAGE", - value: 500000, - total: 1000000, - }, - ]; - return ( - <div className="flex flex-col h-full"> - <div className="px-[200px] flex-1 flex flex-col gap-5 justify-center items-start"> - <Image src={"icons/App_ico.svg"} width={44} height={45} alt="" /> - <span className="font-semibold text-gray-500 text-5xl"> - Welcome, - <br /> - let’s download your first model - </span> - <SidebarButton - className="flex flex-row-reverse items-center rounded-lg gap-2 px-3 py-2 text-xs font-medium border border-gray-200" - icon="icons/arrow-right.svg" - title="Explore models" - height={16} - width={16} - /> - </div> - <div className="px-3 py-2 gap-4 flex items-center justify-center"> - <span className="text-gray-500 text-sm">System status</span> - {system.map((item, index) => ( - <SystemStatus key={index} {...item} /> - ))} - </div> - </div> - ); -}; - -export default Welcome; diff --git a/app/app/_helpers/EventListenerWrapper.tsx b/app/app/_helpers/EventListenerWrapper.tsx deleted file mode 100644 index 7efe04b23..000000000 --- a/app/app/_helpers/EventListenerWrapper.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-nocheck -"use client"; - -import { useSetAtom } from "jotai"; -import { ReactNode, useEffect } from "react"; -import { modelDownloadStateAtom } from "./JotaiWrapper"; - -type Props = { - children: ReactNode; -}; - -export default function EventListenerWrapper({ children }: Props) { - const setDownloadState = useSetAtom(modelDownloadStateAtom); - useEffect(() => { - window.electronAPI.onModelDownloadUpdate((event, state) => { - setDownloadState(state); - }); - - window.electronAPI.onModelDownloadError(() => { - // TODO: Show error message - }); - }, []); - - return <div id="eventlistener">{children}</div>; -} diff --git a/app/electron/core/base-plugin/index.js b/app/electron/core/base-plugin/index.js deleted file mode 100644 index a4a9e8345..000000000 --- a/app/electron/core/base-plugin/index.js +++ /dev/null @@ -1,72 +0,0 @@ -const inference = async (prompt) => - new Promise(async (resolve) => { - if (window.electronAPI) { - const response = await window.electronAPI.sendInquiry(prompt); - resolve(response); - } - }); - -async function testInference(e) { - e.preventDefault(); - const message = new FormData(e.target).get("message"); - const resp = await inference(message); - alert(resp); -} - -const getButton = (text, func) => { - var element = document.createElement("button"); - element.innerText = text; - // Add styles to the button element - element.style.marginTop = "5px"; - element.style.marginRight = "5px"; - element.style.borderRadius = "0.375rem"; // Rounded-md - element.style.backgroundColor = "rgb(79, 70, 229)"; // bg-indigo-600 - element.style.paddingLeft = "0.875rem"; // - element.style.paddingRight = "0.875rem"; // - element.style.fontSize = "0.875rem"; // text-sm - element.style.fontWeight = "600"; // font-semibold - element.style.color = "white"; // text-white - element.style.height = "40px"; - element.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)"; // shadow-sm - element.addEventListener("click", func); - return element; -}; - -const experimentComponent = () => { - var parent = document.createElement("div"); - const label = document.createElement("p"); - label.style.marginTop = "5px"; - label.innerText = "Inference Plugin"; - parent.appendChild(label); - - const form = document.createElement("form"); - form.id = "test"; - form.style.display = "flex"; // Enable Flexbox - form.style.alignItems = "center"; // Center items horizontally - form.addEventListener("submit", testInference); - const input = document.createElement("input"); - input.style.borderRadius = "5px"; - input.style.borderColor = "#E5E7EB"; - input.style.marginTop = "5px"; - input.style.marginRight = "5px"; - input.name = "message"; - form.appendChild(input); - const button = getButton("Test Inference", null); - button.type = "submit"; - button.innerText = "Test Inference"; - form.appendChild(button); - - parent.appendChild(form); - return parent; -}; - -// Register all the above functions and objects with the relevant extension points -export function init({ register }) { - register("inference", "inference", inference); - // Experiment UI - for Preferences - register( - "experimentComponent", - "base-plugin-experiment-component", - experimentComponent - ); -} diff --git a/app/electron/core/base-plugin/package-lock.json b/app/electron/core/base-plugin/package-lock.json deleted file mode 100644 index 5f22d4947..000000000 --- a/app/electron/core/base-plugin/package-lock.json +++ /dev/null @@ -1,1455 +0,0 @@ -{ - "name": "base-plugin", - "version": "2.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "base-plugin", - "version": "2.1.0", - "license": "MIT", - "devDependencies": { - "rimraf": "^3.0.2", - "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@types/eslint": { - "version": "8.44.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", - "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz", - "integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "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, - "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/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "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==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", - "dev": true, - "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" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001535", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001535.tgz", - "integrity": "sha512-48jLyUkiWFfhm/afF7cQPqPjaUmSraEhK4j+FCTJpgnGGEZHqyLe3hmWH7lIooZdSzXL0ReMvHz0vKDoTBsrwg==", - "dev": true, - "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/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "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 - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.523", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.523.tgz", - "integrity": "sha512-9AreocSUWnzNtvLcbpng6N+GkXnCcBR80IQkxRC9Dfdyg4gaWNUPBujAHUpKkiUkoSoR9UlhA4zD/IgBklmhzg==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/envinfo": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", - "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "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, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/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, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "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 - }, - "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 - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "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 - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": 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 - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "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==", - "dev": true, - "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 - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "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 - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.19.4", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", - "integrity": "sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "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" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-merge": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", - "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - } - } -} diff --git a/app/electron/core/base-plugin/package.json b/app/electron/core/base-plugin/package.json deleted file mode 100644 index 6b8346e5f..000000000 --- a/app/electron/core/base-plugin/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "base-plugin", - "version": "2.1.0", - "description": "", - "main": "dist/bundle.js", - "author": "Igor Honhoff", - "license": "MIT", - "activationPoints": [ - "init" - ], - "scripts": { - "prepare": "webpack --config webpack.config.js", - "package": "rimraf ./base-plugin*.tgz && npm pack" - }, - "devDependencies": { - "rimraf": "^3.0.2", - "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" - }, - "dependencies": {}, - "files": [ - "dist/*", - "package.json", - "README.md" - ] -} diff --git a/app/electron/core/data-plugin/index.js b/app/electron/core/data-plugin/index.js deleted file mode 100644 index c3f23f756..000000000 --- a/app/electron/core/data-plugin/index.js +++ /dev/null @@ -1,137 +0,0 @@ -// Provide an async method to manipulate the price provided by the extension point -const PLUGIN_NAME = "data-plugin"; - -const getConversations = () => - new Promise((resolve) => { - if (window && window.electronAPI) { - window.electronAPI - .invokePluginFunc(PLUGIN_NAME, "getConversations") - .then((res) => resolve(res)); - } else { - resolve([]); - } - }); -const getConversationMessages = (id) => - new Promise((resolve) => { - if (window && window.electronAPI) { - window.electronAPI - .invokePluginFunc(PLUGIN_NAME, "getConversationMessages", id) - .then((res) => resolve(res)); - } else { - resolve([]); - } - }); - -const createConversation = (conversation) => - new Promise((resolve) => { - if (window && window.electronAPI) { - window.electronAPI - .invokePluginFunc(PLUGIN_NAME, "storeConversation", conversation) - .then((res) => { - resolve(res); - }); - } else { - resolve("-"); - } - }); -const createMessage = (message) => - new Promise((resolve) => { - if (window && window.electronAPI) { - window.electronAPI - .invokePluginFunc(PLUGIN_NAME, "storeMessage", message) - .then((res) => resolve(res)); - } else { - resolve("-"); - } - }); - -const deleteConversation = (id) => - new Promise((resolve) => { - if (window && window.electronAPI) { - window.electronAPI - .invokePluginFunc(PLUGIN_NAME, "deleteConversation", id) - .then((res) => { - resolve(res); - }); - } else { - resolve("-"); - } - }); - -const setupDb = () => { - window.electronAPI.invokePluginFunc(PLUGIN_NAME, "init"); -}; - -const getButton = (text, func) => { - var element = document.createElement("button"); - element.innerText = text; - // Add styles to the button element - element.style.marginTop = "5px"; - element.style.marginRight = "5px"; - element.style.borderRadius = "0.375rem"; // Rounded-md - element.style.backgroundColor = "rgb(79, 70, 229)"; // bg-indigo-600 - element.style.padding = "0.875rem 1rem"; // px-3.5 py-2.5 - element.style.fontSize = "0.875rem"; // text-sm - element.style.fontWeight = "600"; // font-semibold - element.style.color = "white"; // text-white - element.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.1)"; // shadow-sm - element.addEventListener("click", func); - return element; -}; -const experimentComponent = () => { - var parent = document.createElement("div"); - const label = document.createElement("p"); - label.style.marginTop = "5px"; - label.innerText = "Data Plugin"; - parent.appendChild(label); - const getConvs = getButton("Get Conversation", async () => { - // Define the action you want to perform when the button is clicked - alert(JSON.stringify(await getConversations())); - }); - const spawnConv = getButton("Spawn Conversation", async () => { - // Define the action you want to perform when the button is clicked - const id = await createConversation({ - name: "test", - model_id: "yolo", - }); - alert("A new conversation is created: " + id); - }); - const deleteLastConv = getButton("Delete Last Conversation", async () => { - // Define the action you want to perform when the button is clicked - const convs = await getConversations(); - await deleteConversation(convs[convs.length - 1].id); - alert("Last conversation is deleted"); - }); - const spawnMessage = getButton("Spawn Message", async () => { - const convs = await getConversations(); - await createMessage({ - name: "", - conversation_id: convs[0].id, - message: "yoo", - user: "user", - }); - alert("Message is created"); - }); - parent.appendChild(getConvs); - parent.appendChild(spawnConv); - parent.appendChild(deleteLastConv); - parent.appendChild(spawnMessage); - return parent; -}; - -// Register all the above functions and objects with the relevant extension points -export function init({ register }) { - setupDb(); - register("getConversations", "getConv", getConversations, 1); - register("createConversation", "insertConv", createConversation); - register("deleteConversation", "deleteConv", deleteConversation); - register("createMessage", "insertMessage", createMessage); - register("getConversationMessages", "getMessages", getConversationMessages); - - // Experiment UI - for Preferences - register( - "experimentComponent", - "data-plugin-experiment-component", - experimentComponent - ); -} diff --git a/app/electron/core/data-plugin/module.js b/app/electron/core/data-plugin/module.js deleted file mode 100644 index 528be0548..000000000 --- a/app/electron/core/data-plugin/module.js +++ /dev/null @@ -1,152 +0,0 @@ -const sqlite3 = require("sqlite3").verbose(); -const path = require("path"); -const { app } = require("electron"); - -function init() { - const db = new sqlite3.Database(path.join(app.getPath("userData"), "jan.db")); - - db.serialize(() => { - db.run( - "CREATE TABLE IF NOT EXISTS models ( id INTEGER PRIMARY KEY, name TEXT, image TEXT, url TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);" - ); - db.run( - "CREATE TABLE IF NOT EXISTS conversations ( id INTEGER PRIMARY KEY, name TEXT, model_id INTEGER, image TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);" - ); - db.run( - "CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY, name TEXT, conversation_id INTEGER, user TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);" - ); - }); - - const stmt = db.prepare( - "INSERT INTO conversations (name, model_id, image, message) VALUES (?, ?, ?, ?)" - ); - stmt.finalize(); - db.close(); -} -function getConversations() { - return new Promise((res) => { - const db = new sqlite3.Database( - path.join(app.getPath("userData"), "jan.db") - ); - - db.all( - "SELECT * FROM conversations ORDER BY created_at DESC", - (err, row) => { - res(row); - } - ); - db.close(); - }); -} -function storeConversation(conversation) { - return new Promise((res) => { - const db = new sqlite3.Database( - path.join(app.getPath("userData"), "jan.db") - ); - - db.serialize(() => { - const stmt = db.prepare( - "INSERT INTO conversations (name, model_id, image, message) VALUES (?, ?, ?, ?)" - ); - stmt.run( - conversation.name, - conversation.model_id, - conversation.image, - conversation.message, - function (err) { - if (err) { - // Handle the insertion error here - console.error(err.message); - res(undefined); - return; - } - const id = this.lastID; - console.log(`Record inserted successfully with ID ${id}`); - res(id); - return; - } - ); - stmt.finalize(); - }); - - db.close(); - }); -} -function storeMessage(message) { - return new Promise((res) => { - const db = new sqlite3.Database( - path.join(app.getPath("userData"), "jan.db") - ); - - db.serialize(() => { - const stmt = db.prepare( - "INSERT INTO messages (name, conversation_id, user, message) VALUES (?, ?, ?, ?)" - ); - stmt.run( - message.name, - message.conversation_id, - message.user, - message.message, - function (err) { - if (err) { - // Handle the insertion error here - console.error(err.message); - res(undefined); - return; - } - const id = this.lastID; - console.log(`Record inserted successfully with ID ${id}`); - res(id); - return; - } - ); - stmt.finalize(); - }); - - db.close(); - }); -} -function deleteConversation(id) { - return new Promise((res) => { - const db = new sqlite3.Database( - path.join(app.getPath("userData"), "jan.db") - ); - - db.serialize(() => { - const deleteConv = db.prepare("DELETE FROM conversations WHERE id = ?"); - deleteConv.run(id); - deleteConv.finalize(); - const deleteMessages = db.prepare( - "DELETE FROM messages WHERE conversation_id = ?" - ); - deleteMessages.run(id); - deleteMessages.finalize(); - res([]); - }); - - db.close(); - }); -} - -function getConversationMessages(conversation_id) { - return new Promise((res) => { - const db = new sqlite3.Database( - path.join(app.getPath("userData"), "jan.db") - ); - - const query = `SELECT * FROM messages WHERE conversation_id = ${conversation_id} ORDER BY created_at DESC`; - db.all(query, (err, row) => { - res(row); - }); - db.close(); - }); -} - -module.exports = { - init, - getConversations, - deleteConversation, - storeConversation, - storeMessage, - getConversationMessages, -}; diff --git a/app/electron/core/data-plugin/package.json b/app/electron/core/data-plugin/package.json deleted file mode 100644 index 2e0fd352f..000000000 --- a/app/electron/core/data-plugin/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "data-plugin", - "version": "2.1.0", - "description": "", - "main": "dist/bundle.js", - "author": "Igor Honhoff", - "license": "MIT", - "activationPoints": [ - "init" - ], - "scripts": { - "prepare": "webpack --config webpack.config.js", - "package": "rimraf ./data-plugin*.tgz && cp -f module.js ./dist/module.js && npm pack" - }, - "devDependencies": { - "rimraf": "^3.0.2", - "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" - }, - "bundledDependencies": [ - "sql.js", - "sqlite3" - ], - "files": [ - "dist/*", - "package.json", - "README.md" - ], - "dependencies": { - "sqlite3": "^5.1.6" - } -} diff --git a/app/electron/core/pre-install/base-plugin.tgz b/app/electron/core/pre-install/base-plugin.tgz deleted file mode 100644 index b53eef030..000000000 Binary files a/app/electron/core/pre-install/base-plugin.tgz and /dev/null differ diff --git a/app/electron/core/pre-install/data-plugin.tgz b/app/electron/core/pre-install/data-plugin.tgz deleted file mode 100644 index 90364adab..000000000 Binary files a/app/electron/core/pre-install/data-plugin.tgz and /dev/null differ diff --git a/app/electron/core/pre-install/model-management-plugin.tgz b/app/electron/core/pre-install/model-management-plugin.tgz deleted file mode 100644 index 371d9efa5..000000000 Binary files a/app/electron/core/pre-install/model-management-plugin.tgz and /dev/null differ diff --git a/app/electron/main.ts b/app/electron/main.ts deleted file mode 100644 index 1d53d6359..000000000 --- a/app/electron/main.ts +++ /dev/null @@ -1,221 +0,0 @@ -// @ts-nocheck -const { - app, - BrowserWindow, - screen: electronScreen, - dialog, - ipcMain, -} = require("electron"); -const isDev = require("electron-is-dev"); -const path = require("path"); -const pe = require("pluggable-electron/main"); -const fs = require("fs"); -const { mkdir, writeFile } = require("fs/promises"); -const { Readable } = require("stream"); -const { finished } = require("stream/promises"); -const request = require("request"); -const progress = require("request-progress"); - -let modelSession = undefined; -let modelName = "llama-2-7b-chat.gguf.q4_0.bin"; - -let window; - -const createMainWindow = () => { - window = new BrowserWindow({ - width: electronScreen.getPrimaryDisplay().workArea.width, - height: electronScreen.getPrimaryDisplay().workArea.height, - show: false, - backgroundColor: "white", - webPreferences: { - nodeIntegration: true, - enableRemoteModule: true, - preload: path.resolve(app.getAppPath(), "electron/preload.js"), - }, - }); - - ipcMain.handle("invokePluginFunc", async (event, plugin, method, ...args) => { - const plg = pe - .getStore() - .getActivePlugins() - .filter((p) => p.name === plugin)[0]; - const pluginPath = path.join( - app.getPath("userData"), - "plugins", - plg.name, - "dist/module.js", - ); - return await import( - /* webpackIgnore: true */ - pluginPath - ) - .then((plugin) => { - if (typeof plugin[method] === "function") { - return plugin[method](...args); - } else { - console.log(plugin[method]); - console.error(`Function "${method}" does not exist in the module.`); - } - }) - .then((res) => { - return res; - }) - .catch((err) => console.log(err)); - }); - - const startURL = isDev - ? "http://localhost:3000" - : `file://${path.join(__dirname, "../out/index.html")}`; - - window.loadURL(startURL); - - window.once("ready-to-show", () => window.show()); - window.on("closed", () => { - if (process.platform !== "darwin") app.quit(); - }); - - window.webContents.openDevTools(); -}; - -app.whenReady().then(() => { - createMainWindow(); - setupPlugins(); - - ipcMain.handle("userData", async (event) => { - return path.resolve(__dirname, "../"); - }); - - ipcMain.handle("downloadModel", async (event, url) => { - const userDataPath = app.getPath("userData"); - const destination = path.resolve(userDataPath, modelName); - - progress(request(url), {}) - .on("progress", function (state) { - window.webContents.send("model-download-update", { - ...state, - modelId: modelName, - }); - }) - .on("error", function (err) { - window.webContents.send("model-download-error", err); - }) - .on("end", function () { - app.relaunch(); - app.exit(); - // Do something after request finishes - }) - .pipe(fs.createWriteStream(destination)); - }); - - ipcMain.handle("deleteModel", async (event, modelFileName) => { - const userDataPath = app.getPath("userData"); - const fullPath = path.join(userDataPath, modelFileName); - - let result = "NULL"; - fs.unlink(fullPath, function (err) { - if (err && err.code == "ENOENT") { - console.info("File doesn't exist, won't remove it."); - result = "FILE_NOT_EXIST"; - } else if (err) { - console.error("Error occurred while trying to remove file"); - result = "ERROR"; - } else { - console.info(`removed`); - result = "REMOVED"; - } - }); - console.log(result); - return result; - }); - - // TODO: add options for model configuration - ipcMain.handle("initModel", async (event, product) => { - if (!product.fileName) { - await dialog.showMessageBox({ - message: "Selected model does not have file name..", - }); - - return; - } - - console.info(`Initializing model: ${product.name}..`); - import( - isDev - ? "../node_modules/node-llama-cpp/dist/index.js" - : path.resolve( - app.getAppPath(), - "./../../app.asar.unpacked/node_modules/node-llama-cpp/dist/index.js", - ) - ) - .then(({ LlamaContext, LlamaChatSession, LlamaModel }) => { - const modelPath = path.join(app.getPath("userData"), product.fileName); - // TODO: check if file is already there - const model = new LlamaModel({ - modelPath: modelPath, - }); - const context = new LlamaContext({ model }); - modelSession = new LlamaChatSession({ context }); - console.info(`Init model ${product.name} successfully!`); - }) - .catch(async (e) => { - await dialog.showMessageBox({ - message: "Failed to import LLM module", - }); - }); - }); - - ipcMain.handle("getDownloadedModels", async (event) => { - const userDataPath = app.getPath("userData"); - - const allBinariesName = []; - var files = fs.readdirSync(userDataPath); - for (var i = 0; i < files.length; i++) { - var filename = path.join(userDataPath, files[i]); - var stat = fs.lstatSync(filename); - if (stat.isDirectory()) { - // ignore - } else if (filename.endsWith(".bin")) { - allBinariesName.push(filename); - } - } - return allBinariesName; - }); - - ipcMain.handle("sendInquiry", async (event, question) => { - if (!modelSession) { - console.error("Model session has not been initialized!"); - return; - } - return modelSession.prompt(question); - }); - - app.on("activate", () => { - if (!BrowserWindow.getAllWindows().length) { - createMainWindow(); - } - }); -}); - -app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } -}); - -function setupPlugins() { - pe.init({ - // Function to check from the main process that user wants to install a plugin - confirmInstall: async (plugins) => { - const answer = await dialog.showMessageBox({ - message: `Are you sure you want to install the plugin ${plugins.join( - ", ", - )}`, - buttons: ["Ok", "Cancel"], - cancelId: 1, - }); - return answer.response == 0; - }, - // Path to install plugin to - pluginsPath: path.join(app.getPath("userData"), "plugins"), - }); -} diff --git a/app/electron/preload.js b/app/electron/preload.js deleted file mode 100644 index 574597e9f..000000000 --- a/app/electron/preload.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable react-hooks/rules-of-hooks */ -// Make Pluggable Electron's facade available to the renderer on window.plugins -const useFacade = require("pluggable-electron/facade"); -useFacade(); - -const { contextBridge, ipcRenderer } = require("electron"); - -contextBridge.exposeInMainWorld("electronAPI", { - invokePluginFunc: (plugin, method, ...args) => - ipcRenderer.invoke("invokePluginFunc", plugin, method, ...args), - - userData: () => ipcRenderer.invoke("userData"), - - sendInquiry: (question) => ipcRenderer.invoke("sendInquiry", question), - - initModel: (product) => ipcRenderer.invoke("initModel", product), - - getDownloadedModels: () => ipcRenderer.invoke("getDownloadedModels"), - - getAvailableModels: () => ipcRenderer.invoke("getAvailableModels"), - - deleteModel: (path) => ipcRenderer.invoke("deleteModel", path), - - downloadModel: (url) => ipcRenderer.invoke("downloadModel", url), - - onModelDownloadUpdate: (callback) => - ipcRenderer.on("model-download-update", callback), - - onModelDownloadError: (callback) => - ipcRenderer.on("model-download-error", callback), -}); diff --git a/app/images/jan-desktop-dev-instruction-1.png b/app/images/jan-desktop-dev-instruction-1.png deleted file mode 100644 index 5f2e60da7..000000000 Binary files a/app/images/jan-desktop-dev-instruction-1.png and /dev/null differ diff --git a/app/images/jan-desktop-dev-instruction-2.png b/app/images/jan-desktop-dev-instruction-2.png deleted file mode 100644 index ea6cb9526..000000000 Binary files a/app/images/jan-desktop-dev-instruction-2.png and /dev/null differ diff --git a/app/images/jan-desktop-dev-instruction-3.png b/app/images/jan-desktop-dev-instruction-3.png deleted file mode 100644 index 29f071985..000000000 Binary files a/app/images/jan-desktop-dev-instruction-3.png and /dev/null differ diff --git a/app/images/jan-desktop-dev-instruction-4.png b/app/images/jan-desktop-dev-instruction-4.png deleted file mode 100644 index 30524d91a..000000000 Binary files a/app/images/jan-desktop-dev-instruction-4.png and /dev/null differ diff --git a/app/images/jan-desktop-dev-instruction-5.png b/app/images/jan-desktop-dev-instruction-5.png deleted file mode 100644 index 88bcf56f0..000000000 Binary files a/app/images/jan-desktop-dev-instruction-5.png and /dev/null differ diff --git a/app/images/jan-desktop-dev-instruction-6.png b/app/images/jan-desktop-dev-instruction-6.png deleted file mode 100644 index ba5c1e383..000000000 Binary files a/app/images/jan-desktop-dev-instruction-6.png and /dev/null differ diff --git a/conf/db/docker_psql_init.sql b/conf/db/docker_psql_init.sql deleted file mode 100644 index db34e8393..000000000 --- a/conf/db/docker_psql_init.sql +++ /dev/null @@ -1,26 +0,0 @@ -CREATE DATABASE "jan-keycloak" - WITH - OWNER = postgres - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.utf8' - LC_CTYPE = 'en_US.utf8' - TABLESPACE = pg_default - CONNECTION LIMIT = -1; - -CREATE DATABASE "jan-hasura-data" - WITH - OWNER = postgres - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.utf8' - LC_CTYPE = 'en_US.utf8' - TABLESPACE = pg_default - CONNECTION LIMIT = -1; - -CREATE DATABASE "jan-hasura-metadata" - WITH - OWNER = postgres - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.utf8' - LC_CTYPE = 'en_US.utf8' - TABLESPACE = pg_default - CONNECTION LIMIT = -1; \ No newline at end of file diff --git a/conf/keycloak_conf/example-realm.json b/conf/keycloak_conf/example-realm.json deleted file mode 100644 index bc10dac64..000000000 --- a/conf/keycloak_conf/example-realm.json +++ /dev/null @@ -1,2311 +0,0 @@ -{ - "id": "d3ebd3d9-2493-4aa2-942b-3118a216b430", - "realm": "hasura", - "notBefore": 0, - "defaultSignatureAlgorithm": "RS256", - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 300, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 1800, - "ssoSessionMaxLifespan": 36000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 300, - "oauth2DeviceCodeLifespan": 600, - "oauth2DevicePollingInterval": 5, - "enabled": true, - "sslRequired": "external", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "roles": { - "realm": [ - { - "id": "7219280c-2d93-4cb5-9ff9-fa4b639716fd", - "name": "uma_authorization", - "description": "${role_uma_authorization}", - "composite": false, - "clientRole": false, - "containerId": "d3ebd3d9-2493-4aa2-942b-3118a216b430", - "attributes": {} - }, - { - "id": "7fb465bc-beae-431b-8a38-06afa8b4c75c", - "name": "user", - "description": "", - "composite": false, - "clientRole": false, - "containerId": "d3ebd3d9-2493-4aa2-942b-3118a216b430", - "attributes": {} - }, - { - "id": "b34240e1-92b8-48e9-aaa5-82eecbdcb283", - "name": "default-roles-hasura", - "description": "${role_default-roles}", - "composite": true, - "composites": { - "realm": ["offline_access", "uma_authorization"], - "client": { - "account": ["manage-account", "view-profile"] - } - }, - "clientRole": false, - "containerId": "d3ebd3d9-2493-4aa2-942b-3118a216b430", - "attributes": {} - }, - { - "id": "3ece9760-6a06-4d75-9efc-27164c8253c8", - "name": "offline_access", - "description": "${role_offline-access}", - "composite": false, - "clientRole": false, - "containerId": "d3ebd3d9-2493-4aa2-942b-3118a216b430", - "attributes": {} - } - ], - "client": { - "realm-management": [ - { - "id": "c8c637d4-39a5-4170-8d2f-1aef0a2f9720", - "name": "query-groups", - "description": "${role_query-groups}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "e81f684f-c4ff-425e-861d-80507258b321", - "name": "manage-authorization", - "description": "${role_manage-authorization}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "88d97cbc-e7e1-4561-ad9c-8cf1161a55a0", - "name": "query-realms", - "description": "${role_query-realms}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "67063d5f-8023-4be9-8db2-37f81dfeb90b", - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "024c8120-8208-4ad4-b098-27c7c9d549df", - "name": "view-realm", - "description": "${role_view-realm}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "a2fe97c7-b0d2-444f-bdba-efb2bfecda0f", - "name": "create-client", - "description": "${role_create-client}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "bc2425ed-2269-431c-81f6-eb4401020952", - "name": "query-users", - "description": "${role_query-users}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "a2cb5869-dc32-4373-8a10-71b9132c850e", - "name": "view-authorization", - "description": "${role_view-authorization}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "a8b11879-261c-4e4f-8b05-414069988810", - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "0810aa4f-a32c-432a-9c16-0374233f17e6", - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": ["query-clients"] - } - }, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "53b48727-828f-406c-aa7e-b0d1c4109d0b", - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "27751c74-74f3-4fbf-b42a-124de7207dc0", - "name": "manage-clients", - "description": "${role_manage-clients}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "44c4d09a-8b0e-413e-91a4-c383ef17b345", - "name": "query-clients", - "description": "${role_query-clients}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "837d8209-0fbf-406d-a1f4-d3672879fd7c", - "name": "manage-realm", - "description": "${role_manage-realm}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "90b904a0-ddf1-4542-902e-f0f0cd4bc23e", - "name": "manage-users", - "description": "${role_manage-users}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "49328548-01c4-477e-90e8-5cdec6ede9d2", - "name": "view-events", - "description": "${role_view-events}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "5f381d33-4e28-4b50-87be-0cc0e4887e2f", - "name": "realm-admin", - "description": "${role_realm-admin}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-groups", - "manage-authorization", - "view-realm", - "view-identity-providers", - "query-realms", - "create-client", - "view-authorization", - "query-users", - "manage-identity-providers", - "view-clients", - "impersonation", - "manage-clients", - "query-clients", - "manage-realm", - "manage-users", - "view-events", - "view-users", - "manage-events" - ] - } - }, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "13b75adb-cf15-4f02-8c1e-b70bf405b692", - "name": "view-users", - "description": "${role_view-users}", - "composite": true, - "composites": { - "client": { - "realm-management": ["query-groups", "query-users"] - } - }, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - }, - { - "id": "b5126b18-1e29-4989-a0ce-3350feb02b42", - "name": "manage-events", - "description": "${role_manage-events}", - "composite": false, - "clientRole": true, - "containerId": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "attributes": {} - } - ], - "security-admin-console": [], - "admin-cli": [], - "account-console": [], - "broker": [ - { - "id": "ba86f97b-0032-465d-b52d-06d0cb1514b5", - "name": "read-token", - "description": "${role_read-token}", - "composite": false, - "clientRole": true, - "containerId": "4a3abf8b-7ce0-4eb3-8733-0b76bde3125d", - "attributes": {} - } - ], - "account": [ - { - "id": "8107bb62-629a-4c05-a6b3-9ec05db9feab", - "name": "manage-consent", - "description": "${role_manage-consent}", - "composite": true, - "composites": { - "client": { - "account": ["view-consent"] - } - }, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "cb761f1a-f422-4292-9f27-aeca063ae6ad", - "name": "view-applications", - "description": "${role_view-applications}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "b87631c3-f3bb-4684-825e-53b7b784687d", - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": ["manage-account-links"] - } - }, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "81a519c5-d106-4b4c-986d-3416537d91b6", - "name": "view-groups", - "description": "${role_view-groups}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "e563f5f3-e86f-491c-882a-7acc3d84c6f0", - "name": "view-consent", - "description": "${role_view-consent}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "4434c108-c594-43e9-b8d4-8ded56196cc5", - "name": "view-profile", - "description": "${role_view-profile}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "c342ec0b-6885-4d8d-b036-1aafdc376c06", - "name": "delete-account", - "description": "${role_delete-account}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - }, - { - "id": "5c200c4e-fd80-4cd1-8723-562ba7430398", - "name": "manage-account-links", - "description": "${role_manage-account-links}", - "composite": false, - "clientRole": true, - "containerId": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "attributes": {} - } - ], - "hasura": [ - { - "id": "e971ec56-92a0-4c06-a8a2-a35946852ee6", - "name": "uma_protection", - "composite": false, - "clientRole": true, - "containerId": "4be1cdcc-b0b3-4581-957b-54fa17c0d929", - "attributes": {} - }, - { - "id": "8cbd62f4-daa2-4809-850b-88870e2c70fc", - "name": "user", - "description": "", - "composite": false, - "clientRole": true, - "containerId": "4be1cdcc-b0b3-4581-957b-54fa17c0d929", - "attributes": {} - } - ] - } - }, - "groups": [], - "defaultRole": { - "id": "b34240e1-92b8-48e9-aaa5-82eecbdcb283", - "name": "default-roles-hasura", - "description": "${role_default-roles}", - "composite": true, - "clientRole": false, - "containerId": "d3ebd3d9-2493-4aa2-942b-3118a216b430" - }, - "requiredCredentials": ["password"], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpPolicyCodeReusable": false, - "otpSupportedApplications": [ - "totpAppGoogleName", - "totpAppMicrosoftAuthenticatorName", - "totpAppFreeOTPName" - ], - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": ["ES256"], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "users": [ - { - "username": "username", - "enabled": true, - "emailVerified": true, - "credentials": [ - { - "type": "password", - "value": "password" - } - ], - "realmRoles": [ - "user", - "default-roles-hasura" - ], - "clientRoles": { - "hasura": [ - "user" - ] - } - }, - { - "id": "8728e38e-6b60-44d2-8830-f1e2ad284a02", - "createdTimestamp": 1692777925764, - "username": "service-account-hasura", - "enabled": true, - "totp": false, - "emailVerified": false, - "serviceAccountClientId": "hasura", - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": ["user", "default-roles-hasura"], - "clientRoles": { - "hasura": ["uma_protection"] - }, - "notBefore": 0, - "groups": [] - } - ], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": ["offline_access"] - }, - { - "clientScope": "hasura", - "roles": ["user"] - } - ], - "clientScopeMappings": { - "account": [ - { - "client": "account-console", - "roles": ["manage-account", "view-groups"] - } - ] - }, - "clients": [ - { - "id": "ce02d0ff-b633-4d79-8a33-2c8241017d72", - "clientId": "account", - "name": "${client_account}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/hasura/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": ["/realms/hasura/account/*"], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "101df256-3450-4b5c-8d0f-d29b531e3499", - "clientId": "account-console", - "name": "${client_account-console}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/hasura/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": ["/realms/hasura/account/*"], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "b06a98d0-6d91-4260-9406-aea123f842dc", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "db12bda8-7624-46cc-a84f-9c83cf99b370", - "clientId": "admin-cli", - "name": "${client_admin-cli}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "4a3abf8b-7ce0-4eb3-8733-0b76bde3125d", - "clientId": "broker", - "name": "${client_broker}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "4be1cdcc-b0b3-4581-957b-54fa17c0d929", - "clientId": "hasura", - "name": "Hasura", - "description": "", - "rootUrl": "", - "adminUrl": "", - "baseUrl": "", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "oMtCPAV7diKpE564SBspgKj4HqlKM4Hy", - "redirectUris": ["http://localhost:3000/*"], - "webOrigins": ["http://localhost:3000"], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": true, - "authorizationServicesEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "oauth2.device.authorization.grant.enabled": "false", - "client.secret.creation.time": "1692777925", - "backchannel.logout.session.required": "true", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "c4016925-f659-455a-9cdb-29bba88327e9", - "name": "Client ID", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "client_id", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "client_id", - "jsonType.label": "String" - } - }, - { - "id": "e80e0f4c-cd0d-4bb8-a1e4-108a49f4d1a7", - "name": "Client Host", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientHost", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientHost", - "jsonType.label": "String" - } - }, - { - "id": "3cb8ba1a-81f2-42b7-91b0-3fbe29126262", - "name": "Client IP Address", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientAddress", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientAddress", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "hasura", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ], - "authorizationSettings": { - "allowRemoteResourceManagement": true, - "policyEnforcementMode": "ENFORCING", - "resources": [ - { - "name": "Default Resource", - "type": "urn:hasura:resources:default", - "ownerManagedAccess": false, - "attributes": {}, - "_id": "088f6856-3491-4600-ac5d-0287da57511c", - "uris": ["/*"] - } - ], - "policies": [ - { - "id": "f82ec078-33ce-4204-83c9-627a802c0821", - "name": "Default Policy", - "description": "A policy that grants access only for users within this realm", - "type": "role", - "logic": "POSITIVE", - "decisionStrategy": "AFFIRMATIVE", - "config": { - "roles": "[{\"id\":\"default-roles-hasura\",\"required\":false}]" - } - }, - { - "id": "2cad4a9f-b0f6-4067-98a7-4f42ed5e33ef", - "name": "Default Permission", - "description": "A permission that applies to the default resource type", - "type": "resource", - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "config": { - "defaultResourceType": "urn:hasura:resources:default", - "applyPolicies": "[\"Default Policy\"]" - } - } - ], - "scopes": [], - "decisionStrategy": "UNANIMOUS" - } - }, - { - "id": "5d7dda49-d56d-4c64-8a01-ee5dd5310c81", - "clientId": "realm-management", - "name": "${client_realm-management}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "29f3fff6-2a63-4f7b-9474-d2385f0eff32", - "clientId": "security-admin-console", - "name": "${client_security-admin-console}", - "rootUrl": "${authAdminUrl}", - "baseUrl": "/admin/hasura/console/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": ["/admin/hasura/console/*"], - "webOrigins": ["+"], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "795b2582-0f87-46ac-8be0-13518ad27445", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - } - ], - "clientScopes": [ - { - "id": "7df17b55-8301-4667-b9f3-41f9520a92cf", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } - }, - { - "id": "9cf833ae-3238-4aa3-9a9a-bbb8bc3767e3", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "8d49f2bc-7ffc-4ee0-ae71-d82623330caf", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "7e1a84a8-47d0-4cd8-ba0f-dc689588b7ec", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "807ae7c0-7c18-4d46-b1c6-9d191294bf7b", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ] - }, - { - "id": "ad8bfcfe-469b-4e72-82ab-2e8b564efc14", - "name": "acr", - "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "96589cee-a8cc-4919-8b60-00a77a34ff87", - "name": "acr loa level", - "protocol": "openid-connect", - "protocolMapper": "oidc-acr-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true" - } - } - ] - }, - { - "id": "2a8948cb-65cf-4ce4-ae11-fae5d9391fd3", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "6679f3f8-c764-4cd4-ae63-9da31200e7c5", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - }, - { - "id": "09a8bf42-8326-40a5-b1d3-0a65fe6236c3", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "794f2bc0-4b14-4cb3-a7f2-730b2fabc84d", - "name": "hasura", - "description": "", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "gui.order": "", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "74c7a728-24a3-480e-bbb9-2129bd2dccb1", - "name": "x-hasura-default-role", - "protocol": "openid-connect", - "protocolMapper": "oidc-hardcoded-claim-mapper", - "consentRequired": false, - "config": { - "claim.value": "user", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "https://hasura\\.io/jwt/claims.x-hasura-default-role", - "jsonType.label": "String", - "access.tokenResponse.claim": "false" - } - }, - { - "id": "b451832d-670a-4e0d-878e-904c2b1598c2", - "name": "x-hasura-user-id", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "id", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "https://hasura\\.io/jwt/claims.x-hasura-user-id", - "jsonType.label": "String" - } - }, - { - "id": "eb62cfc4-ea5f-454a-9c78-384cb5e80373", - "name": "x-hasura-allowed-roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "https://hasura\\.io/jwt/claims.x-hasura-allowed-roles", - "jsonType.label": "String", - "usermodel.clientRoleMapping.clientId": "hasura" - } - } - ] - }, - { - "id": "8321f73d-4f9e-486e-ae03-cde49fc78bc1", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "56bb56c7-0237-4263-b858-7f9cdba57a1d", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } - } - ] - }, - { - "id": "c2c39673-f405-4fed-81a5-3bc3aa333b8b", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "01e5705c-f668-476d-8526-7d8851531832", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - }, - { - "id": "66d6d45a-d4ca-4574-bcbe-b26982b4c7f8", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "f03591f6-3ea2-405b-b47c-6eb797ec5926", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "3c61cc63-50f9-4cfb-b45e-422c59161709", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "2dfbc3d5-81f1-4160-9b0a-c58fd997fe68", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "a5e7f48a-219c-4bca-a491-d54e8788d8be", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "837efb21-32d2-47e5-8b1c-fdf5d3ea17bc", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "d1200744-27c1-426c-8332-ce4b0c433c50", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - }, - { - "id": "63eae02f-f44b-4fe6-91f2-a16d096c46db", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "5cbb20a8-2947-420d-9a5d-1ce4eb928117", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "fdb72b90-48f8-4dcf-be77-e246fc77814c", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "a61f7495-5229-48a8-a1d2-0596f13d1c06", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "ac4150b4-0b5f-4187-a81f-21e582fde2b4", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "2f8cf479-e0f5-49a6-a46b-f4708f60840e", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - }, - { - "id": "2530d28b-3135-442d-aabe-3dcd20d6370c", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - }, - { - "id": "68ca4cca-c6d3-4fa4-8079-ee0c81286577", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "ef95b412-17ff-4ef5-b9e9-8b95f7cc44b3", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "long" - } - } - ] - }, - { - "id": "8b3ba733-fa23-489f-b954-a0b89fba8b54", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "43ee6247-a7fd-4649-8770-5c966a23b831", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} - } - ] - }, - { - "id": "818f4f96-a63c-4c1d-9251-d999517ede72", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "f9fbf5ed-195e-44f1-a5d3-6bf64919bb2b", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "id": "e3f2c7fe-ca50-4b01-b999-098c82beb362", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "7ae1a4ac-99db-4a27-8f18-f537a8020e4f", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - }, - { - "id": "edd5d134-b2c1-47d8-9cc5-3558559cf407", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - } - ] - } - ], - "defaultDefaultClientScopes": [ - "role_list", - "profile", - "email", - "roles", - "web-origins", - "acr", - "hasura" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "address", - "phone", - "microprofile-jwt" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "referrerPolicy": "no-referrer", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" - }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": ["jboss-logging"], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "identityProviders": [], - "identityProviderMappers": [], - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "e2254ce7-52d6-4450-aa77-5ba2b40b8e26", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": ["true"] - } - }, - { - "id": "b88f3a6b-b2a8-476d-9433-904ca547f64c", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "saml-user-attribute-mapper", - "oidc-usermodel-property-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-full-name-mapper", - "saml-user-property-mapper", - "saml-role-list-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-address-mapper" - ] - } - }, - { - "id": "d9ba5290-8c0e-4fa7-bf53-afc4fab4ec4b", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": ["true"] - } - }, - { - "id": "1c24034f-5374-4020-b8e2-ba2eb4c0a944", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "e66a399a-317f-42c0-8ec7-9e2ba781a53d", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "eec0d3e9-e1e2-41c0-8a03-cc5f06c0f77e", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": ["true"], - "client-uris-must-match": ["true"] - } - }, - { - "id": "01f2436b-aa02-4f55-ac64-6132dd6ee375", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-usermodel-property-mapper", - "saml-user-property-mapper", - "oidc-usermodel-attribute-mapper", - "saml-user-attribute-mapper", - "oidc-full-name-mapper", - "oidc-address-mapper", - "oidc-sha256-pairwise-sub-mapper", - "saml-role-list-mapper" - ] - } - }, - { - "id": "86fe59f0-cb96-4a39-8476-ae092479fb69", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": ["200"] - } - } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "796db70c-b8e9-4efa-b225-91d8cc8099ea", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "priority": ["100"], - "algorithm": ["RSA-OAEP"] - } - }, - { - "id": "06ed66b9-a1ac-4662-afb4-889d176189b3", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": ["100"], - "algorithm": ["HS256"] - } - }, - { - "id": "fc8169fe-cb2b-4edb-befa-fa136215a184", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": ["100"] - } - }, - { - "id": "9c40d8de-d867-4f6a-9637-b99500551f15", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": ["100"] - } - } - ] - }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "da3e4aa5-578c-4a70-a0ee-6bd0ac54acd5", - "alias": "Account verification options", - "description": "Method with which to verity the existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false - } - ] - }, - { - "id": "489875e5-f48e-484a-8a82-d49e8af1834a", - "alias": "Browser - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "43d1a926-1785-4391-bf16-519da996ab47", - "alias": "Direct Grant - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "27d47660-5e77-4732-b781-36e88d2f6baf", - "alias": "First broker login - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "a7d1c2ef-57c8-4907-b21b-0d2df675c9c0", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Account verification options", - "userSetupAllowed": false - } - ] - }, - { - "id": "5f97b94f-e60d-498e-8874-d719adbcc985", - "alias": "Reset - Conditional OTP", - "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "22b24e38-53ff-4788-ae8a-dcbce66819a7", - "alias": "User creation or linking", - "description": "Flow for the existing/non-existing user alternatives", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false - } - ] - }, - { - "id": "aa67bda7-bfc9-4cd2-84a5-22e371e89135", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "f9b90830-656d-4378-bd98-c11d8a20295c", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "identity-provider-redirector", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 25, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "forms", - "userSetupAllowed": false - } - ] - }, - { - "id": "9b00a800-deea-4b4a-b9cb-530886a7098a", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-secret-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-x509", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "88c2fd63-c912-4727-8323-63d31333efaf", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "12a8d6fe-ad7e-4443-9b40-b8855535def0", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "c64af03f-9326-4689-ad7e-d804b3fe0d60", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "User creation or linking", - "userSetupAllowed": false - } - ] - }, - { - "id": "b0e1e734-a068-4ab1-b643-9ac5e18b54b9", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "8978b81a-5145-40bf-9a02-4b9f5c2270cf", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": true, - "flowAlias": "registration form", - "userSetupAllowed": false - } - ] - }, - { - "id": "dd0879d0-a1c7-47dd-8343-5495259359dc", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-profile-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-password-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 50, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-recaptcha-action", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 60, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "2b5b0164-695d-406a-831d-de8e0864ba8b", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-credential-email", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 40, - "autheticatorFlow": true, - "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "b26ac227-95e1-4dea-9673-9cf6f72950d7", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - } - ], - "authenticatorConfig": [ - { - "id": "2c59769e-dc23-4813-8ab7-deaa7cde4de5", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "49f039b3-3d77-43d1-9a32-706285b18e3d", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } - } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "TERMS_AND_CONDITIONS", - "name": "Terms and Conditions", - "providerId": "TERMS_AND_CONDITIONS", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "delete_account", - "name": "Delete Account", - "providerId": "delete_account", - "enabled": false, - "defaultAction": false, - "priority": 60, - "config": {} - }, - { - "alias": "webauthn-register", - "name": "Webauthn Register", - "providerId": "webauthn-register", - "enabled": true, - "defaultAction": false, - "priority": 70, - "config": {} - }, - { - "alias": "webauthn-register-passwordless", - "name": "Webauthn Register Passwordless", - "providerId": "webauthn-register-passwordless", - "enabled": true, - "defaultAction": false, - "priority": 80, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "attributes": { - "cibaBackchannelTokenDeliveryMode": "poll", - "cibaExpiresIn": "120", - "cibaAuthRequestedUserHint": "login_hint", - "oauth2DeviceCodeLifespan": "600", - "oauth2DevicePollingInterval": "5", - "parRequestUriLifespan": "60", - "cibaInterval": "5", - "realmReusableOtpCode": "false" - }, - "keycloakVersion": "22.0.0", - "userManagedAccessAllowed": false, - "clientProfiles": { - "profiles": [] - }, - "clientPolicies": { - "policies": [] - } -} diff --git a/conf/keycloak_theme/keywind/.DS_Store b/conf/keycloak_theme/keywind/.DS_Store deleted file mode 100644 index 694ba58ec..000000000 Binary files a/conf/keycloak_theme/keywind/.DS_Store and /dev/null differ diff --git a/conf/keycloak_theme/keywind/login/assets/icons/arrow-top-right-on-square.ftl b/conf/keycloak_theme/keywind/login/assets/icons/arrow-top-right-on-square.ftl deleted file mode 100644 index 81c4bf81d..000000000 --- a/conf/keycloak_theme/keywind/login/assets/icons/arrow-top-right-on-square.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/20/solid/arrow-top-right-on-square.svg --> -<#macro kw> - <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> - <path clip-rule="evenodd" d="M4.25 5.5C3.83579 5.5 3.5 5.83579 3.5 6.25V14.75C3.5 15.1642 3.83579 15.5 4.25 15.5H12.75C13.1642 15.5 13.5 15.1642 13.5 14.75V10.75C13.5 10.3358 13.8358 10 14.25 10C14.6642 10 15 10.3358 15 10.75V14.75C15 15.9926 13.9926 17 12.75 17H4.25C3.00736 17 2 15.9926 2 14.75V6.25C2 5.00736 3.00736 4 4.25 4H9.25C9.66421 4 10 4.33579 10 4.75C10 5.16421 9.66421 5.5 9.25 5.5H4.25Z" fill-rule="evenodd" /> - <path clip-rule="evenodd" d="M6.19385 12.7532C6.47175 13.0603 6.94603 13.0841 7.25319 12.8062L16.5 4.43999V7.25C16.5 7.66421 16.8358 8 17.25 8C17.6642 8 18 7.66421 18 7.25V2.75C18 2.33579 17.6642 2 17.25 2H12.75C12.3358 2 12 2.33579 12 2.75C12 3.16421 12.3358 3.5 12.75 3.5H15.3032L6.24682 11.6938C5.93966 11.9717 5.91595 12.446 6.19385 12.7532Z" fill-rule="evenodd" /> - </svg> -</#macro> diff --git a/conf/keycloak_theme/keywind/login/assets/icons/chevron-down.ftl b/conf/keycloak_theme/keywind/login/assets/icons/chevron-down.ftl deleted file mode 100644 index 673ef1191..000000000 --- a/conf/keycloak_theme/keywind/login/assets/icons/chevron-down.ftl +++ /dev/null @@ -1,6 +0,0 @@ -<#-- https://github.com/tailwindlabs/heroicons/blob/master/src/20/solid/chevron-down.svg --> -<#macro kw> - <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> - <path clip-rule="evenodd" d="M5.23017 7.20938C5.52875 6.92228 6.00353 6.93159 6.29063 7.23017L10 11.1679L13.7094 7.23017C13.9965 6.93159 14.4713 6.92228 14.7698 7.20938C15.0684 7.49647 15.0777 7.97125 14.7906 8.26983L10.5406 12.7698C10.3992 12.9169 10.204 13 10 13C9.79599 13 9.60078 12.9169 9.45938 12.7698L5.20938 8.26983C4.92228 7.97125 4.93159 7.49647 5.23017 7.20938Z" fill-rule="evenodd" /> - </svg> -</#macro> diff --git a/conf/keycloak_theme/keywind/login/assets/providers/bitbucket.ftl b/conf/keycloak_theme/keywind/login/assets/providers/bitbucket.ftl deleted file mode 100644 index 068bc73d8..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/bitbucket.ftl +++ /dev/null @@ -1,14 +0,0 @@ -<#-- https://atlassian.design/resources/logo-library --> -<#macro kw name="Bitbucket"> - <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <title>${name} - - - - - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/discord.ftl b/conf/keycloak_theme/keywind/login/assets/providers/discord.ftl deleted file mode 100644 index 8ebecaa48..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/discord.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#-- https://discord.com/branding --> -<#macro kw name="Discord"> - - ${name} - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/facebook.ftl b/conf/keycloak_theme/keywind/login/assets/providers/facebook.ftl deleted file mode 100644 index bc692e759..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/facebook.ftl +++ /dev/null @@ -1,8 +0,0 @@ -<#-- https://www.facebook.com/brand/resources/facebookapp/logo --> -<#macro kw name="Facebook"> - - ${name} - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/github.ftl b/conf/keycloak_theme/keywind/login/assets/providers/github.ftl deleted file mode 100644 index 9523103c4..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/github.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#-- https://github.com/logos --> -<#macro kw name="GitHub"> - - ${name} - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/gitlab.ftl b/conf/keycloak_theme/keywind/login/assets/providers/gitlab.ftl deleted file mode 100644 index 4acfc132d..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/gitlab.ftl +++ /dev/null @@ -1,10 +0,0 @@ -<#-- https://about.gitlab.com/press/press-kit --> -<#macro kw name="GitLab"> - - ${name} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/google.ftl b/conf/keycloak_theme/keywind/login/assets/providers/google.ftl deleted file mode 100644 index b536cdbb8..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/google.ftl +++ /dev/null @@ -1,10 +0,0 @@ -<#-- https://developers.google.com/identity/branding-guidelines --> -<#macro kw name="Google"> - - ${name} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/instagram.ftl b/conf/keycloak_theme/keywind/login/assets/providers/instagram.ftl deleted file mode 100644 index c4996d880..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/instagram.ftl +++ /dev/null @@ -1,35 +0,0 @@ -<#-- https://www.facebook.com/brand/resources/instagram/instagram-brand --> -<#macro kw name="Instagram"> - - ${name} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/linkedin.ftl b/conf/keycloak_theme/keywind/login/assets/providers/linkedin.ftl deleted file mode 100644 index 944d14335..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/linkedin.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#-- https://brand.linkedin.com/downloads --> -<#macro kw name="LinkedIn"> - - ${name} - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/microsoft.ftl b/conf/keycloak_theme/keywind/login/assets/providers/microsoft.ftl deleted file mode 100644 index 408635b84..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/microsoft.ftl +++ /dev/null @@ -1,10 +0,0 @@ -<#-- https://learn.microsoft.com/azure/active-directory/develop/howto-add-branding-in-azure-ad-apps --> -<#macro kw name="Microsoft"> - - ${name} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/oidc.ftl b/conf/keycloak_theme/keywind/login/assets/providers/oidc.ftl deleted file mode 100644 index f7954ff5e..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/oidc.ftl +++ /dev/null @@ -1,9 +0,0 @@ -<#-- https://openid.net/add-openid/logos --> -<#macro kw name="OpenID"> - - ${name} - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/openshift.ftl b/conf/keycloak_theme/keywind/login/assets/providers/openshift.ftl deleted file mode 100644 index e85ddef7e..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/openshift.ftl +++ /dev/null @@ -1,11 +0,0 @@ -<#-- https://www.redhat.com/technologies/cloud-computing/openshift --> -<#macro kw name="Red Hat OpenShift"> - - ${name} - - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/paypal.ftl b/conf/keycloak_theme/keywind/login/assets/providers/paypal.ftl deleted file mode 100644 index 7946e03cd..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/paypal.ftl +++ /dev/null @@ -1,9 +0,0 @@ -<#-- https://www.paypal.com --> -<#macro kw name="PayPal"> - - ${name} - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/providers.ftl b/conf/keycloak_theme/keywind/login/assets/providers/providers.ftl deleted file mode 100644 index b9c55f6c8..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/providers.ftl +++ /dev/null @@ -1,79 +0,0 @@ -<#import "./bitbucket.ftl" as bitbucketIcon> -<#import "./discord.ftl" as discordIcon> -<#import "./facebook.ftl" as facebookIcon> -<#import "./github.ftl" as githubIcon> -<#import "./gitlab.ftl" as gitlabIcon> -<#import "./google.ftl" as googleIcon> -<#import "./instagram.ftl" as instagramIcon> -<#import "./linkedin.ftl" as linkedinIcon> -<#import "./microsoft.ftl" as microsoftIcon> -<#import "./oidc.ftl" as oidcIcon> -<#import "./openshift.ftl" as openshiftIcon> -<#import "./paypal.ftl" as paypalIcon> -<#import "./slack.ftl" as slackIcon> -<#import "./stackoverflow.ftl" as stackoverflowIcon> -<#import "./twitter.ftl" as twitterIcon> - -<#macro bitbucket> - <@bitbucketIcon.kw /> - - -<#macro discord> - <@discordIcon.kw /> - - -<#macro facebook> - <@facebookIcon.kw /> - - -<#macro github> - <@githubIcon.kw /> - - -<#macro gitlab> - <@gitlabIcon.kw /> - - -<#macro google> - <@googleIcon.kw /> - - -<#macro instagram> - <@instagramIcon.kw /> - - -<#macro linkedin> - <@linkedinIcon.kw /> - - -<#macro microsoft> - <@microsoftIcon.kw /> - - -<#macro oidc> - <@oidcIcon.kw /> - - -<#macro "openshift-v3"> - <@openshiftIcon.kw /> - - -<#macro "openshift-v4"> - <@openshiftIcon.kw /> - - -<#macro paypal> - <@paypalIcon.kw /> - - -<#macro slack> - <@slackIcon.kw /> - - -<#macro stackoverflow> - <@stackoverflowIcon.kw /> - - -<#macro twitter> - <@twitterIcon.kw /> - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/slack.ftl b/conf/keycloak_theme/keywind/login/assets/providers/slack.ftl deleted file mode 100644 index d4dffe3bb..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/slack.ftl +++ /dev/null @@ -1,14 +0,0 @@ -<#-- https://slack.com/media-kit --> -<#macro kw name="Slack"> - - ${name} - - - - - - - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/stackoverflow.ftl b/conf/keycloak_theme/keywind/login/assets/providers/stackoverflow.ftl deleted file mode 100644 index 1ffad8d6a..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/stackoverflow.ftl +++ /dev/null @@ -1,8 +0,0 @@ -<#-- https://stackoverflow.design/brand/logo --> -<#macro kw name="Stack Overflow"> - - ${name} - - - - diff --git a/conf/keycloak_theme/keywind/login/assets/providers/twitter.ftl b/conf/keycloak_theme/keywind/login/assets/providers/twitter.ftl deleted file mode 100644 index 2bc7e7e49..000000000 --- a/conf/keycloak_theme/keywind/login/assets/providers/twitter.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#-- https://about.twitter.com/en/who-we-are/brand-toolkit --> -<#macro kw name="Twitter"> - - ${name} - - - diff --git a/conf/keycloak_theme/keywind/login/components/atoms/alert.ftl b/conf/keycloak_theme/keywind/login/components/atoms/alert.ftl deleted file mode 100644 index 58e8309f0..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/alert.ftl +++ /dev/null @@ -1,22 +0,0 @@ -<#macro kw color=""> - <#switch color> - <#case "error"> - <#assign colorClass="bg-red-100 text-red-600"> - <#break> - <#case "info"> - <#assign colorClass="bg-blue-100 text-blue-600"> - <#break> - <#case "success"> - <#assign colorClass="bg-green-100 text-green-600"> - <#break> - <#case "warning"> - <#assign colorClass="bg-orange-100 text-orange-600"> - <#break> - <#default> - <#assign colorClass="bg-blue-100 text-blue-600"> - - - - diff --git a/conf/keycloak_theme/keywind/login/components/atoms/body.ftl b/conf/keycloak_theme/keywind/login/components/atoms/body.ftl deleted file mode 100644 index dcc94a06e..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/body.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> - - <#nested> - - diff --git a/conf/keycloak_theme/keywind/login/components/atoms/button-group.ftl b/conf/keycloak_theme/keywind/login/components/atoms/button-group.ftl deleted file mode 100644 index 459120917..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/button-group.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> -
- <#nested> -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/button.ftl b/conf/keycloak_theme/keywind/login/components/atoms/button.ftl deleted file mode 100644 index eeb0af7b7..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/button.ftl +++ /dev/null @@ -1,33 +0,0 @@ -<#macro kw color="" component="button" size="" rest...> - <#switch color> - <#case "primary"> - <#assign colorClass="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700"> - <#break> - <#case "secondary"> - <#assign colorClass="bg-secondary-100 text-secondary-600 focus:ring-secondary-600 hover:bg-secondary-200 hover:text-secondary-900"> - <#break> - <#default> - <#assign colorClass="bg-primary-600 text-white focus:ring-primary-600 hover:bg-primary-700"> - - - <#switch size> - <#case "medium"> - <#assign sizeClass="px-4 py-2 text-sm"> - <#break> - <#case "small"> - <#assign sizeClass="px-2 py-1 text-xs"> - <#break> - <#default> - <#assign sizeClass="px-4 py-2 text-sm"> - - - <${component} - class="${colorClass} ${sizeClass} flex justify-center relative rounded-lg w-full focus:outline-none focus:ring-2 focus:ring-offset-2" - - <#list rest as attrName, attrValue> - ${attrName}="${attrValue}" - - > - <#nested> - - diff --git a/conf/keycloak_theme/keywind/login/components/atoms/card.ftl b/conf/keycloak_theme/keywind/login/components/atoms/card.ftl deleted file mode 100644 index c1e808df1..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/card.ftl +++ /dev/null @@ -1,19 +0,0 @@ -<#macro kw content="" footer="" header=""> -
- <#if header?has_content> -
- ${header} -
- - <#if content?has_content> -
- ${content} -
- - <#if footer?has_content> -
- ${footer} -
- -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/checkbox.ftl b/conf/keycloak_theme/keywind/login/components/atoms/checkbox.ftl deleted file mode 100644 index e47fd619a..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/checkbox.ftl +++ /dev/null @@ -1,19 +0,0 @@ -<#macro kw checked=false label="" name="" rest...> -
- checked - - class="border-secondary-200 h-4 rounded text-primary-600 w-4 focus:ring-primary-200 focus:ring-opacity-50" - id="${name}" - name="${name}" - type="checkbox" - - <#list rest as attrName, attrValue> - ${attrName}="${attrValue}" - - > - -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/container.ftl b/conf/keycloak_theme/keywind/login/components/atoms/container.ftl deleted file mode 100644 index 34ead183c..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/container.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> -
- <#nested> -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/form.ftl b/conf/keycloak_theme/keywind/login/components/atoms/form.ftl deleted file mode 100644 index 014bb4f1c..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/form.ftl +++ /dev/null @@ -1,11 +0,0 @@ -<#macro kw rest...> -
- ${attrName}="${attrValue}" - - > - <#nested> -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/heading.ftl b/conf/keycloak_theme/keywind/login/components/atoms/heading.ftl deleted file mode 100644 index 7665c0196..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/heading.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> -

- <#nested> -

- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/input.ftl b/conf/keycloak_theme/keywind/login/components/atoms/input.ftl deleted file mode 100644 index 01e2897ad..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/input.ftl +++ /dev/null @@ -1,37 +0,0 @@ -<#macro - kw - autofocus=false - disabled=false - invalid=false - label="" - message="" - name="" - required=true - rest... -> -
- - autofocus - <#if disabled>disabled - <#if required>required - - aria-invalid="${invalid?c}" - class="block border-secondary-200 mt-1 rounded-md w-full focus:border-primary-300 focus:ring focus:ring-primary-200 focus:ring-opacity-50 sm:text-sm" - id="${name}" - name="${name}" - placeholder="${label}" - - <#list rest as attrName, attrValue> - ${attrName}="${attrValue}" - - > - <#if invalid?? && message??> -
- ${message?no_esc} -
- -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/link.ftl b/conf/keycloak_theme/keywind/login/components/atoms/link.ftl deleted file mode 100644 index bde766653..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/link.ftl +++ /dev/null @@ -1,30 +0,0 @@ -<#macro kw color="" component="a" size="" rest...> - <#switch color> - <#case "primary"> - <#assign colorClass="text-primary-600 hover:text-primary-500"> - <#break> - <#case "secondary"> - <#assign colorClass="text-secondary-600 hover:text-secondary-900"> - <#break> - <#default> - <#assign colorClass="text-primary-600 hover:text-primary-500"> - - - <#switch size> - <#case "small"> - <#assign sizeClass="text-sm"> - <#break> - <#default> - <#assign sizeClass=""> - - - <${component} - class="<#compress>${colorClass} ${sizeClass} inline-flex" - - <#list rest as attrName, attrValue> - ${attrName}="${attrValue}" - - > - <#nested> - - diff --git a/conf/keycloak_theme/keywind/login/components/atoms/logo.ftl b/conf/keycloak_theme/keywind/login/components/atoms/logo.ftl deleted file mode 100644 index f166403e6..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/logo.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> -
- <#nested> -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/nav.ftl b/conf/keycloak_theme/keywind/login/components/atoms/nav.ftl deleted file mode 100644 index 81a4abf63..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/nav.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> -
- <#nested> -
- diff --git a/conf/keycloak_theme/keywind/login/components/atoms/radio.ftl b/conf/keycloak_theme/keywind/login/components/atoms/radio.ftl deleted file mode 100644 index 5596d5c4b..000000000 --- a/conf/keycloak_theme/keywind/login/components/atoms/radio.ftl +++ /dev/null @@ -1,18 +0,0 @@ -<#macro kw checked=false id="" label="" rest...> -
- checked - - class="border-secondary-200 focus:ring-primary-600" - id="${id}" - type="radio" - - <#list rest as attrName, attrValue> - ${attrName}="${attrValue}" - - > - -
- diff --git a/conf/keycloak_theme/keywind/login/components/molecules/identity-provider.ftl b/conf/keycloak_theme/keywind/login/components/molecules/identity-provider.ftl deleted file mode 100644 index 50c9c81c7..000000000 --- a/conf/keycloak_theme/keywind/login/components/molecules/identity-provider.ftl +++ /dev/null @@ -1,78 +0,0 @@ -<#import "/assets/providers/providers.ftl" as providerIcons> - -<#macro kw providers=[]> -
- ${msg("identity-provider-login-label")} -
-
- <#list providers as provider> - <#switch provider.alias> - <#case "bitbucket"> - <#assign colorClass="hover:bg-provider-bitbucket/10"> - <#break> - <#case "discord"> - <#assign colorClass="hover:bg-provider-discord/10"> - <#break> - <#case "facebook"> - <#assign colorClass="hover:bg-provider-facebook/10"> - <#break> - <#case "github"> - <#assign colorClass="hover:bg-provider-github/10"> - <#break> - <#case "gitlab"> - <#assign colorClass="hover:bg-provider-gitlab/10"> - <#break> - <#case "google"> - <#assign colorClass="hover:bg-provider-google/10"> - <#break> - <#case "instagram"> - <#assign colorClass="hover:bg-provider-instagram/10"> - <#break> - <#case "linkedin"> - <#assign colorClass="hover:bg-provider-linkedin/10"> - <#break> - <#case "microsoft"> - <#assign colorClass="hover:bg-provider-microsoft/10"> - <#break> - <#case "oidc"> - <#assign colorClass="hover:bg-provider-oidc/10"> - <#break> - <#case "openshift-v3"> - <#assign colorClass="hover:bg-provider-openshift/10"> - <#break> - <#case "openshift-v4"> - <#assign colorClass="hover:bg-provider-openshift/10"> - <#break> - <#case "paypal"> - <#assign colorClass="hover:bg-provider-paypal/10"> - <#break> - <#case "slack"> - <#assign colorClass="hover:bg-provider-slack/10"> - <#break> - <#case "stackoverflow"> - <#assign colorClass="hover:bg-provider-stackoverflow/10"> - <#break> - <#case "twitter"> - <#assign colorClass="hover:bg-provider-twitter/10"> - <#break> - <#default> - <#assign colorClass="hover:bg-secondary-100"> - - - - <#if providerIcons[provider.alias]??> -
- <@providerIcons[provider.alias] /> -
- <#else> - ${provider.displayName!} - -
- -
- diff --git a/conf/keycloak_theme/keywind/login/components/molecules/locale-provider.ftl b/conf/keycloak_theme/keywind/login/components/molecules/locale-provider.ftl deleted file mode 100644 index 198e5be10..000000000 --- a/conf/keycloak_theme/keywind/login/components/molecules/locale-provider.ftl +++ /dev/null @@ -1,29 +0,0 @@ -<#import "/assets/icons/chevron-down.ftl" as icon> -<#import "/components/atoms/link.ftl" as link> - -<#macro kw currentLocale="" locales=[]> -
- <@link.kw @click="open = true" color="secondary" component="button" type="button"> -
- ${currentLocale} - <@icon.kw /> -
- -
- <#list locales as locale> - <#if currentLocale != locale.label> -
- <@link.kw color="secondary" href=locale.url size="small"> - ${locale.label} - -
- - -
-
- diff --git a/conf/keycloak_theme/keywind/login/components/molecules/username.ftl b/conf/keycloak_theme/keywind/login/components/molecules/username.ftl deleted file mode 100644 index ba6339389..000000000 --- a/conf/keycloak_theme/keywind/login/components/molecules/username.ftl +++ /dev/null @@ -1,15 +0,0 @@ -<#import "/assets/icons/arrow-top-right-on-square.ftl" as icon> -<#import "/components/atoms/link.ftl" as link> - -<#macro kw linkHref="" linkTitle="" name=""> -
- ${name} - <@link.kw - color="primary" - href=linkHref - title=linkTitle - > - <@icon.kw /> - -
- diff --git a/conf/keycloak_theme/keywind/login/document.ftl b/conf/keycloak_theme/keywind/login/document.ftl deleted file mode 100644 index 188e16a31..000000000 --- a/conf/keycloak_theme/keywind/login/document.ftl +++ /dev/null @@ -1,35 +0,0 @@ -<#macro kw script=""> - ${msg("loginTitle", (realm.displayName!""))} - - - - - - <#if properties.meta?has_content> - <#list properties.meta?split(" ") as meta> - - - - - <#if properties.favicons?has_content> - <#list properties.favicons?split(" ") as favicon> - - - - - <#if properties.styles?has_content> - <#list properties.styles?split(" ") as style> - - - - - <#if script?has_content> - - - - <#if properties.scripts?has_content> - <#list properties.scripts?split(" ") as script> - - - - diff --git a/conf/keycloak_theme/keywind/login/error.ftl b/conf/keycloak_theme/keywind/login/error.ftl deleted file mode 100644 index 52af9c1e6..000000000 --- a/conf/keycloak_theme/keywind/login/error.ftl +++ /dev/null @@ -1,18 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/alert.ftl" as alert> -<#import "components/atoms/link.ftl" as link> - -<@layout.registrationLayout displayMessage=false; section> - <#if section="header"> - ${kcSanitize(msg("errorTitle"))?no_esc} - <#elseif section="form"> - <@alert.kw color="error">${kcSanitize(message.summary)?no_esc} - <#if !skipLink??> - <#if client?? && client.baseUrl?has_content> - <@link.kw color="secondary" href=client.baseUrl size="small"> - ${kcSanitize(msg("backToApplication"))?no_esc} - - - - - diff --git a/conf/keycloak_theme/keywind/login/features/labels/totp-device.ftl b/conf/keycloak_theme/keywind/login/features/labels/totp-device.ftl deleted file mode 100644 index 98ae12f8d..000000000 --- a/conf/keycloak_theme/keywind/login/features/labels/totp-device.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> - <#compress> - ${msg("loginTotpDeviceName")} <#if totp.otpCredentials?size gte 1>* - - diff --git a/conf/keycloak_theme/keywind/login/features/labels/totp.ftl b/conf/keycloak_theme/keywind/login/features/labels/totp.ftl deleted file mode 100644 index be5158ebe..000000000 --- a/conf/keycloak_theme/keywind/login/features/labels/totp.ftl +++ /dev/null @@ -1,5 +0,0 @@ -<#macro kw> - <#compress> - ${msg("authenticatorCode")} * - - diff --git a/conf/keycloak_theme/keywind/login/features/labels/username.ftl b/conf/keycloak_theme/keywind/login/features/labels/username.ftl deleted file mode 100644 index 6c01d6b34..000000000 --- a/conf/keycloak_theme/keywind/login/features/labels/username.ftl +++ /dev/null @@ -1,11 +0,0 @@ -<#macro kw> - <#compress> - <#if !realm.loginWithEmailAllowed> - ${msg("username")} - <#elseif !realm.registrationEmailAsUsername> - ${msg("usernameOrEmail")} - <#else> - ${msg("email")} - - - diff --git a/conf/keycloak_theme/keywind/login/login-config-totp.ftl b/conf/keycloak_theme/keywind/login/login-config-totp.ftl deleted file mode 100644 index e0b64c634..000000000 --- a/conf/keycloak_theme/keywind/login/login-config-totp.ftl +++ /dev/null @@ -1,110 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> -<#import "features/labels/totp.ftl" as totpLabel> -<#import "features/labels/totp-device.ftl" as totpDeviceLabel> - -<#assign totpLabel><@totpLabel.kw /> -<#assign totpDeviceLabel><@totpDeviceLabel.kw /> - -<@layout.registrationLayout - displayMessage=!messagesPerField.existsError("totp", "userLabel") - displayRequiredFields=false - ; - section -> - <#if section="header"> - ${msg("loginTotpTitle")} - <#elseif section="form"> -
    -
  1. -

    ${msg("loginTotpStep1")}

    -
      - <#list totp.supportedApplications as app> -
    • ${msg(app)}
    • - -
    -
  2. - <#if mode?? && mode="manual"> -
  3. -

    ${msg("loginTotpManualStep2")}

    -

    ${totp.totpSecretEncoded}

    -
  4. -
  5. - <@link.kw color="primary" href=totp.qrUrl> - ${msg("loginTotpScanBarcode")} - -
  6. -
  7. -

    ${msg("loginTotpManualStep3")}

    -
      -
    • ${msg("loginTotpType")}: ${msg("loginTotp." + totp.policy.type)}
    • -
    • ${msg("loginTotpAlgorithm")}: ${totp.policy.getAlgorithmKey()}
    • -
    • ${msg("loginTotpDigits")}: ${totp.policy.digits}
    • - <#if totp.policy.type="totp"> -
    • ${msg("loginTotpInterval")}: ${totp.policy.period}
    • - <#elseif totp.policy.type="hotp"> -
    • ${msg("loginTotpCounter")}: ${totp.policy.initialCounter}
    • - -
    -
  8. - <#else> -
  9. -

    ${msg("loginTotpStep2")}

    - Figure: Barcode - <@link.kw color="primary" href=totp.manualUrl> - ${msg("loginTotpUnableToScan")} - -
  10. - -
  11. ${msg("loginTotpStep3")}
  12. -
  13. ${msg("loginTotpStep3DeviceName")}
  14. -
- <@form.kw action=url.loginAction method="post"> - - <#if mode??> - - - <@input.kw - autocomplete="off" - autofocus=true - invalid=messagesPerField.existsError("totp") - label=totpLabel - message=kcSanitize(messagesPerField.get("totp")) - name="totp" - required=false - type="text" - /> - <@input.kw - autocomplete="off" - invalid=messagesPerField.existsError("userLabel") - label=totpDeviceLabel - message=kcSanitize(messagesPerField.get("userLabel")) - name="userLabel" - required=false - type="text" - /> - <@buttonGroup.kw> - <#if isAppInitiatedAction??> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - <@button.kw color="secondary" name="cancel-aia" type="submit" value="true"> - ${msg("doCancel")} - - <#else> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-idp-link-confirm.ftl b/conf/keycloak_theme/keywind/login/login-idp-link-confirm.ftl deleted file mode 100644 index 9a2554d51..000000000 --- a/conf/keycloak_theme/keywind/login/login-idp-link-confirm.ftl +++ /dev/null @@ -1,18 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/form.ftl" as form> - -<@layout.registrationLayout; section> - <#if section="header"> - ${msg("confirmLinkIdpTitle")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - <@button.kw color="primary" name="submitAction" type="submit" value="updateProfile"> - ${msg("confirmLinkIdpReviewProfile")} - - <@button.kw color="primary" name="submitAction" type="submit" value="linkAccount"> - ${msg("confirmLinkIdpContinue", idpDisplayName)} - - - - diff --git a/conf/keycloak_theme/keywind/login/login-oauth-grant.ftl b/conf/keycloak_theme/keywind/login/login-oauth-grant.ftl deleted file mode 100644 index aa4173cbf..000000000 --- a/conf/keycloak_theme/keywind/login/login-oauth-grant.ftl +++ /dev/null @@ -1,62 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> - -<@layout.registrationLayout; section> - <#if section="header"> - <#if client.attributes.logoUri??> - - -

- <#if client.name?has_content> - ${msg("oauthGrantTitle", advancedMsg(client.name))} - <#else> - ${msg("oauthGrantTitle", client.clientId)} - -

- <#elseif section="form"> -

${msg("oauthGrantRequest")}

-
    - <#if oauth.clientScopesRequested??> - <#list oauth.clientScopesRequested as clientScope> -
  • - <#if !clientScope.dynamicScopeParameter??> - ${advancedMsg(clientScope.consentScreenText)} - <#else> - ${advancedMsg(clientScope.consentScreenText)}: ${clientScope.dynamicScopeParameter} - -
  • - - -
- <#if client.attributes.policyUri?? || client.attributes.tosUri??> -

- <#if client.name?has_content> - ${msg("oauthGrantInformation",advancedMsg(client.name))} - <#else> - ${msg("oauthGrantInformation",client.clientId)} - - <#if client.attributes.tosUri??> - ${msg("oauthGrantReview")} - ${msg("oauthGrantTos")} - - <#if client.attributes.policyUri??> - ${msg("oauthGrantReview")} - ${msg("oauthGrantPolicy")} - -

- - <@form.kw action=url.oauthAction method="post"> - - <@buttonGroup.kw> - <@button.kw color="primary" name="accept" type="submit"> - ${msg("doYes")} - - <@button.kw color="secondary" name="cancel" type="submit"> - ${msg("doNo")} - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-otp.ftl b/conf/keycloak_theme/keywind/login/login-otp.ftl deleted file mode 100644 index b1bb3b975..000000000 --- a/conf/keycloak_theme/keywind/login/login-otp.ftl +++ /dev/null @@ -1,50 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/radio.ftl" as radio> -<#import "features/labels/totp.ftl" as totpLabel> - -<#assign totpLabel><@totpLabel.kw /> - -<@layout.registrationLayout - displayMessage=!messagesPerField.existsError("totp") - ; - section -> - <#if section="header"> - ${msg("doLogIn")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - <#if otpLogin.userOtpCredentials?size gt 1> -
- <#list otpLogin.userOtpCredentials as otpCredential> - <@radio.kw - checked=(otpCredential.id == otpLogin.selectedCredentialId) - id="kw-otp-credential-${otpCredential?index}" - label=otpCredential.userLabel - name="selectedCredentialId" - tabindex=otpCredential?index - value=otpCredential.id - /> - -
- - <@input.kw - autocomplete="off" - autofocus=true - invalid=messagesPerField.existsError("totp") - label=totpLabel - message=kcSanitize(messagesPerField.get("totp")) - name="otp" - type="text" - /> - <@buttonGroup.kw> - <@button.kw color="primary" name="submitAction" type="submit"> - ${msg("doLogIn")} - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-page-expired.ftl b/conf/keycloak_theme/keywind/login/login-page-expired.ftl deleted file mode 100644 index 2b6288d94..000000000 --- a/conf/keycloak_theme/keywind/login/login-page-expired.ftl +++ /dev/null @@ -1,18 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> - -<@layout.registrationLayout; section> - <#if section="header"> - ${msg("pageExpiredTitle")} - <#elseif section="form"> - <@buttonGroup.kw> - <@button.kw color="primary" component="a" href=url.loginRestartFlowUrl> - ${msg("doTryAgain")} - - <@button.kw color="secondary" component="a" href=url.loginAction> - ${msg("doContinue")} - - - - diff --git a/conf/keycloak_theme/keywind/login/login-password.ftl b/conf/keycloak_theme/keywind/login/login-password.ftl deleted file mode 100644 index 54e7d9dca..000000000 --- a/conf/keycloak_theme/keywind/login/login-password.ftl +++ /dev/null @@ -1,39 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> - -<@layout.registrationLayout displayMessage=!messagesPerField.existsError("password"); section> - <#if section="header"> - ${msg("doLogIn")} - <#elseif section="form"> - <@form.kw - action=url.loginAction - method="post" - onsubmit="login.disabled = true; return true;" - > - <@input.kw - autofocus=true - invalid=messagesPerField.existsError("password") - label=msg("password") - message=kcSanitize(messagesPerField.get("password"))?no_esc - name="password" - type="password" - /> - <#if realm.resetPasswordAllowed> -
- <@link.kw color="primary" href=url.loginResetCredentialsUrl size="small"> - ${msg("doForgotPassword")} - -
- - <@buttonGroup.kw> - <@button.kw color="primary" name="login" type="submit"> - ${msg("doLogIn")} - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-recovery-authn-code-config.ftl b/conf/keycloak_theme/keywind/login/login-recovery-authn-code-config.ftl deleted file mode 100644 index 186d71080..000000000 --- a/conf/keycloak_theme/keywind/login/login-recovery-authn-code-config.ftl +++ /dev/null @@ -1,91 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/alert.ftl" as alert> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/checkbox.ftl" as checkbox> -<#import "components/atoms/form.ftl" as form> - -<@layout.registrationLayout script="dist/recoveryCodes.js"; section> - <#if section="header"> - ${msg("recovery-code-config-header")} - <#elseif section="form"> -
- <@alert.kw color="warning"> -
-

${msg("recovery-code-config-warning-title")}

-

${msg("recovery-code-config-warning-message")}

-
- -
    - <#list recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList as code> -
  • ${code[0..3]}-${code[4..7]}-${code[8..]}
  • - -
-
- <@button.kw @click="print" color="secondary" size="small" type="button"> - ${msg("recovery-codes-print")} - - <@button.kw @click="download" color="secondary" size="small" type="button"> - ${msg("recovery-codes-download")} - - <@button.kw @click="copy" color="secondary" size="small" type="button"> - ${msg("recovery-codes-copy")} - -
- <@form.kw action=url.loginAction method="post"> - - - - <@checkbox.kw - label=msg("recovery-codes-confirmation-message") - name="kcRecoveryCodesConfirmationCheck" - required="required" - x\-ref="confirmationCheck" - /> - <@buttonGroup.kw> - <#if isAppInitiatedAction??> - <@button.kw color="primary" type="submit"> - ${msg("recovery-codes-action-complete")} - - <@button.kw - @click="$refs.confirmationCheck.required = false" - color="secondary" - name="cancel-aia" - type="submit" - value="true" - > - ${msg("recovery-codes-action-cancel")} - - <#else> - <@button.kw color="primary" type="submit"> - ${msg("recovery-codes-action-complete")} - - - - -
- - - - diff --git a/conf/keycloak_theme/keywind/login/login-recovery-authn-code-input.ftl b/conf/keycloak_theme/keywind/login/login-recovery-authn-code-input.ftl deleted file mode 100644 index a46bcfa09..000000000 --- a/conf/keycloak_theme/keywind/login/login-recovery-authn-code-input.ftl +++ /dev/null @@ -1,26 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> - -<@layout.registrationLayout; section> - <#if section="header"> - ${msg("auth-recovery-code-header")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - <@input.kw - autocomplete="off" - autofocus=true - label=msg("auth-recovery-code-prompt", recoveryAuthnCodesInputBean.codeNumber?c) - name="recoveryCodeInput" - type="text" - /> - <@buttonGroup.kw> - <@button.kw color="primary" name="login" type="submit"> - ${msg("doLogIn")} - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-reset-password.ftl b/conf/keycloak_theme/keywind/login/login-reset-password.ftl deleted file mode 100644 index b0516aae8..000000000 --- a/conf/keycloak_theme/keywind/login/login-reset-password.ftl +++ /dev/null @@ -1,44 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> -<#import "features/labels/username.ftl" as usernameLabel> - -<#assign usernameLabel><@usernameLabel.kw /> - -<@layout.registrationLayout - displayInfo=true - displayMessage=!messagesPerField.existsError("username") - ; - section -> - <#if section="header"> - ${msg("emailForgotTitle")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - <@input.kw - autocomplete=realm.loginWithEmailAllowed?string("email", "username") - autofocus=true - invalid=messagesPerField.existsError("username") - label=usernameLabel - message=kcSanitize(messagesPerField.get("username")) - name="username" - type="text" - value=(auth?has_content && auth.showUsername())?then(auth.attemptedUsername, '') - /> - <@buttonGroup.kw> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - - - <#elseif section="info"> - ${msg("emailInstruction")} - <#elseif section="nav"> - <@link.kw color="secondary" href=url.loginUrl size="small"> - ${kcSanitize(msg("backToLogin"))?no_esc} - - - diff --git a/conf/keycloak_theme/keywind/login/login-update-password.ftl b/conf/keycloak_theme/keywind/login/login-update-password.ftl deleted file mode 100644 index ed82380e2..000000000 --- a/conf/keycloak_theme/keywind/login/login-update-password.ftl +++ /dev/null @@ -1,64 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/checkbox.ftl" as checkbox> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> - -<@layout.registrationLayout - displayMessage=!messagesPerField.existsError("password", "password-confirm") - ; - section -> - <#if section="header"> - ${msg("updatePasswordTitle")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - - - <@input.kw - autocomplete="new-password" - autofocus=true - invalid=messagesPerField.existsError("password", "password-confirm") - label=msg("passwordNew") - name="password-new" - type="password" - /> - <@input.kw - autocomplete="new-password" - invalid=messagesPerField.existsError("password-confirm") - label=msg("passwordConfirm") - message=kcSanitize(messagesPerField.get("password-confirm")) - name="password-confirm" - type="password" - /> - <#if isAppInitiatedAction??> - <@checkbox.kw - checked=true - label=msg("logoutOtherSessions") - name="logout-sessions" - value="on" - /> - - <@buttonGroup.kw> - <#if isAppInitiatedAction??> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - <@button.kw color="secondary" name="cancel-aia" type="submit" value="true"> - ${msg("doCancel")} - - <#else> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-update-profile.ftl b/conf/keycloak_theme/keywind/login/login-update-profile.ftl deleted file mode 100644 index 306bad944..000000000 --- a/conf/keycloak_theme/keywind/login/login-update-profile.ftl +++ /dev/null @@ -1,71 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> - -<@layout.registrationLayout - displayMessage=!messagesPerField.existsError("email", "firstName", "lastName", "username") - ; - section -> - <#if section="header"> - ${msg("loginProfileTitle")} - <#elseif section="form"> - <@form.kw action=url.loginAction method="post"> - <#if user.editUsernameAllowed> - <@input.kw - autocomplete="username" - autofocus=true - invalid=messagesPerField.existsError("username") - label=msg("username") - message=kcSanitize(messagesPerField.get("username")) - name="username" - type="text" - value=(user.username)!'' - /> - - <@input.kw - autocomplete="email" - invalid=messagesPerField.existsError("email") - label=msg("email") - message=kcSanitize(messagesPerField.get("email")) - name="email" - type="email" - value=(user.email)!'' - /> - <@input.kw - autocomplete="given-name" - invalid=messagesPerField.existsError("firstName") - label=msg("firstName") - message=kcSanitize(messagesPerField.get("firstName")) - name="firstName" - type="text" - value=(user.firstName)!'' - /> - <@input.kw - autocomplete="family-name" - invalid=messagesPerField.existsError("lastName") - label=msg("lastName") - message=kcSanitize(messagesPerField.get("lastName")) - name="lastName" - type="text" - value=(user.lastName)!'' - /> - <@buttonGroup.kw> - <#if isAppInitiatedAction??> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - <@button.kw color="secondary" name="cancel-aia" type="submit" value="true"> - ${msg("doCancel")} - - <#else> - <@button.kw color="primary" type="submit"> - ${msg("doSubmit")} - - - - - - diff --git a/conf/keycloak_theme/keywind/login/login-username.ftl b/conf/keycloak_theme/keywind/login/login-username.ftl deleted file mode 100644 index b8064b2da..000000000 --- a/conf/keycloak_theme/keywind/login/login-username.ftl +++ /dev/null @@ -1,71 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/checkbox.ftl" as checkbox> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> -<#import "components/molecules/identity-provider.ftl" as identityProvider> -<#import "features/labels/username.ftl" as usernameLabel> - -<#assign usernameLabel><@usernameLabel.kw /> - -<@layout.registrationLayout - displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled?? - displayMessage=!messagesPerField.existsError("username") - ; - section -> - <#if section="header"> - ${msg("loginAccountTitle")} - <#elseif section="form"> - <#if realm.password> - <@form.kw - action=url.loginAction - method="post" - onsubmit="login.disabled = true; return true;" - > - <#if !usernameHidden??> - <@input.kw - autocomplete=realm.loginWithEmailAllowed?string("email", "username") - autofocus=true - disabled=usernameEditDisabled?? - invalid=messagesPerField.existsError("username") - label=usernameLabel - message=kcSanitize(messagesPerField.get("username"))?no_esc - name="username" - type="text" - value=(login.username)!'' - /> - - <#if realm.rememberMe && !usernameHidden??> -
- <@checkbox.kw - checked=login.rememberMe?? - label=msg("rememberMe") - name="rememberMe" - /> -
- - <@buttonGroup.kw> - <@button.kw color="primary" name="login" type="submit"> - ${msg("doLogIn")} - - - - - <#elseif section="info"> - <#if realm.password && realm.registrationAllowed && !registrationDisabled??> -
- ${msg("noAccount")} - <@link.kw color="primary" href=url.registrationUrl> - ${msg("doRegister")} - -
- - <#elseif section="socialProviders"> - <#if realm.password && social.providers??> - <@identityProvider.kw providers=social.providers /> - - - diff --git a/conf/keycloak_theme/keywind/login/login.ftl b/conf/keycloak_theme/keywind/login/login.ftl deleted file mode 100644 index 308413817..000000000 --- a/conf/keycloak_theme/keywind/login/login.ftl +++ /dev/null @@ -1,88 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/checkbox.ftl" as checkbox> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> -<#import "components/molecules/identity-provider.ftl" as identityProvider> -<#import "features/labels/username.ftl" as usernameLabel> - -<#assign usernameLabel><@usernameLabel.kw /> - -<@layout.registrationLayout - displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled?? - displayMessage=!messagesPerField.existsError("username", "password") - ; - section -> - <#if section="header"> - ${msg("loginAccountTitle")} - <#elseif section="form"> - <#if realm.password> - <@form.kw - action=url.loginAction - method="post" - onsubmit="login.disabled = true; return true;" - > - - <@input.kw - autocomplete=realm.loginWithEmailAllowed?string("email", "username") - autofocus=true - disabled=usernameEditDisabled?? - invalid=messagesPerField.existsError("username", "password") - label=usernameLabel - message=kcSanitize(messagesPerField.getFirstError("username", "password")) - name="username" - type="text" - value=(login.username)!'username' - /> - <@input.kw - invalid=messagesPerField.existsError("username", "password") - label=msg("password") - name="password" - type="password" - value=(login.password)!'password' - /> - <#if realm.rememberMe && !usernameEditDisabled?? || realm.resetPasswordAllowed> -
- <#if realm.rememberMe && !usernameEditDisabled??> - <@checkbox.kw - checked=login.rememberMe?? - label=msg("rememberMe") - name="rememberMe" - /> - - <#if realm.resetPasswordAllowed> - <@link.kw color="primary" href=url.loginResetCredentialsUrl size="small"> - ${msg("doForgotPassword")} - - -
- - <@buttonGroup.kw> - <@button.kw color="primary" name="login" type="submit"> - ${msg("doLogIn")} - - - - - <#elseif section="info"> - <#if realm.password && realm.registrationAllowed && !registrationDisabled??> -
- ${msg("noAccount")} - <@link.kw color="primary" href=url.registrationUrl> - ${msg("doRegister")} - -
- - <#elseif section="socialProviders"> - <#if realm.password && social.providers??> - <@identityProvider.kw providers=social.providers /> - - - diff --git a/conf/keycloak_theme/keywind/login/logout-confirm.ftl b/conf/keycloak_theme/keywind/login/logout-confirm.ftl deleted file mode 100644 index e7ec48626..000000000 --- a/conf/keycloak_theme/keywind/login/logout-confirm.ftl +++ /dev/null @@ -1,25 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/link.ftl" as link> - -<@layout.registrationLayout; section> - <#if section="header"> - ${msg("logoutConfirmTitle")} - <#elseif section="form"> -

${msg("logoutConfirmHeader")}

- <@form.kw action=url.logoutConfirmAction method="post"> - - <@button.kw color="primary" name="confirmLogout" type="submit" value=msg('doLogout')> - ${msg("doLogout")} - - - <#if !logoutConfirm.skipLink> - <#if (client.baseUrl)?has_content> - <@link.kw color="secondary" href=client.baseUrl size="small"> - ${kcSanitize(msg("backToApplication"))?no_esc} - - - - - diff --git a/conf/keycloak_theme/keywind/login/register.ftl b/conf/keycloak_theme/keywind/login/register.ftl deleted file mode 100644 index c1a2f061f..000000000 --- a/conf/keycloak_theme/keywind/login/register.ftl +++ /dev/null @@ -1,88 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> -<#import "components/atoms/form.ftl" as form> -<#import "components/atoms/input.ftl" as input> -<#import "components/atoms/link.ftl" as link> - -<@layout.registrationLayout - displayMessage=!messagesPerField.existsError("firstName", "lastName", "email", "username", "password", "password-confirm") - ; - section -> - <#if section="header"> - ${msg("registerTitle")} - <#elseif section="form"> - <@form.kw action=url.registrationAction method="post"> - <@input.kw - autocomplete="given-name" - autofocus=true - invalid=messagesPerField.existsError("firstName") - label=msg("firstName") - message=kcSanitize(messagesPerField.get("firstName")) - name="firstName" - type="text" - value=(register.formData.firstName)!'' - /> - <@input.kw - autocomplete="family-name" - invalid=messagesPerField.existsError("lastName") - label=msg("lastName") - message=kcSanitize(messagesPerField.get("lastName")) - name="lastName" - type="text" - value=(register.formData.lastName)!'' - /> - <@input.kw - autocomplete="email" - invalid=messagesPerField.existsError("email") - label=msg("email") - message=kcSanitize(messagesPerField.get("email")) - name="email" - type="email" - value=(register.formData.email)!'' - /> - <#if !realm.registrationEmailAsUsername> - <@input.kw - autocomplete="username" - invalid=messagesPerField.existsError("username") - label=msg("username") - message=kcSanitize(messagesPerField.get("username")) - name="username" - type="text" - value=(register.formData.username)!'' - /> - - <#if passwordRequired??> - <@input.kw - autocomplete="new-password" - invalid=messagesPerField.existsError("password", "password-confirm") - label=msg("password") - message=kcSanitize(messagesPerField.getFirstError("password", "password-confirm")) - name="password" - type="password" - /> - <@input.kw - autocomplete="new-password" - invalid=messagesPerField.existsError("password-confirm") - label=msg("passwordConfirm") - message=kcSanitize(messagesPerField.get("password-confirm")) - name="password-confirm" - type="password" - /> - - <#if recaptchaRequired??> -
- - <@buttonGroup.kw> - <@button.kw color="primary" type="submit"> - ${msg("doRegister")} - - - - <#elseif section="nav"> - <@link.kw color="secondary" href=url.loginUrl size="small"> - ${kcSanitize(msg("backToLogin"))?no_esc} - - - diff --git a/conf/keycloak_theme/keywind/login/resources/dist/assets/index-a7b84447.js b/conf/keycloak_theme/keywind/login/resources/dist/assets/index-a7b84447.js deleted file mode 100644 index c1b2f3c66..000000000 --- a/conf/keycloak_theme/keywind/login/resources/dist/assets/index-a7b84447.js +++ /dev/null @@ -1 +0,0 @@ -var s={};Object.defineProperty(s,"__esModule",{value:!0});function v(e,r,a){var l;if(a===void 0&&(a={}),!r.codes){r.codes={};for(var n=0;n=8&&(t-=8,c[u++]=255&i>>t)}if(t>=r.bits||255&i<<8-t)throw new SyntaxError("Unexpected end of data");return c}function o(e,r,a){a===void 0&&(a={});for(var l=a,n=l.pad,b=n===void 0?!0:n,c=(1<r.bits;)i-=r.bits,t+=r.chars[c&u>>i];if(i&&(t+=r.chars[c&u<Te&&R.splice(t,1)}function $r(){!Me&&!Ce&&(Ce=!0,queueMicrotask(Rr))}function Rr(){Ce=!1,Me=!0;for(let e=0;ee.effect(t,{scheduler:r=>{Ie?Ir(r):r()}}),yt=e.raw}function ct(e){z=e}function Lr(e){let t=()=>{};return[n=>{let i=z(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),Z(i))},i},()=>{t()}]}var xt=[],bt=[],mt=[];function Fr(e){mt.push(e)}function wt(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,bt.push(t))}function Kr(e){xt.push(e)}function Dr(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function Et(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var qe=new MutationObserver(Je),We=!1;function Ve(){qe.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),We=!0}function St(){Br(),qe.disconnect(),We=!1}var U=[],Ee=!1;function Br(){U=U.concat(qe.takeRecords()),U.length&&!Ee&&(Ee=!0,queueMicrotask(()=>{kr(),Ee=!1}))}function kr(){Je(U),U.length=0}function x(e){if(!We)return e();St();let t=e();return Ve(),t}var Ue=!1,ae=[];function zr(){Ue=!0}function Hr(){Ue=!1,Je(ae),ae=[]}function Je(e){if(Ue){ae=ae.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;os.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,u=e[o].oldValue,c=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},l=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&u===null?c():s.hasAttribute(a)?(l(),c()):l()}i.forEach((o,s)=>{Et(s,o)}),n.forEach((o,s)=>{xt.forEach(a=>a(s,o))});for(let o of r)if(!t.includes(o)&&(bt.forEach(s=>s(o)),o._x_cleanups))for(;o._x_cleanups.length;)o._x_cleanups.pop()();t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||o.isConnected&&(delete o._x_ignoreSelf,delete o._x_ignore,mt.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function At(e){return ee(K(e))}function X(e,t,r){return e._x_dataStack=[t,...K(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function lt(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function K(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?K(e.host):e.parentNode?K(e.parentNode):[]}function ee(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,u=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...u,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function Ot(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let u=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,u,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,u)})};return r(e)}function Ct(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>qr(n,i),s=>Pe(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let u=n.initialize(o,s,a);return r.initialValue=u,i(o,s,a)}}else r.initialValue=n;return r}}function qr(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function Pe(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),Pe(e[t[0]],t.slice(1),r)}}var Mt={};function S(e,t){Mt[e]=t}function $e(e,t){return Object.entries(Mt).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){let[i,o]=Rt(t);return i={interceptor:Ct,...i},wt(t,o),n(t,i)},enumerable:!1})}),e}function Wr(e,t,r,...n){try{return r(...n)}catch(i){Y(i,e,t)}}function Y(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message} - -${r?'Expression: "'+r+`" - -`:""}`,t),setTimeout(()=>{throw e},0)}var se=!0;function Vr(e){let t=se;se=!1,e(),se=t}function F(e,t,r={}){let n;return m(e,t)(i=>n=i,r),n}function m(...e){return Tt(...e)}var Tt=It;function Ur(e){Tt=e}function It(e,t){let r={};$e(r,e);let n=[r,...K(e)],i=typeof t=="function"?Jr(n,t):Yr(n,t,e);return Wr.bind(null,e,t,i)}function Jr(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(ee([n,...e]),i);ue(r,o)}}var Se={};function Gr(e,t){if(Se[e])return Se[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(async()=>{ ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return Y(s,t,e),Promise.resolve()}})();return Se[e]=o,o}function Yr(e,t,r){let n=Gr(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=ee([o,...e]);if(typeof n=="function"){let u=n(n,a).catch(c=>Y(c,r,t));n.finished?(ue(i,n.result,a,s,r),n.result=void 0):u.then(c=>{ue(i,c,a,s,r)}).catch(c=>Y(c,r,t)).finally(()=>n.result=void 0)}}}function ue(e,t,r,n,i){if(se&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>ue(e,s,r,n)).catch(s=>Y(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var Ge="x-";function H(e=""){return Ge+e}function Qr(e){Ge=e}var Re={};function g(e,t){return Re[e]=t,{before(r){if(!Re[r]){console.warn("Cannot find directive `${directive}`. `${name}` will use the default order of execution");return}const n=$.indexOf(r);$.splice(n>=0?n:$.indexOf("DEFAULT"),0,e)}}}function Ye(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,u])=>({name:a,value:u})),s=Pt(o);o=o.map(a=>s.find(u=>u.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(Lt((o,s)=>n[o]=s)).filter(Kt).map(en(n,r)).sort(tn).map(o=>Xr(e,o))}function Pt(e){return Array.from(e).map(Lt()).filter(t=>!Kt(t))}var je=!1,V=new Map,$t=Symbol();function Zr(e){je=!0;let t=Symbol();$t=t,V.set(t,[]);let r=()=>{for(;V.get(t).length;)V.get(t).shift()();V.delete(t)},n=()=>{je=!1,r()};e(r),n()}function Rt(e){let t=[],r=a=>t.push(a),[n,i]=Lr(e);return t.push(i),[{Alpine:re,effect:n,cleanup:r,evaluateLater:m.bind(m,e),evaluate:F.bind(F,e)},()=>t.forEach(a=>a())]}function Xr(e,t){let r=()=>{},n=Re[t.type]||r,[i,o]=Rt(e);Dr(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),je?V.get($t).push(n):n())};return s.runCleanups=o,s}var jt=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Nt=e=>e;function Lt(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=Ft.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var Ft=[];function Qe(e){Ft.push(e)}function Kt({name:e}){return Dt().test(e)}var Dt=()=>new RegExp(`^${Ge}([^:^.]+)\\b`);function en(e,t){return({name:r,value:n})=>{let i=r.match(Dt()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(u=>u.replace(".","")),expression:n,original:a}}}var Ne="DEFAULT",$=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",Ne,"teleport"];function tn(e,t){let r=$.indexOf(e.type)===-1?Ne:e.type,n=$.indexOf(t.type)===-1?Ne:t.type;return $.indexOf(r)-$.indexOf(n)}function J(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function M(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>M(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)M(n,t),n=n.nextElementSibling}function D(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function rn(){document.body||D("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's ` diff --git a/conf/keycloak_theme/keywind/login/webauthn-error.ftl b/conf/keycloak_theme/keywind/login/webauthn-error.ftl deleted file mode 100644 index 852d1e3d5..000000000 --- a/conf/keycloak_theme/keywind/login/webauthn-error.ftl +++ /dev/null @@ -1,34 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> - -<@layout.registrationLayout displayMessage=true; section> - <#if section="header"> - ${kcSanitize(msg("webauthn-error-title"))?no_esc} - <#elseif section="form"> -
-
- - -
- <@buttonGroup.kw> - <@button.kw - @click="$refs.executionValueInput.value = '${execution}'; $refs.isSetRetryInput.value = 'retry'; $refs.errorCredentialForm.submit()" - color="primary" - name="try-again" - tabindex="4" - type="button" - > - ${kcSanitize(msg("doTryAgain"))?no_esc} - - <#if isAppInitiatedAction??> -
- <@button.kw color="secondary" name="cancel-aia" type="submit" value="true"> - ${msg("doCancel")} - -
- - -
- - diff --git a/conf/keycloak_theme/keywind/login/webauthn-register.ftl b/conf/keycloak_theme/keywind/login/webauthn-register.ftl deleted file mode 100644 index 57f4dad87..000000000 --- a/conf/keycloak_theme/keywind/login/webauthn-register.ftl +++ /dev/null @@ -1,54 +0,0 @@ -<#import "template.ftl" as layout> -<#import "components/atoms/button.ftl" as button> -<#import "components/atoms/button-group.ftl" as buttonGroup> - -<@layout.registrationLayout script="dist/webAuthnRegister.js"; section> - <#if section="title"> - title - <#elseif section="header"> - ${kcSanitize(msg("webauthn-registration-title"))?no_esc} - <#elseif section="form"> -
-
- - - - - - -
- <@buttonGroup.kw> - <@button.kw @click="registerSecurityKey" color="primary" type="submit"> - ${msg("doRegister")} - - <#if !isSetRetry?has_content && isAppInitiatedAction?has_content> -
- <@button.kw color="secondary" name="cancel-aia" type="submit" value="true"> - ${msg("doCancel")} - -
- - -
- - - - diff --git a/conf/sample.env_app-backend b/conf/sample.env_app-backend deleted file mode 100644 index e75a8c98c..000000000 --- a/conf/sample.env_app-backend +++ /dev/null @@ -1,23 +0,0 @@ -## postgres database to store Hasura metadata -HASURA_GRAPHQL_METADATA_DATABASE_URL=postgres://postgres:postgrespassword@postgres:5432/jan-hasura-metadata -## this env var can be used to add the above postgres database to Hasura as a data source. this can be removed/updated based on your needs -PG_DATABASE_URL=postgres://postgres:postgrespassword@postgres:5432/jan-hasura-data -## enable the console served by server -HASURA_GRAPHQL_ENABLE_CONSOLE="true" # set to "false" to disable console -## enable debugging mode. It is recommended to disable this in production -HASURA_GRAPHQL_DEV_MODE="true" -HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup, http-log, webhook-log, websocket-log, query-log -## uncomment next line to run console offline (i.e load console assets from server instead of CDN) -# HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets -## uncomment next line to set an admin secret -HASURA_GRAPHQL_ADMIN_SECRET=myadminsecretkey -HASURA_GRAPHQL_UNAUTHORIZED_ROLE="public" -HASURA_GRAPHQL_METADATA_DEFAULTS='{"backend_configs":{"dataconnector":{"athena":{"uri":"http://data-connector-agent:8081/api/v1/athena"},"mariadb":{"uri":"http://data-connector-agent:8081/api/v1/mariadb"},"mysql8":{"uri":"http://data-connector-agent:8081/api/v1/mysql"},"oracle":{"uri":"http://data-connector-agent:8081/api/v1/oracle"},"snowflake":{"uri":"http://data-connector-agent:8081/api/v1/snowflake"}}}}' -HASURA_GRAPHQL_JWT_SECRET={"jwk_url": "http://keycloak:8088/realms/hasura/protocol/openid-connect/certs"} - -# Environment variable for auto migrate -HASURA_GRAPHQL_MIGRATIONS_DIR=/migrations -HASURA_GRAPHQL_METADATA_DIR=/metadata -HASURA_GRAPHQL_ENABLE_CONSOLE='true' -HASURA_ACTION_STABLE_DIFFUSION_URL=http://sd:8000 -HASURA_EVENTS_HOOK_URL="http://worker:8787" \ No newline at end of file diff --git a/conf/sample.env_app-backend-postgres b/conf/sample.env_app-backend-postgres deleted file mode 100644 index 39aa93db5..000000000 --- a/conf/sample.env_app-backend-postgres +++ /dev/null @@ -1 +0,0 @@ -POSTGRES_PASSWORD=postgrespassword \ No newline at end of file diff --git a/conf/sample.env_web-client b/conf/sample.env_web-client deleted file mode 100644 index e024bb762..000000000 --- a/conf/sample.env_web-client +++ /dev/null @@ -1,15 +0,0 @@ -NEXT_PUBLIC_ENV=development -NEXT_PUBLIC_WEB_URL=http://localhost:3000 -NEXT_PUBLIC_DISCORD_INVITATION_URL=# -NEXT_PUBLIC_DOWNLOAD_APP_IOS=# -NEXT_PUBLIC_DOWNLOAD_APP_ANDROID=# -NEXT_PUBLIC_GRAPHQL_ENGINE_URL=http://localhost:8080/v1/graphql -NEXT_PUBLIC_GRAPHQL_ENGINE_WEB_SOCKET_URL=ws://localhost:8080/v1/graphql -NEXT_PUBLIC_OPENAPI_ENDPOINT=http://localhost:8000/v1/chat/completions -KEYCLOAK_CLIENT_ID=hasura -KEYCLOAK_CLIENT_SECRET=oMtCPAV7diKpE564SBspgKj4HqlKM4Hy -AUTH_ISSUER=http://localhost:8088/realms/$KEYCLOAK_CLIENT_ID -NEXTAUTH_URL=http://localhost:3000 -NEXTAUTH_SECRET=my-secret -END_SESSION_URL=http://localhost:8088/realms/$KEYCLOAK_CLIENT_ID/protocol/openid-connect/logout -REFRESH_TOKEN_URL=http://localhost:8088/realms/$KEYCLOAK_CLIENT_ID/protocol/openid-connect/token diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 2a0c2bad7..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,121 +0,0 @@ -# docker version -version: "3" - -services: - keycloak: - image: quay.io/keycloak/keycloak:${KEYCLOAK_VERSION-22.0.0} - command: ["start-dev", "--import-realm", "--http-port", "8088"] - environment: - KC_DB: postgres - KC_DB_URL_HOST: postgres - KC_DB_URL_DATABASE: jan-keycloak - KC_DB_PASSWORD: postgrespassword - KC_DB_USERNAME: postgres - KC_DB_SCHEMA: public - KC_HEALTH_ENABLED: "true" - KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN-admin} - KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD-admin} - volumes: - - ./conf/keycloak_conf:/opt/keycloak/data/import - - ./conf/keycloak_theme/keywind:/opt/keycloak/themes/keywind - ports: - - "8088:8088" - depends_on: - postgres: - condition: service_healthy - networks: - jan_community: - ipv4_address: 172.20.0.9 - - postgres: - image: postgres:15 - command: postgres -c jit=off - restart: always - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgrespassword - ports: - - "5432:5432" - healthcheck: - test: "exit 0" - volumes: - - ./conf/db/docker_psql_init.sql:/docker-entrypoint-initdb.d/docker_postgres_init.sql - networks: - jan_community: - ipv4_address: 172.20.0.11 - - graphql-engine: - image: hasura/graphql-engine:v2.31.0.cli-migrations-v3 - ports: - - 8080:8080 - restart: always - env_file: - - conf/sample.env_app-backend - volumes: - - ./app-backend/hasura/migrations:/migrations - - ./app-backend/hasura/metadata:/metadata - depends_on: - data-connector-agent: - condition: service_healthy - keycloak: - condition: service_started - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"] - interval: 10s - timeout: 10s - retries: 30 - networks: - jan_community: - ipv4_address: 172.20.0.12 - - data-connector-agent: - image: hasura/graphql-data-connector:v2.31.0 - restart: always - ports: - - 8081:8081 - environment: - QUARKUS_LOG_LEVEL: ERROR # FATAL, ERROR, WARN, INFO, DEBUG, TRACE - ## https://quarkus.io/guides/opentelemetry#configuration-reference - QUARKUS_OPENTELEMETRY_ENABLED: "false" - ## QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_ENDPOINT: http://jaeger:4317 - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8081/api/v1/athena/health"] - interval: 5s - timeout: 10s - retries: 5 - start_period: 5s - networks: - jan_community: - ipv4_address: 172.20.0.14 - - web: - build: - context: ./web-client - dockerfile: ./dev.Dockerfile - restart: always - volumes: - - ./web-client/:/app - - /app/node_modules - - /app/.next - env_file: - - conf/sample.env_web-client - ports: - - 3000:3000 - environment: - NODE_ENV: development - extra_hosts: - - "localhost:172.20.0.9" - depends_on: - graphql-engine: - condition: service_healthy - networks: - jan_community: - ipv4_address: 172.20.0.15 - -networks: - jan_community: - driver: bridge - ipam: - driver: default - config: - - subnet: 172.20.0.0/16 diff --git a/app/electron/core/plugin-manager/execution/Activation.js b/electron/core/plugin-manager/execution/Activation.js similarity index 100% rename from app/electron/core/plugin-manager/execution/Activation.js rename to electron/core/plugin-manager/execution/Activation.js diff --git a/app/electron/core/plugin-manager/execution/ExtensionPoint.js b/electron/core/plugin-manager/execution/ExtensionPoint.js similarity index 100% rename from app/electron/core/plugin-manager/execution/ExtensionPoint.js rename to electron/core/plugin-manager/execution/ExtensionPoint.js diff --git a/app/electron/core/plugin-manager/execution/ExtensionPoint.test.js b/electron/core/plugin-manager/execution/ExtensionPoint.test.js similarity index 100% rename from app/electron/core/plugin-manager/execution/ExtensionPoint.test.js rename to electron/core/plugin-manager/execution/ExtensionPoint.test.js diff --git a/app/electron/core/plugin-manager/execution/Plugin.js b/electron/core/plugin-manager/execution/Plugin.js similarity index 100% rename from app/electron/core/plugin-manager/execution/Plugin.js rename to electron/core/plugin-manager/execution/Plugin.js diff --git a/app/electron/core/plugin-manager/execution/Plugin.test.js b/electron/core/plugin-manager/execution/Plugin.test.js similarity index 100% rename from app/electron/core/plugin-manager/execution/Plugin.test.js rename to electron/core/plugin-manager/execution/Plugin.test.js diff --git a/app/electron/core/plugin-manager/execution/activation-manager.js b/electron/core/plugin-manager/execution/activation-manager.js similarity index 100% rename from app/electron/core/plugin-manager/execution/activation-manager.js rename to electron/core/plugin-manager/execution/activation-manager.js diff --git a/app/electron/core/plugin-manager/execution/activation-manager.test.js b/electron/core/plugin-manager/execution/activation-manager.test.js similarity index 100% rename from app/electron/core/plugin-manager/execution/activation-manager.test.js rename to electron/core/plugin-manager/execution/activation-manager.test.js diff --git a/app/electron/core/plugin-manager/execution/extension-manager.js b/electron/core/plugin-manager/execution/extension-manager.js similarity index 100% rename from app/electron/core/plugin-manager/execution/extension-manager.js rename to electron/core/plugin-manager/execution/extension-manager.js diff --git a/app/electron/core/plugin-manager/execution/extension-manager.test.js b/electron/core/plugin-manager/execution/extension-manager.test.js similarity index 100% rename from app/electron/core/plugin-manager/execution/extension-manager.test.js rename to electron/core/plugin-manager/execution/extension-manager.test.js diff --git a/app/electron/core/plugin-manager/execution/facade.js b/electron/core/plugin-manager/execution/facade.js similarity index 100% rename from app/electron/core/plugin-manager/execution/facade.js rename to electron/core/plugin-manager/execution/facade.js diff --git a/app/electron/core/plugin-manager/execution/import-manager.js b/electron/core/plugin-manager/execution/import-manager.js similarity index 100% rename from app/electron/core/plugin-manager/execution/import-manager.js rename to electron/core/plugin-manager/execution/import-manager.js diff --git a/app/electron/core/plugin-manager/execution/index.js b/electron/core/plugin-manager/execution/index.js similarity index 90% rename from app/electron/core/plugin-manager/execution/index.js rename to electron/core/plugin-manager/execution/index.js index 3e0ce3820..83fe0ce17 100644 --- a/app/electron/core/plugin-manager/execution/index.js +++ b/electron/core/plugin-manager/execution/index.js @@ -2,10 +2,10 @@ import { definePresetEps, setImporter } from "./import-manager.js"; export * as extensionPoints from "./extension-manager.js"; export * as activationPoints from "./activation-manager.js"; -export * as plugins from "./facade"; +export * as plugins from "./facade.js"; export { default as ExtensionPoint } from "./ExtensionPoint.js"; -if (typeof window === "undefined" || !window.pluggableElectronIpc) +if (typeof window !== "undefined" && !window.pluggableElectronIpc) console.warn( "Facade is not registered in preload. Facade functions will throw an error if used." ); diff --git a/app/electron/core/plugin-manager/execution/index.test.js b/electron/core/plugin-manager/execution/index.test.js similarity index 100% rename from app/electron/core/plugin-manager/execution/index.test.js rename to electron/core/plugin-manager/execution/index.test.js diff --git a/app/electron/core/plugin-manager/facade/index.js b/electron/core/plugin-manager/facade/index.js similarity index 100% rename from app/electron/core/plugin-manager/facade/index.js rename to electron/core/plugin-manager/facade/index.js diff --git a/app/electron/core/plugin-manager/facade/index.test.js b/electron/core/plugin-manager/facade/index.test.js similarity index 100% rename from app/electron/core/plugin-manager/facade/index.test.js rename to electron/core/plugin-manager/facade/index.test.js diff --git a/app/electron/core/plugin-manager/pluginMgr/Plugin.js b/electron/core/plugin-manager/pluginMgr/Plugin.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/Plugin.js rename to electron/core/plugin-manager/pluginMgr/Plugin.js diff --git a/app/electron/core/plugin-manager/pluginMgr/Plugin.test.js b/electron/core/plugin-manager/pluginMgr/Plugin.test.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/Plugin.test.js rename to electron/core/plugin-manager/pluginMgr/Plugin.test.js diff --git a/app/electron/core/plugin-manager/pluginMgr/globals.js b/electron/core/plugin-manager/pluginMgr/globals.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/globals.js rename to electron/core/plugin-manager/pluginMgr/globals.js diff --git a/app/electron/core/plugin-manager/pluginMgr/index.js b/electron/core/plugin-manager/pluginMgr/index.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/index.js rename to electron/core/plugin-manager/pluginMgr/index.js diff --git a/app/electron/core/plugin-manager/pluginMgr/index.test.js b/electron/core/plugin-manager/pluginMgr/index.test.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/index.test.js rename to electron/core/plugin-manager/pluginMgr/index.test.js diff --git a/app/electron/core/plugin-manager/pluginMgr/router.js b/electron/core/plugin-manager/pluginMgr/router.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/router.js rename to electron/core/plugin-manager/pluginMgr/router.js diff --git a/app/electron/core/plugin-manager/pluginMgr/store.js b/electron/core/plugin-manager/pluginMgr/store.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/store.js rename to electron/core/plugin-manager/pluginMgr/store.js diff --git a/app/electron/core/plugin-manager/pluginMgr/store.test.js b/electron/core/plugin-manager/pluginMgr/store.test.js similarity index 100% rename from app/electron/core/plugin-manager/pluginMgr/store.test.js rename to electron/core/plugin-manager/pluginMgr/store.test.js diff --git a/electron/core/plugins/data-plugin/README.md b/electron/core/plugins/data-plugin/README.md new file mode 100644 index 000000000..2197d9ad2 --- /dev/null +++ b/electron/core/plugins/data-plugin/README.md @@ -0,0 +1,8 @@ +## Database handler plugin for Jan App + +**Notice**: please only install dependencies and run build using npm and not yarn. + +- index.ts: Main entry point for the plugin. +- module.ts: Defines the plugin module which would be executed by the main node process. +- package.json: Defines the plugin metadata. +- tsconfig.json: Defines the typescript configuration. diff --git a/electron/core/plugins/data-plugin/index.ts b/electron/core/plugins/data-plugin/index.ts new file mode 100644 index 000000000..c2f91d89a --- /dev/null +++ b/electron/core/plugins/data-plugin/index.ts @@ -0,0 +1,152 @@ +// Provide an async method to manipulate the price provided by the extension point +const MODULE_PATH = "data-plugin/dist/module.js"; + +const storeModel = (model: any) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "storeModel", model) + .then((res: any) => resolve(res)); + } + }); + +const getFinishedDownloadModels = () => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getFinishedDownloadModels") + .then((res: any) => resolve(res)); + } + }); + +const getModelById = (modelId: string) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getModelById", modelId) + .then((res: any) => resolve(res)); + } + }); + +const updateFinishedDownloadAt = (fileName: string) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc( + MODULE_PATH, + "updateFinishedDownloadAt", + fileName, + Date.now() + ) + .then((res: any) => resolve(res)); + } + }); + +const getUnfinishedDownloadModels = () => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getUnfinishedDownloadModels") + .then((res: any[]) => resolve(res)); + } else { + resolve([]); + } + }); + +const deleteDownloadModel = (modelId: string) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "deleteDownloadModel", modelId) + .then((res: any) => resolve(res)); + } + }); + +const getConversations = () => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getConversations") + .then((res: any[]) => resolve(res)); + } else { + resolve([]); + } + }); +const getConversationMessages = (id: any) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getConversationMessages", id) + .then((res: any[]) => resolve(res)); + } else { + resolve([]); + } + }); + +const createConversation = (conversation: any) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "storeConversation", conversation) + .then((res: any) => { + resolve(res); + }); + } else { + resolve("-"); + } + }); +const createMessage = (message: any) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "storeMessage", message) + .then((res: any) => resolve(res)); + } else { + resolve("-"); + } + }); + +const deleteConversation = (id: any) => + new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "deleteConversation", id) + .then((res: any) => { + resolve(res); + }); + } else { + resolve("-"); + } + }); + +const setupDb = () => { + window.electronAPI.invokePluginFunc(MODULE_PATH, "init"); +}; + +// Register all the above functions and objects with the relevant extension points +export function init({ register }: { register: any }) { + setupDb(); + register("getConversations", "getConv", getConversations, 1); + register("createConversation", "insertConv", createConversation); + register("deleteConversation", "deleteConv", deleteConversation); + register("createMessage", "insertMessage", createMessage); + register("getConversationMessages", "getMessages", getConversationMessages); + register("storeModel", "storeModel", storeModel); + register( + "updateFinishedDownloadAt", + "updateFinishedDownloadAt", + updateFinishedDownloadAt + ); + register( + "getUnfinishedDownloadModels", + "getUnfinishedDownloadModels", + getUnfinishedDownloadModels + ); + register("deleteDownloadModel", "deleteDownloadModel", deleteDownloadModel); + register("getModelById", "getModelById", getModelById); + register( + "getFinishedDownloadModels", + "getFinishedDownloadModels", + getFinishedDownloadModels + ); +} diff --git a/electron/core/plugins/data-plugin/module.ts b/electron/core/plugins/data-plugin/module.ts new file mode 100644 index 000000000..384e538ae --- /dev/null +++ b/electron/core/plugins/data-plugin/module.ts @@ -0,0 +1,371 @@ +const sqlite3 = require("sqlite3").verbose(); +const path = require("path"); +const { app } = require("electron"); + +const MODEL_TABLE_CREATION = ` +CREATE TABLE IF NOT EXISTS models ( + id TEXT PRIMARY KEY, + slug TEXT NOT NULL, + name TEXT NOT NULL, + description TEXT NOT NULL, + avatar_url TEXT, + long_description TEXT NOT NULL, + technical_description TEXT NOT NULL, + author TEXT NOT NULL, + version TEXT NOT NULL, + model_url TEXT NOT NULL, + nsfw INTEGER NOT NULL, + greeting TEXT NOT NULL, + type TEXT NOT NULL, + file_name TEXT NOT NULL, + download_url TEXT NOT NULL, + start_download_at INTEGER DEFAULT -1, + finish_download_at INTEGER DEFAULT -1, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP +);`; + +const MODEL_TABLE_INSERTION = ` +INSERT INTO models ( + id, + slug, + name, + description, + avatar_url, + long_description, + technical_description, + author, + version, + model_url, + nsfw, + greeting, + type, + file_name, + download_url, + start_download_at +) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`; + +function init() { + const db = new sqlite3.Database(path.join(app.getPath("userData"), "jan.db")); + console.log( + `Database located at ${path.join(app.getPath("userData"), "jan.db")}` + ); + + db.serialize(() => { + db.run(MODEL_TABLE_CREATION); + db.run( + "CREATE TABLE IF NOT EXISTS conversations ( id INTEGER PRIMARY KEY, name TEXT, model_id TEXT, image TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);" + ); + db.run( + "CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY, name TEXT, conversation_id INTEGER, user TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);" + ); + }); + + const stmt = db.prepare( + "INSERT INTO conversations (name, model_id, image, message) VALUES (?, ?, ?, ?)" + ); + stmt.finalize(); + db.close(); +} + +/** + * Store a model in the database when user start downloading it + * + * @param model Product + */ +function storeModel(model: any) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + console.debug("Inserting", JSON.stringify(model)); + db.serialize(() => { + const stmt = db.prepare(MODEL_TABLE_INSERTION); + stmt.run( + model.id, + model.slug, + model.name, + model.description, + model.avatarUrl, + model.longDescription, + model.technicalDescription, + model.author, + model.version, + model.modelUrl, + model.nsfw, + model.greeting, + model.type, + model.fileName, + model.downloadUrl, + Date.now(), + function (err: any) { + if (err) { + // Handle the insertion error here + console.error(err.message); + res(undefined); + return; + } + // @ts-ignoreF + const id = this.lastID; + res(id); + return; + } + ); + stmt.finalize(); + }); + + db.close(); + }); +} + +/** + * Update the finished download time of a model + * + * @param model Product + */ +function updateFinishedDownloadAt(fileName: string, time: number) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + console.debug(`Updating fileName ${fileName} to ${time}`); + const stmt = `UPDATE models SET finish_download_at = ? WHERE file_name = ?`; + db.run(stmt, [time, fileName], (err: any) => { + if (err) { + console.log(err); + } else { + console.log("Updated 1 row"); + res("Updated"); + } + }); + + db.close(); + }); +} + +/** + * Get all unfinished models from the database + */ +function getUnfinishedDownloadModels() { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + const query = `SELECT * FROM models WHERE finish_download_at = -1 ORDER BY start_download_at DESC`; + db.all(query, (err: Error, row: any) => { + res(row); + }); + db.close(); + }); +} + +function getFinishedDownloadModels() { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + const query = `SELECT * FROM models WHERE finish_download_at != -1 ORDER BY finish_download_at DESC`; + db.all(query, (err: Error, row: any) => { + res(row); + }); + db.close(); + }); +} + +function deleteDownloadModel(modelId: string) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + console.log(`Deleting ${modelId}`); + db.serialize(() => { + const stmt = db.prepare("DELETE FROM models WHERE id = ?"); + stmt.run(modelId); + stmt.finalize(); + }); + + db.close(); + }); +} + +function getModelById(modelId: string) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + console.debug("Get model by id", modelId); + db.get( + `SELECT * FROM models WHERE id = ?`, + [modelId], + (err: any, row: any) => { + console.debug("Get model by id result", row); + + if (row) { + const product = { + id: row.id, + slug: row.slug, + name: row.name, + description: row.description, + avatarUrl: row.avatar_url, + longDescription: row.long_description, + technicalDescription: row.technical_description, + author: row.author, + version: row.version, + modelUrl: row.model_url, + nsfw: row.nsfw, + greeting: row.greeting, + type: row.type, + inputs: row.inputs, + outputs: row.outputs, + createdAt: new Date(row.created_at), + updatedAt: new Date(row.updated_at), + fileName: row.file_name, + downloadUrl: row.download_url, + }; + res(product); + } + } + ); + + db.close(); + }); +} + +function getConversations() { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + db.all( + "SELECT * FROM conversations ORDER BY created_at DESC", + (err: any, row: any) => { + res(row); + } + ); + db.close(); + }); +} +function storeConversation(conversation: any) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + db.serialize(() => { + const stmt = db.prepare( + "INSERT INTO conversations (name, model_id, image, message) VALUES (?, ?, ?, ?)" + ); + stmt.run( + conversation.name, + conversation.model_id, + conversation.image, + conversation.message, + function (err: any) { + if (err) { + // Handle the insertion error here + console.error(err.message); + res(undefined); + return; + } + // @ts-ignoreF + const id = this.lastID; + res(id); + return; + } + ); + stmt.finalize(); + }); + + db.close(); + }); +} + +function storeMessage(message: any) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + db.serialize(() => { + const stmt = db.prepare( + "INSERT INTO messages (name, conversation_id, user, message) VALUES (?, ?, ?, ?)" + ); + stmt.run( + message.name, + message.conversation_id, + message.user, + message.message, + (err: any) => { + if (err) { + // Handle the insertion error here + console.error(err.message); + res(undefined); + return; + } + //@ts-ignore + const id = this.lastID; + res(id); + return; + } + ); + stmt.finalize(); + }); + + db.close(); + }); +} + +function deleteConversation(id: any) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + db.serialize(() => { + const deleteConv = db.prepare("DELETE FROM conversations WHERE id = ?"); + deleteConv.run(id); + deleteConv.finalize(); + const deleteMessages = db.prepare( + "DELETE FROM messages WHERE conversation_id = ?" + ); + deleteMessages.run(id); + deleteMessages.finalize(); + res([]); + }); + + db.close(); + }); +} + +function getConversationMessages(conversation_id: any) { + return new Promise((res) => { + const db = new sqlite3.Database( + path.join(app.getPath("userData"), "jan.db") + ); + + const query = `SELECT * FROM messages WHERE conversation_id = ${conversation_id} ORDER BY created_at DESC`; + db.all(query, (err: Error, row: any) => { + res(row); + }); + db.close(); + }); +} + +module.exports = { + init, + getConversations, + deleteConversation, + storeConversation, + storeMessage, + getConversationMessages, + storeModel, + updateFinishedDownloadAt, + getUnfinishedDownloadModels, + getFinishedDownloadModels, + deleteDownloadModel, + getModelById, +}; diff --git a/electron/core/plugins/data-plugin/package.json b/electron/core/plugins/data-plugin/package.json new file mode 100644 index 000000000..83f148f7e --- /dev/null +++ b/electron/core/plugins/data-plugin/package.json @@ -0,0 +1,41 @@ +{ + "name": "data-plugin", + "version": "2.1.0", + "description": "", + "main": "dist/index.js", + "author": "Jan", + "license": "MIT", + "activationPoints": [ + "init" + ], + "scripts": { + "build": "tsc -b . && webpack --config webpack.config.js", + "build:package": "rimraf ./data-plugin*.tgz && npm run build && npm pack", + "build:publish": "npm run build:package && cpx *.tgz ../../pre-install" + }, + "exports": { + ".": "./dist/index.js", + "./main": "./dist/module.js" + }, + "devDependencies": { + "cpx": "^1.5.0", + "rimraf": "^3.0.2", + "ts-loader": "^9.4.4", + "ts-node": "^10.9.1", + "typescript": "^5.2.2", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4" + }, + "bundledDependencies": [ + "sql.js", + "sqlite3" + ], + "files": [ + "dist/**", + "package.json", + "node_modules" + ], + "dependencies": { + "sqlite3": "^5.1.6" + } +} diff --git a/electron/core/plugins/data-plugin/tsconfig.json b/electron/core/plugins/data-plugin/tsconfig.json new file mode 100644 index 000000000..72d6f3732 --- /dev/null +++ b/electron/core/plugins/data-plugin/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Language and Environment */ + "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + /* Modules */ + "module": "ES6" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "." /* Specify the base directory to resolve non-relative module names. */, + // "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */, + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + /* Type Checking */ + "strict": false /* Enable all strict type-checking options. */, + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/electron/core/plugins/data-plugin/types/index.d.ts b/electron/core/plugins/data-plugin/types/index.d.ts new file mode 100644 index 000000000..a7ac3c8ac --- /dev/null +++ b/electron/core/plugins/data-plugin/types/index.d.ts @@ -0,0 +1,7 @@ +export {}; + +declare global { + interface Window { + electronAPI?: any | undefined; + } +} diff --git a/electron/core/plugins/data-plugin/webpack.config.js b/electron/core/plugins/data-plugin/webpack.config.js new file mode 100644 index 000000000..18696aa34 --- /dev/null +++ b/electron/core/plugins/data-plugin/webpack.config.js @@ -0,0 +1,25 @@ +const path = require("path"); + +module.exports = { + experiments: { outputModule: true }, + entry: "./index.ts", // Adjust the entry point to match your project's main file + mode: "production", + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules/, + }, + ], + }, + output: { + filename: "index.js", // Adjust the output file name as needed + path: path.resolve(__dirname, "dist"), + library: { type: "module" }, // Specify ESM output format + }, + resolve: { + extensions: [".ts", ".js"], + }, + // Add loaders and other configuration as needed for your project +}; diff --git a/electron/core/plugins/inference-plugin/index.js b/electron/core/plugins/inference-plugin/index.js new file mode 100644 index 000000000..76c1445fc --- /dev/null +++ b/electron/core/plugins/inference-plugin/index.js @@ -0,0 +1,25 @@ +const MODULE_PATH = "inference-plugin/dist/module.js"; + +const prompt = async (prompt) => + new Promise(async (resolve) => { + if (window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "prompt", prompt) + .then((res) => resolve(res)); + } + }); + +const initModel = async (product) => + new Promise(async (resolve) => { + if (window.electronAPI) { + window.electronAPI + .invokePluginFunc(MODULE_PATH, "initModel", product) + .then((res) => resolve(res)); + } + }); + +// Register all the above functions and objects with the relevant extension points +export function init({ register }) { + register("initModel", "initModel", initModel); + register("prompt", "prompt", prompt); +} diff --git a/electron/core/plugins/inference-plugin/module.js b/electron/core/plugins/inference-plugin/module.js new file mode 100644 index 000000000..763c632cc --- /dev/null +++ b/electron/core/plugins/inference-plugin/module.js @@ -0,0 +1,55 @@ +const path = require("path"); +const { app, dialog } = require("electron"); +const _importDynamic = new Function("modulePath", "return import(modulePath)"); + +let llamaSession = null; + +async function initModel(product) { + // fileName fallback + if (!product.fileName) { + product.fileName = product.file_name; + } + + if (!product.fileName) { + await dialog.showMessageBox({ + message: "Selected model does not have file name..", + }); + + return; + } + + console.info(`Initializing model: ${product.name}..`); + _importDynamic("../node_modules/node-llama-cpp/dist/index.js") + .then(({ LlamaContext, LlamaChatSession, LlamaModel }) => { + const modelPath = path.join(app.getPath("userData"), product.fileName); + const model = new LlamaModel({ modelPath }); + const context = new LlamaContext({ model }); + llamaSession = new LlamaChatSession({ context }); + console.info(`Init model ${product.name} successfully!`); + }) + .catch(async (e) => { + console.error(e); + await dialog.showMessageBox({ + message: "Failed to import LLM module", + }); + }); +} + +async function prompt(prompt) { + if (!llamaSession) { + await dialog.showMessageBox({ + message: "Model not initialized", + }); + + return; + } + console.log("prompt: ", prompt); + const response = await llamaSession.prompt(prompt); + console.log("response: ", response); + return response; +} + +module.exports = { + initModel, + prompt, +}; diff --git a/electron/core/plugins/inference-plugin/package.json b/electron/core/plugins/inference-plugin/package.json new file mode 100644 index 000000000..170a2f0eb --- /dev/null +++ b/electron/core/plugins/inference-plugin/package.json @@ -0,0 +1,38 @@ +{ + "name": "inference-plugin", + "version": "0.0.1", + "description": "", + "main": "dist/index.js", + "author": "James", + "license": "MIT", + "activationPoints": [ + "init" + ], + "scripts": { + "build": "webpack --config webpack.config.js", + "build:package": "rimraf ./*.tgz && npm run build && cpx \"module.js\" \"dist\" && npm pack", + "build:publish": "yarn build:package && cpx *.tgz ../../pre-install" + }, + "devDependencies": { + "cpx": "^1.5.0", + "rimraf": "^3.0.2", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4" + }, + "bundledDependencies": [ + "electron-is-dev", + "node-llama-cpp" + ], + "dependencies": { + "electron-is-dev": "^2.0.0", + "node-llama-cpp": "^2.4.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "files": [ + "dist/*", + "package.json", + "README.md" + ] +} diff --git a/app/electron/core/model-management-plugin/webpack.config.js b/electron/core/plugins/inference-plugin/webpack.config.js similarity index 64% rename from app/electron/core/model-management-plugin/webpack.config.js rename to electron/core/plugins/inference-plugin/webpack.config.js index 7248a0990..2821852d4 100644 --- a/app/electron/core/model-management-plugin/webpack.config.js +++ b/electron/core/plugins/inference-plugin/webpack.config.js @@ -3,8 +3,18 @@ const path = require("path"); module.exports = { experiments: { outputModule: true }, entry: "./index.js", // Adjust the entry point to match your project's main file + mode: "production", + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules/, + }, + ], + }, output: { - filename: "bundle.js", // Adjust the output file name as needed + filename: "index.js", // Adjust the output file name as needed path: path.resolve(__dirname, "dist"), library: { type: "module" }, // Specify ESM output format }, diff --git a/app/electron/core/model-management-plugin/index.js b/electron/core/plugins/model-management-plugin/index.js similarity index 54% rename from app/electron/core/model-management-plugin/index.js rename to electron/core/plugins/model-management-plugin/index.js index 1f934924f..0d2449931 100644 --- a/app/electron/core/model-management-plugin/index.js +++ b/electron/core/plugins/model-management-plugin/index.js @@ -1,39 +1,39 @@ +const MODULE_PATH = "model-management-plugin/dist/module.js"; + const getDownloadedModels = async () => new Promise(async (resolve) => { if (window.electronAPI) { - const response = await window.electronAPI.getDownloadedModels(); - resolve(response); + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getDownloadedModels") + .then((res) => resolve(res)); } }); const getAvailableModels = async () => new Promise(async (resolve) => { if (window.electronAPI) { - const response = await window.electronAPI.getAvailableModels(); - resolve(response); + window.electronAPI + .invokePluginFunc(MODULE_PATH, "getAvailableModels") + .then((res) => resolve(res)); } }); -const downloadModel = async (url) => +const downloadModel = async (product) => new Promise(async (resolve) => { - if (window.electronAPI) { - const response = await window.electronAPI.downloadModel(url); - resolve(response); + if (window && window.electronAPI) { + window.electronAPI + .downloadFile(product.downloadUrl, product.fileName) + .then((res) => resolve(res)); + } else { + resolve("-"); } }); const deleteModel = async (path) => new Promise(async (resolve) => { if (window.electronAPI) { - const response = await window.electronAPI.deleteModel(path); - resolve(response); - } - }); - -const initModel = async (product) => - new Promise(async (resolve) => { - if (window.electronAPI) { - const response = await window.electronAPI.initModel(product); + console.debug(`Delete model model management plugin: ${path}`); + const response = await window.electronAPI.deleteFile(path); resolve(response); } }); @@ -44,5 +44,4 @@ export function init({ register }) { register("getAvailableModels", "getAvailableModels", getAvailableModels); register("downloadModel", "downloadModel", downloadModel); register("deleteModel", "deleteModel", deleteModel); - register("initModel", "initModel", initModel); } diff --git a/electron/core/plugins/model-management-plugin/module.js b/electron/core/plugins/model-management-plugin/module.js new file mode 100644 index 000000000..d1472656b --- /dev/null +++ b/electron/core/plugins/model-management-plugin/module.js @@ -0,0 +1,101 @@ +const path = require("path"); +const { readdirSync, lstatSync } = require("fs"); +const { app } = require("electron"); + +const ALL_MODELS = [ + { + id: "llama-2-7b-chat.Q4_K_M.gguf.bin", + slug: "llama-2-7b-chat.Q4_K_M.gguf.bin", + name: "Llama 2 7B Chat - GGUF", + description: "medium, balanced quality - recommended", + avatarUrl: + "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/6426d3f3a7723d62b53c259b/tvPikpAzKTKGN5wrpadOJ.jpeg?w=200&h=200&f=face", + longDescription: + "GGUF is a new format introduced by the llama.cpp team on August 21st 2023. It is a replacement for GGML, which is no longer supported by llama.cpp. GGUF offers numerous advantages over GGML, such as better tokenisation, and support for special tokens. It is also supports metadata, and is designed to be extensible.", + technicalDescription: + 'GGML_TYPE_Q4_K - "type-1" 4-bit quantization in super-blocks containing 8 blocks, each block having 32 weights. Scales and mins are quantized with 6 bits. This ends up using 4.5 bpw.', + author: "The Bloke", + version: "1.0.0", + modelUrl: "https://google.com", + nsfw: false, + greeting: "Hello there", + type: "LLM", + inputs: undefined, + outputs: undefined, + createdAt: 0, + updatedAt: undefined, + fileName: "llama-2-7b-chat.Q4_K_M.gguf.bin", + downloadUrl: + "https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf", + }, + { + id: "llama-2-13b-chat.Q4_K_M.gguf", + slug: "llama-2-13b-chat.Q4_K_M.gguf", + name: "Llama 2 13B Chat - GGUF", + description: "medium, balanced quality - recommended", + avatarUrl: + "https://aeiljuispo.cloudimg.io/v7/https://cdn-uploads.huggingface.co/production/uploads/6426d3f3a7723d62b53c259b/tvPikpAzKTKGN5wrpadOJ.jpeg?w=200&h=200&f=face", + longDescription: + "GGUF is a new format introduced by the llama.cpp team on August 21st 2023. It is a replacement for GGML, which is no longer supported by llama.cpp. GGUF offers numerous advantages over GGML, such as better tokenisation, and support for special tokens. It is also supports metadata, and is designed to be extensible.", + technicalDescription: + 'GGML_TYPE_Q4_K - "type-1" 4-bit quantization in super-blocks containing 8 blocks, each block having 32 weights. Scales and mins are quantized with 6 bits. This ends up using 4.5 bpw.', + author: "The Bloke", + version: "1.0.0", + modelUrl: "https://google.com", + nsfw: false, + greeting: "Hello there", + type: "LLM", + inputs: undefined, + outputs: undefined, + createdAt: 0, + updatedAt: undefined, + fileName: "llama-2-13b-chat.Q4_K_M.gguf.bin", + downloadUrl: + "https://huggingface.co/TheBloke/Llama-2-13B-chat-GGUF/resolve/main/llama-2-13b-chat.Q4_K_M.gguf", + }, +]; + +function getDownloadedModels() { + const userDataPath = app.getPath("userData"); + + const allBinariesName = []; + var files = readdirSync(userDataPath); + for (var i = 0; i < files.length; i++) { + var filename = path.join(userDataPath, files[i]); + var stat = lstatSync(filename); + if (stat.isDirectory()) { + // ignore + } else if (filename.endsWith(".bin")) { + var binaryName = path.basename(filename); + allBinariesName.push(binaryName); + } + } + + const downloadedModels = ALL_MODELS.map((model) => { + if ( + model.fileName && + allBinariesName + .map((t) => t.toLowerCase()) + .includes(model.fileName.toLowerCase()) + ) { + return model; + } + return undefined; + }).filter((m) => m !== undefined); + + return downloadedModels; +} + +function getAvailableModels() { + const downloadedModelIds = getDownloadedModels().map((model) => model.id); + return ALL_MODELS.filter((model) => { + if (!downloadedModelIds.includes(model.id)) { + return model; + } + }); +} + +module.exports = { + getDownloadedModels, + getAvailableModels, +}; diff --git a/app/electron/core/model-management-plugin/package.json b/electron/core/plugins/model-management-plugin/package.json similarity index 57% rename from app/electron/core/model-management-plugin/package.json rename to electron/core/plugins/model-management-plugin/package.json index cba07a937..dd7d61d3c 100644 --- a/app/electron/core/model-management-plugin/package.json +++ b/electron/core/plugins/model-management-plugin/package.json @@ -2,22 +2,23 @@ "name": "model-management-plugin", "version": "0.0.1", "description": "", - "main": "dist/bundle.js", + "main": "dist/index.js", "author": "James", "license": "MIT", "activationPoints": [ "init" ], "scripts": { - "prepare": "webpack --config webpack.config.js", - "package": "rimraf ./*.tgz && npm pack" + "build": "webpack --config webpack.config.js", + "build:package": "rimraf ./*.tgz && npm run build && cpx \"module.js\" \"dist\" && npm pack", + "build:publish": "yarn build:package && cpx *.tgz ../../pre-install" }, "devDependencies": { + "cpx": "^1.5.0", "rimraf": "^3.0.2", "webpack": "^5.88.2", "webpack-cli": "^5.1.4" }, - "dependencies": {}, "files": [ "dist/*", "package.json", diff --git a/app/electron/core/data-plugin/webpack.config.js b/electron/core/plugins/model-management-plugin/webpack.config.js similarity index 64% rename from app/electron/core/data-plugin/webpack.config.js rename to electron/core/plugins/model-management-plugin/webpack.config.js index 7248a0990..2821852d4 100644 --- a/app/electron/core/data-plugin/webpack.config.js +++ b/electron/core/plugins/model-management-plugin/webpack.config.js @@ -3,8 +3,18 @@ const path = require("path"); module.exports = { experiments: { outputModule: true }, entry: "./index.js", // Adjust the entry point to match your project's main file + mode: "production", + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules/, + }, + ], + }, output: { - filename: "bundle.js", // Adjust the output file name as needed + filename: "index.js", // Adjust the output file name as needed path: path.resolve(__dirname, "dist"), library: { type: "module" }, // Specify ESM output format }, diff --git a/electron/core/plugins/monitoring-plugin/index.js b/electron/core/plugins/monitoring-plugin/index.js new file mode 100644 index 000000000..ac47a9adc --- /dev/null +++ b/electron/core/plugins/monitoring-plugin/index.js @@ -0,0 +1,36 @@ +// Provide an async method to manipulate the price provided by the extension point +const PLUGIN_NAME = "monitoring-plugin/dist/module.js"; + +const getResourcesInfo = () => { + return new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(PLUGIN_NAME, "getResourcesInfo") + .then((res) => { + resolve(res); + }); + } else { + resolve({}); + } + }); +}; + +const getCurrentLoad = () => { + return new Promise((resolve) => { + if (window && window.electronAPI) { + window.electronAPI + .invokePluginFunc(PLUGIN_NAME, "getCurrentLoad") + .then((res) => { + resolve(res); + }); + } else { + resolve({}); + } + }); +}; + +// Register all the above functions and objects with the relevant extension points +export function init({ register }) { + register("getResourcesInfo", "getResourcesInfo", getResourcesInfo); + register("getCurrentLoad", "getCurrentLoad", getCurrentLoad); +} diff --git a/electron/core/plugins/monitoring-plugin/module.js b/electron/core/plugins/monitoring-plugin/module.js new file mode 100644 index 000000000..6fe5881c2 --- /dev/null +++ b/electron/core/plugins/monitoring-plugin/module.js @@ -0,0 +1,25 @@ +const si = require("systeminformation"); + +const getResourcesInfo = async () => + new Promise(async (resolve) => { + const cpu = await si.cpu(); + const mem = await si.mem(); + const gpu = await si.graphics(); + const response = { + cpu, + mem, + gpu, + }; + resolve(response); + }); + +const getCurrentLoad = async () => + new Promise(async (resolve) => { + const currentLoad = await si.currentLoad(); + resolve(currentLoad); + }); + +module.exports = { + getResourcesInfo, + getCurrentLoad, +}; diff --git a/electron/core/plugins/monitoring-plugin/package.json b/electron/core/plugins/monitoring-plugin/package.json new file mode 100644 index 000000000..34d110ab5 --- /dev/null +++ b/electron/core/plugins/monitoring-plugin/package.json @@ -0,0 +1,32 @@ +{ + "name": "monitoring-plugin", + "version": "0.0.1", + "description": "", + "main": "dist/bundle.js", + "author": "Jan", + "license": "MIT", + "activationPoints": [ + "init" + ], + "scripts": { + "build": "webpack --config webpack.config.js", + "build:package": "rimraf ./*.tgz && npm run build && cpx \"module.js\" \"dist\" && npm pack", + "build:publish": "yarn build:package && cpx *.tgz ../../pre-install" + }, + "devDependencies": { + "rimraf": "^3.0.2", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4" + }, + "dependencies": { + "systeminformation": "^5.21.8" + }, + "bundledDependencies": [ + "systeminformation" + ], + "files": [ + "dist/*", + "package.json", + "README.md" + ] +} diff --git a/app/electron/core/base-plugin/webpack.config.js b/electron/core/plugins/monitoring-plugin/webpack.config.js similarity index 100% rename from app/electron/core/base-plugin/webpack.config.js rename to electron/core/plugins/monitoring-plugin/webpack.config.js diff --git a/models/.gitkeep b/electron/core/pre-install/.gitkeep similarity index 100% rename from models/.gitkeep rename to electron/core/pre-install/.gitkeep diff --git a/electron/icon.png b/electron/icon.png new file mode 100644 index 000000000..289f99ded Binary files /dev/null and b/electron/icon.png differ diff --git a/electron/main.ts b/electron/main.ts new file mode 100644 index 000000000..5419668a5 --- /dev/null +++ b/electron/main.ts @@ -0,0 +1,204 @@ +import { + app, + BrowserWindow, + screen as electronScreen, + ipcMain, + dialog, + shell, +} from "electron"; +import { readdirSync } from "fs"; +import { resolve, join, extname } from "path"; +import { unlink, createWriteStream } from "fs"; +import isDev = require("electron-is-dev"); +import { init } from "./core/plugin-manager/pluginMgr"; +const { autoUpdater } = require("electron-updater"); +// @ts-ignore +import request = require("request"); +// @ts-ignore +import progress = require("request-progress"); + +let mainWindow: BrowserWindow | undefined = undefined; + +autoUpdater.autoDownload = false; +autoUpdater.autoInstallOnAppQuit = true; + +const createMainWindow = () => { + mainWindow = new BrowserWindow({ + width: electronScreen.getPrimaryDisplay().workArea.width, + height: electronScreen.getPrimaryDisplay().workArea.height, + show: false, + backgroundColor: "white", + webPreferences: { + nodeIntegration: true, + preload: join(__dirname, "preload.js"), + }, + }); + + ipcMain.handle( + "invokePluginFunc", + async (event, modulePath, method, ...args) => { + const module = join(app.getPath("userData"), "plugins", modulePath); + return await import(/* webpackIgnore: true */ module) + .then((plugin) => { + if (typeof plugin[method] === "function") { + return plugin[method](...args); + } else { + console.log(plugin[method]); + console.error(`Function "${method}" does not exist in the module.`); + } + }) + .then((res) => { + return res; + }) + .catch((err) => console.log(err)); + } + ); + + const startURL = isDev + ? "http://localhost:3000" + : `file://${join(__dirname, "../renderer/index.html")}`; + + mainWindow.loadURL(startURL); + + mainWindow.once("ready-to-show", () => mainWindow?.show()); + mainWindow.on("closed", () => { + if (process.platform !== "darwin") app.quit(); + }); + + if (isDev) mainWindow.webContents.openDevTools(); +}; + +app.whenReady().then(() => { + createMainWindow(); + setupPlugins(); + autoUpdater.checkForUpdates(); + + ipcMain.handle("basePlugins", async (event) => { + const basePluginPath = join( + __dirname, + "../", + isDev ? "/core/pre-install" : "../app.asar.unpacked/core/pre-install" + ); + return readdirSync(basePluginPath) + .filter((file) => extname(file) === ".tgz") + .map((file) => join(basePluginPath, file)); + }); + + ipcMain.handle("pluginPath", async (event) => { + return join(app.getPath("userData"), "plugins"); + }); + ipcMain.handle("appVersion", async (event) => { + return app.getVersion(); + }); + ipcMain.handle("openExternalUrl", async (event, url) => { + shell.openExternal(url); + }); + + /** + * Used to delete a file from the user data folder + */ + ipcMain.handle("deleteFile", async (_event, filePath) => { + const userDataPath = app.getPath("userData"); + const fullPath = join(userDataPath, filePath); + + let result = "NULL"; + unlink(fullPath, function (err) { + if (err && err.code == "ENOENT") { + result = `File not exist: ${err}`; + } else if (err) { + result = `File delete error: ${err}`; + } else { + result = "File deleted successfully"; + } + console.log(`Delete file ${filePath} from ${fullPath} result: ${result}`); + }); + + return result; + }); + + /** + * Used to download a file from a given url + */ + ipcMain.handle("downloadFile", async (_event, url, fileName) => { + const userDataPath = app.getPath("userData"); + const destination = resolve(userDataPath, fileName); + + progress(request(url), {}) + .on("progress", function (state: any) { + mainWindow?.webContents.send("FILE_DOWNLOAD_UPDATE", { + ...state, + fileName, + }); + }) + .on("error", function (err: Error) { + mainWindow?.webContents.send("FILE_DOWNLOAD_ERROR", { + fileName, + err, + }); + }) + .on("end", function () { + mainWindow?.webContents.send("FILE_DOWNLOAD_COMPLETE", { + fileName, + }); + }) + .pipe(createWriteStream(destination)); + }); + + app.on("activate", () => { + if (!BrowserWindow.getAllWindows().length) { + createMainWindow(); + } + }); +}); + +/*New Update Available*/ +autoUpdater.on("update-available", async (info: any) => { + const action = await dialog.showMessageBox({ + message: `Update available. Do you want to download the latest update?`, + buttons: ["Download", "Later"], + }); + if (action.response === 0) await autoUpdater.downloadUpdate(); +}); + +/*App Update Completion Message*/ +autoUpdater.on("update-downloaded", async (info: any) => { + mainWindow?.webContents.send("APP_UPDATE_COMPLETE", {}); + const action = await dialog.showMessageBox({ + message: `Update downloaded. Please restart the application to apply the updates.`, + buttons: ["Restart", "Later"], + }); + if (action.response === 0) { + autoUpdater.quitAndInstall(); + } +}); + +/*App Update Error */ +autoUpdater.on("error", (info: any) => { + dialog.showMessageBox({ message: info.message }); + mainWindow?.webContents.send("APP_UPDATE_ERROR", {}); +}); + +/*App Update Progress */ +autoUpdater.on("download-progress", (progress: any) => { + console.log("app update progress: ", progress.percent); + mainWindow?.webContents.send("APP_UPDATE_PROGRESS", { + percent: progress.percent, + }); +}); + +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } +}); + +function setupPlugins() { + init({ + // Function to check from the main process that user wants to install a plugin + confirmInstall: async (plugins: string[]) => { + return true; + }, + // Path to install plugin to + pluginsPath: join(app.getPath("userData"), "plugins"), + }); +} diff --git a/electron/package.json b/electron/package.json new file mode 100644 index 000000000..abb8ac016 --- /dev/null +++ b/electron/package.json @@ -0,0 +1,55 @@ +{ + "name": "jan-electron", + "version": "0.1.1", + "main": "./build/main.js", + "author": "Jan", + "license": "MIT", + "homepage": "./", + "build": { + "appId": "jan.ai.app", + "productName": "Jan", + "files": [ + "renderer/**/*", + "build/*.{js,map}", + "build/core/plugin-manager/**/*", + "core/pre-install" + ], + "asarUnpack": [ + "core/pre-install" + ], + "publish": [ + { + "provider": "github", + "owner": "janhq", + "repo": "jan" + } + ], + "extends": null, + "mac": { + "type": "distribution" + } + }, + "scripts": { + "dev": "tsc -p . && electron .", + "build": "tsc -p . && electron-builder -p never -mw", + "build:publish": "tsc -p . && electron-builder -p onTagOrDraft -mw", + "postinstall": "electron-builder install-app-deps" + }, + "dependencies": { + "electron-is-dev": "^2.0.0", + "electron-updater": "^6.1.4", + "node-llama-cpp": "^2.4.1", + "pluggable-electron": "^0.6.0", + "request": "^2.88.2", + "request-progress": "^3.0.0" + }, + "devDependencies": { + "concurrently": "^8.2.1", + "electron": "26.2.1", + "electron-builder": "^24.6.4", + "wait-on": "^7.0.1" + }, + "installConfig": { + "hoistingLimits": "workspaces" + } +} diff --git a/electron/preload.ts b/electron/preload.ts new file mode 100644 index 000000000..18a9e78a0 --- /dev/null +++ b/electron/preload.ts @@ -0,0 +1,43 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +// Make Pluggable Electron's facade available to the renderer on window.plugins +//@ts-ignore +const useFacade = require("pluggable-electron/facade"); +useFacade(); +//@ts-ignore +const { contextBridge, ipcRenderer } = require("electron"); + +contextBridge.exposeInMainWorld("electronAPI", { + invokePluginFunc: (plugin: any, method: any, ...args: any[]) => + ipcRenderer.invoke("invokePluginFunc", plugin, method, ...args), + + basePlugins: () => ipcRenderer.invoke("basePlugins"), + + pluginPath: () => ipcRenderer.invoke("pluginPath"), + + appVersion: () => ipcRenderer.invoke("appVersion"), + + openExternalUrl: (url: string) => ipcRenderer.invoke("openExternalUrl", url), + + deleteFile: (filePath: string) => ipcRenderer.invoke("deleteFile", filePath), + + downloadFile: (url: string, path: string) => + ipcRenderer.invoke("downloadFile", url, path), + + onFileDownloadUpdate: (callback: any) => + ipcRenderer.on("FILE_DOWNLOAD_UPDATE", callback), + + onFileDownloadError: (callback: any) => + ipcRenderer.on("FILE_DOWNLOAD_ERROR", callback), + + onFileDownloadSuccess: (callback: any) => + ipcRenderer.on("FILE_DOWNLOAD_COMPLETE", callback), + + onAppUpdateDownloadUpdate: (callback: any) => + ipcRenderer.on("APP_UPDATE_PROGRESS", callback), + + onAppUpdateDownloadError: (callback: any) => + ipcRenderer.on("APP_UPDATE_ERROR", callback), + + onAppUpdateDownloadSuccess: (callback: any) => + ipcRenderer.on("APP_UPDATE_COMPLETE", callback), +}); diff --git a/electron/tsconfig.json b/electron/tsconfig.json new file mode 100644 index 000000000..675a6abec --- /dev/null +++ b/electron/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "sourceMap": true, + "strict": true, + "outDir": "./build", + "rootDir": "./", + "noEmitOnError": true, + "allowJs": true, + "typeRoots": ["node_modules/@types"] + }, + "exclude": ["core", "build", "node_modules"] +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..827d81d8a --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "jan-app", + "private": true, + "workspaces": { + "packages": [ + "electron", + "web" + ], + "nohoist": [ + "electron", + "electron/**", + "web", + "web/**" + ] + }, + "scripts": { + "dev:electron": "yarn workspace jan-electron dev", + "dev:web": "yarn workspace jan-web dev", + "dev": "concurrently --kill-others-on-fail \"yarn dev:web\" \"wait-on http://localhost:3000 && yarn dev:electron\"", + "build:web": "yarn workspace jan-web build && cpx \"web/out/**\" \"electron/renderer/\"", + "build:electron": "yarn workspace jan-electron build", + "build:plugins": "rm -f ./electron/core/pre-install/*.tgz && concurrently \"cd ./electron/core/plugins/data-plugin && npm install && npm run build:publish\" \"cd ./electron/core/plugins/inference-plugin && npm install && npm run build:publish\" \"cd ./electron/core/plugins/model-management-plugin && npm install && npm run build:publish\" \"cd ./electron/core/plugins/monitoring-plugin && npm install && npm run build:publish\"", + "build": "yarn build:web && yarn build:electron", + "build:publish": "yarn build:web && yarn workspace jan-electron build:publish" + }, + "devDependencies": { + "concurrently": "^8.2.1", + "cpx": "^1.5.0", + "wait-on": "^7.0.1" + }, + "version": "0.0.0" +} diff --git a/run.sh b/run.sh deleted file mode 100755 index 2856f8770..000000000 --- a/run.sh +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/bash -### Clean sub-processes on exit -trap "trap - SIGTERM && kill -- -$$" SIGINT - -MAX_STEPS=13 -progress() { - local BAR_SIZE="##########" - local MAX_BAR_SIZE="${#BAR_SIZE}" - local CLEAR_LINE="\\033[K" - spin[0]="-" - spin[1]="\\" - spin[2]="|" - spin[3]="/" - perc=$((($3 + 1) * 100 / MAX_STEPS)) - percBar=$((perc * MAX_BAR_SIZE / 100)) - - eval "$1" >/dev/null 2>error.log & - pid=$! - - echo -ne "\\r- [$3/$MAX_STEPS] [ ] $2 ...$CLEAR_LINE\\n" - while kill -0 $pid >/dev/null 2>&1; do - for i in "${spin[@]}"; do - echo -ne "\\r\\033[1A- [$3/$MAX_STEPS] [$i] $2 $CLEAR_LINE\\n" - sleep 0.1 - done - done - if [ -s "error.log" ] && [[ "$(cat error.log)" != "WARNING"* ]]; then - echo -ne "\\r\\033[1A- [$3/$MAX_STEPS] [x] $2\\n $(cat error.log)" - exit 1 - fi - echo -ne "\\r\\033[1A- [$3/$MAX_STEPS] [✔] $2 $CLEAR_LINE\\n" -} -step=1 - -mkdir -p models/ - -### macOS setup -if [[ "$OSTYPE" == "darwin"* ]]; then - MAX_STEPS=13 - if [[ ! -x "$(command -v brew)" ]]; then - progress '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' "Installing Homebrew" 1 - else - progress '' "Homebrew - Installed" $((step++)) - fi - - xcode-select -p &>/dev/null - if [ $? -ne 0 ]; then - progress 'xcode-select --install' "Installing Xcode Command Line Tools" $((step++)) - else - progress '' "Xcode Command Line Tools - Installed" $((step++)) - fi - - if [[ ! -x "$(command -v git)" ]]; then - progress 'brew install git' "Installing Git" $((step++)) - else - progress '' "Git - Installed" $((step++)) - fi - - if [[ ! -x "$(command -v wget)" ]]; then - progress 'brew install wget' "Installing Wget" $((step++)) - else - progress '' "Wget - Installed" $((step++)) - fi - - if [[ ! -x "$(command -v docker)" ]]; then - progress 'brew install --cask docker' "Installing Docker" $((step++)) - else - progress '' "Docker - Installed" $((step++)) - fi - - docker compose version &>/dev/null - if [ $? -ne 0 ] && [ ! -x "$(command -v docker-compose)" ]; then - progress 'brew install docker-compose' "Installing Docker Compose" $((step++)) - else - progress '' "docker-compose - Installed" $((step++)) - fi -fi -### - -### Debian setup -if [[ "$OSTYPE" == "linux"* ]]; then - MAX_STEPS=12 - progress "sudo apt update 2>/dev/null" "Apt Updating" $((step++)) - - if [[ ! -x "$(command -v git)" ]]; then - progress 'sudo apt install git' "Installing Git" $((step++)) - else - progress '' "Git - Installed" $((step++)) - fi - - if [[ ! -x "$(command -v wget)" ]]; then - progress 'sudo apt install wget' "Installing Wget" $((step++)) - else - progress '' "Wget - Installed" $((step++)) - fi - - if [[ ! -x "$(command -v docker)" ]]; then - progress '/bin/bash -c "$(curl -fsSL https://get.docker.com/) 2>/dev/null"' "Installing Docker" $((step++)) - else - progress '' "Docker - Installed" $((step++)) - fi - - docker compose version &>/dev/null - if [ $? -ne 0 ] && [ ! -x "$(command -v docker-compose)" ]; then - progress 'sudo apt install docker-compose' "Installing Docker Compose" $((step++)) - else - progress '' "docker-compose - Installed" $((step++)) - fi -fi -### - -### Pull Jan -if [ -d "jan" ]; then - cd jan - progress 'git pull 2>/dev/null' "Git pull" $((step++)) -else - progress 'git clone --quiet https://github.com/janhq/jan' "Git clone" $((step++)) - cd jan -fi - -progress 'git submodule update --init --recursive' "Pull submodule" $((step++)) -### - -### Prepare environment -progress 'cp -f sample.env .env' "Prepare .env file" $((step++)) -### - -### Download Model -if [ -f "/models/llama-2-7b.Q4_K_S.gguf" ]; then - progress '' "Llama model - Installed" $((step++)) -else - progress 'wget https://huggingface.co/TheBloke/Llama-2-7B-GGUF/resolve/main/llama-2-7b.Q4_K_S.gguf -P models' "Download Llama model" $((step++)) -fi -### - -### Launch Docker & Docker compose up -if [[ "$OSTYPE" == "darwin"* ]]; then - progress $' - if (! docker stats --no-stream 2>/dev/null ); then - open /Applications/Docker.app - while (! docker stats --no-stream 2>/dev/null ); do - sleep 0.3 - done - fi' "Waiting for docker to launch" $((step++)) -elif [[ "$OSTYPE" == "linux"* ]]; then - progress 'sudo service docker start 2>/dev/null' "Starting Docker Service" $((step++)) -fi - -docker compose version &>/dev/null -if [[ "$OSTYPE" == "darwin"* ]]; then - if [ $? == 0 ]; then - progress 'docker compose up -d --quiet-pull --remove-orphans 2>/dev/null' "Docker compose up" $((step++)) - elif [[ -x "$(command -v docker-compose)" ]]; then - progress 'docker-compose up -d --quiet-pull --remove-orphans 2>/dev/null' "Docker compose up" $((step++)) - fi -elif [[ "$OSTYPE" == "linux"* ]]; then - if [[ $? == 0 ]]; then - progress 'sudo docker compose up -d --quiet-pull --remove-orphans 2>/dev/null' "Docker compose up" $((step++)) - elif [[ -x "$(command -v docker-compose)" ]]; then - progress 'sudo docker-compose up -d --quiet-pull --remove-orphans 2>/dev/null' "Docker compose up" $((step++)) - fi -else - echo >&2 "Can not find docker compose runner" - exit 2 -fi - -### - -### Wait for service ready -progress $' - while (true); do - if curl -sL -w "%{http_code}\\n" "http://localhost:3000" -o /dev/null | grep -q "200"; then - break - fi -done -' "Waiting for service ready" $((step++)) -### - -echo -ne "\\r You can now view Jan app in the browser: http://localhost:3000 \\n" diff --git a/sample.env b/sample.env deleted file mode 100644 index ab897ce1a..000000000 --- a/sample.env +++ /dev/null @@ -1,8 +0,0 @@ -KEYCLOAK_VERSION=22.0.0 -KEYCLOAK_ADMIN=admin -KEYCLOAK_ADMIN_PASSWORD=admin - -# Inference -## LLM -LLM_MODEL_URL=https://huggingface.co/TheBloke/CodeLlama-13B-GGUF/resolve/main/codellama-13b.Q3_K_L.gguf -LLM_MODEL_FILE=llama-2-7b-chat.ggmlv3.q4_1.bin \ No newline at end of file diff --git a/app/.eslintrc.json b/web/.eslintrc.json similarity index 100% rename from app/.eslintrc.json rename to web/.eslintrc.json diff --git a/app/.gitignore b/web/.gitignore similarity index 100% rename from app/.gitignore rename to web/.gitignore diff --git a/app/Dockerfile b/web/Dockerfile similarity index 100% rename from app/Dockerfile rename to web/Dockerfile diff --git a/app/app/_components/AdvancedPrompt/index.tsx b/web/app/_components/AdvancedPrompt/index.tsx similarity index 100% rename from app/app/_components/AdvancedPrompt/index.tsx rename to web/app/_components/AdvancedPrompt/index.tsx diff --git a/app/app/_components/AdvancedPromptGenerationParams/index.tsx b/web/app/_components/AdvancedPromptGenerationParams/index.tsx similarity index 100% rename from app/app/_components/AdvancedPromptGenerationParams/index.tsx rename to web/app/_components/AdvancedPromptGenerationParams/index.tsx diff --git a/app/app/_components/AdvancedPromptImageUpload/index.tsx b/web/app/_components/AdvancedPromptImageUpload/index.tsx similarity index 100% rename from app/app/_components/AdvancedPromptImageUpload/index.tsx rename to web/app/_components/AdvancedPromptImageUpload/index.tsx diff --git a/app/app/_components/AdvancedPromptResolution/index.tsx b/web/app/_components/AdvancedPromptResolution/index.tsx similarity index 100% rename from app/app/_components/AdvancedPromptResolution/index.tsx rename to web/app/_components/AdvancedPromptResolution/index.tsx diff --git a/app/app/_components/AdvancedPromptText/index.tsx b/web/app/_components/AdvancedPromptText/index.tsx similarity index 100% rename from app/app/_components/AdvancedPromptText/index.tsx rename to web/app/_components/AdvancedPromptText/index.tsx diff --git a/app/app/_components/AdvancedTextArea/index.tsx b/web/app/_components/AdvancedTextArea/index.tsx similarity index 100% rename from app/app/_components/AdvancedTextArea/index.tsx rename to web/app/_components/AdvancedTextArea/index.tsx diff --git a/app/app/_components/AiSearch/index.tsx b/web/app/_components/AiSearch/index.tsx similarity index 100% rename from app/app/_components/AiSearch/index.tsx rename to web/app/_components/AiSearch/index.tsx diff --git a/app/app/_components/AiTypeCard/index.tsx b/web/app/_components/AiTypeCard/index.tsx similarity index 100% rename from app/app/_components/AiTypeCard/index.tsx rename to web/app/_components/AiTypeCard/index.tsx diff --git a/app/app/_components/ApiStep/index.tsx b/web/app/_components/ApiStep/index.tsx similarity index 100% rename from app/app/_components/ApiStep/index.tsx rename to web/app/_components/ApiStep/index.tsx diff --git a/web/app/_components/AvailableModelCard/index.tsx b/web/app/_components/AvailableModelCard/index.tsx new file mode 100644 index 000000000..64fc0f979 --- /dev/null +++ b/web/app/_components/AvailableModelCard/index.tsx @@ -0,0 +1,69 @@ +import { Product } from "@/_models/Product"; +import DownloadModelContent from "../DownloadModelContent"; +import ModelDownloadButton from "../ModelDownloadButton"; +import ModelDownloadingButton from "../ModelDownloadingButton"; +import ViewModelDetailButton from "../ViewModelDetailButton"; +import { useAtomValue } from "jotai"; +import { modelDownloadStateAtom } from "@/_helpers/JotaiWrapper"; + +type Props = { + product: Product; + isRecommend: boolean; + required?: string; + onDownloadClick?: (product: Product) => void; +}; + +const AvailableModelCard: React.FC = ({ + product, + isRecommend, + required, + onDownloadClick, +}) => { + const downloadState = useAtomValue(modelDownloadStateAtom); + + let isDownloading = false; + let total = 0; + let transferred = 0; + + if (product.fileName && downloadState[product.fileName]) { + isDownloading = + downloadState[product.fileName].error == null && + downloadState[product.fileName].percent < 1; + + if (isDownloading) { + total = downloadState[product.fileName].size.total; + transferred = downloadState[product.fileName].size.transferred; + } + } + + const handleViewDetails = () => {}; + + const downloadButton = isDownloading ? ( +
+ +
+ ) : ( +
+ onDownloadClick?.(product)} /> +
+ ); + + return ( +
+
+ + {downloadButton} +
+ {/* */} +
+ ); +}; + +export default AvailableModelCard; diff --git a/app/app/_components/BasicPromptAccessories/index.tsx b/web/app/_components/BasicPromptAccessories/index.tsx similarity index 100% rename from app/app/_components/BasicPromptAccessories/index.tsx rename to web/app/_components/BasicPromptAccessories/index.tsx diff --git a/app/app/_components/BasicPromptButton/index.tsx b/web/app/_components/BasicPromptButton/index.tsx similarity index 100% rename from app/app/_components/BasicPromptButton/index.tsx rename to web/app/_components/BasicPromptButton/index.tsx diff --git a/app/app/_components/BasicPromptInput/index.tsx b/web/app/_components/BasicPromptInput/index.tsx similarity index 100% rename from app/app/_components/BasicPromptInput/index.tsx rename to web/app/_components/BasicPromptInput/index.tsx diff --git a/app/app/_components/ButtonSlider/index.tsx b/web/app/_components/ButtonSlider/index.tsx similarity index 100% rename from app/app/_components/ButtonSlider/index.tsx rename to web/app/_components/ButtonSlider/index.tsx diff --git a/app/app/_components/ChangeTheme/index.tsx b/web/app/_components/ChangeTheme/index.tsx similarity index 100% rename from app/app/_components/ChangeTheme/index.tsx rename to web/app/_components/ChangeTheme/index.tsx diff --git a/app/app/_components/ChatBody/index.tsx b/web/app/_components/ChatBody/index.tsx similarity index 100% rename from app/app/_components/ChatBody/index.tsx rename to web/app/_components/ChatBody/index.tsx diff --git a/app/app/_components/ChatBody/renderChatMessage.tsx b/web/app/_components/ChatBody/renderChatMessage.tsx similarity index 100% rename from app/app/_components/ChatBody/renderChatMessage.tsx rename to web/app/_components/ChatBody/renderChatMessage.tsx diff --git a/web/app/_components/ChatContainer/index.tsx b/web/app/_components/ChatContainer/index.tsx new file mode 100644 index 000000000..46e740f90 --- /dev/null +++ b/web/app/_components/ChatContainer/index.tsx @@ -0,0 +1,29 @@ +"use client"; + +import { useAtomValue } from "jotai"; +import { MainViewState, getMainViewStateAtom } from "@/_helpers/JotaiWrapper"; +import { ReactNode } from "react"; +import ModelManagement from "../ModelManagement"; +import Welcome from "../WelcomeContainer"; +import { Preferences } from "../Preferences"; + +type Props = { + children: ReactNode; +}; + +export default function ChatContainer({ children }: Props) { + const viewState = useAtomValue(getMainViewStateAtom); + + switch (viewState) { + case MainViewState.ExploreModel: + return ; + case MainViewState.Setting: + return ; + case MainViewState.ResourceMonitor: + case MainViewState.MyModel: + case MainViewState.Welcome: + return ; + default: + return
{children}
; + } +} diff --git a/app/app/_components/ChatItem/index.tsx b/web/app/_components/ChatItem/index.tsx similarity index 100% rename from app/app/_components/ChatItem/index.tsx rename to web/app/_components/ChatItem/index.tsx diff --git a/app/app/_components/CompactHistoryItem/index.tsx b/web/app/_components/CompactHistoryItem/index.tsx similarity index 100% rename from app/app/_components/CompactHistoryItem/index.tsx rename to web/app/_components/CompactHistoryItem/index.tsx diff --git a/app/app/_components/CompactHistoryList/index.tsx b/web/app/_components/CompactHistoryList/index.tsx similarity index 100% rename from app/app/_components/CompactHistoryList/index.tsx rename to web/app/_components/CompactHistoryList/index.tsx diff --git a/app/app/_components/CompactLogo/index.tsx b/web/app/_components/CompactLogo/index.tsx similarity index 100% rename from app/app/_components/CompactLogo/index.tsx rename to web/app/_components/CompactLogo/index.tsx diff --git a/app/app/_components/CompactSideBar/index.tsx b/web/app/_components/CompactSideBar/index.tsx similarity index 100% rename from app/app/_components/CompactSideBar/index.tsx rename to web/app/_components/CompactSideBar/index.tsx diff --git a/app/app/_components/ConfirmDeleteConversationModal/index.tsx b/web/app/_components/ConfirmDeleteConversationModal/index.tsx similarity index 100% rename from app/app/_components/ConfirmDeleteConversationModal/index.tsx rename to web/app/_components/ConfirmDeleteConversationModal/index.tsx diff --git a/app/app/_components/ConfirmDeleteModelModal/index.tsx b/web/app/_components/ConfirmDeleteModelModal/index.tsx similarity index 100% rename from app/app/_components/ConfirmDeleteModelModal/index.tsx rename to web/app/_components/ConfirmDeleteModelModal/index.tsx diff --git a/app/app/_components/ConfirmSignOutModal/index.tsx b/web/app/_components/ConfirmSignOutModal/index.tsx similarity index 100% rename from app/app/_components/ConfirmSignOutModal/index.tsx rename to web/app/_components/ConfirmSignOutModal/index.tsx diff --git a/app/app/_components/ConversationalCard/index.tsx b/web/app/_components/ConversationalCard/index.tsx similarity index 95% rename from app/app/_components/ConversationalCard/index.tsx rename to web/app/_components/ConversationalCard/index.tsx index 7a93b2057..5be2142cf 100644 --- a/app/app/_components/ConversationalCard/index.tsx +++ b/web/app/_components/ConversationalCard/index.tsx @@ -14,9 +14,7 @@ const ConversationalCard: React.FC = ({ product }) => { return ( +
+
+ {/* */} + + ); +}; + +export default DownloadedModelCard; diff --git a/app/app/_components/DropdownList/index.tsx b/web/app/_components/DropdownList/index.tsx similarity index 100% rename from app/app/_components/DropdownList/index.tsx rename to web/app/_components/DropdownList/index.tsx diff --git a/app/app/_components/ExpandableHeader/index.tsx b/web/app/_components/ExpandableHeader/index.tsx similarity index 100% rename from app/app/_components/ExpandableHeader/index.tsx rename to web/app/_components/ExpandableHeader/index.tsx diff --git a/app/app/_components/Footer/index.tsx b/web/app/_components/Footer/index.tsx similarity index 100% rename from app/app/_components/Footer/index.tsx rename to web/app/_components/Footer/index.tsx diff --git a/app/app/_components/GenerateImageCard/index.tsx b/web/app/_components/GenerateImageCard/index.tsx similarity index 94% rename from app/app/_components/GenerateImageCard/index.tsx rename to web/app/_components/GenerateImageCard/index.tsx index 75eb0dbbe..601a15d7e 100644 --- a/app/app/_components/GenerateImageCard/index.tsx +++ b/web/app/_components/GenerateImageCard/index.tsx @@ -11,7 +11,7 @@ const GenerateImageCard: React.FC = ({ product }) => { return (